fiqus 2025.11.0__py3-none-any.whl → 2025.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. fiqus/MainFiQuS.py +6 -0
  2. fiqus/data/DataConductor.py +9 -1
  3. fiqus/data/DataFiQuS.py +3 -3
  4. fiqus/data/DataFiQuSConductorAC_Rutherford.py +569 -0
  5. fiqus/data/DataFiQuSHomogenizedConductor.py +478 -0
  6. fiqus/geom_generators/GeometryConductorAC_Rutherford.py +706 -0
  7. fiqus/geom_generators/GeometryConductorAC_Strand_RutherfordCopy.py +1848 -0
  8. fiqus/geom_generators/GeometryHomogenizedConductor.py +183 -0
  9. fiqus/getdp_runners/RunGetdpConductorAC_Rutherford.py +200 -0
  10. fiqus/getdp_runners/RunGetdpHomogenizedConductor.py +178 -0
  11. fiqus/mains/MainConductorAC_Rutherford.py +76 -0
  12. fiqus/mains/MainHomogenizedConductor.py +112 -0
  13. fiqus/mesh_generators/MeshConductorAC_Rutherford.py +235 -0
  14. fiqus/mesh_generators/MeshConductorAC_Strand_RutherfordCopy.py +718 -0
  15. fiqus/mesh_generators/MeshHomogenizedConductor.py +229 -0
  16. fiqus/post_processors/PostProcessAC_Rutherford.py +142 -0
  17. fiqus/post_processors/PostProcessHomogenizedConductor.py +114 -0
  18. fiqus/pro_templates/combined/ConductorACRutherford_template.pro +1742 -0
  19. fiqus/pro_templates/combined/HomogenizedConductor_template.pro +1663 -0
  20. {fiqus-2025.11.0.dist-info → fiqus-2025.12.0.dist-info}/METADATA +6 -5
  21. {fiqus-2025.11.0.dist-info → fiqus-2025.12.0.dist-info}/RECORD +27 -11
  22. tests/test_geometry_generators.py +20 -0
  23. tests/test_mesh_generators.py +38 -0
  24. tests/test_solvers.py +100 -0
  25. {fiqus-2025.11.0.dist-info → fiqus-2025.12.0.dist-info}/LICENSE.txt +0 -0
  26. {fiqus-2025.11.0.dist-info → fiqus-2025.12.0.dist-info}/WHEEL +0 -0
  27. {fiqus-2025.11.0.dist-info → fiqus-2025.12.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1663 @@
1
+ Group {
2
+ // ------- PROBLEM DEFINITION -------
3
+ // Cables
4
+ Cables = Region[ {<<rm.powered.Cables.vol.numbers|join(', ')>>} ];
5
+ BndCables = Region[ {<<rm.powered.Cables.surf.numbers|join(', ')>>} ];
6
+ ArbitraryPointsCables = Region[ {<<rm.powered.Cables.curve.numbers|join(', ')>>} ];
7
+
8
+ // Individual regions for the cables
9
+ {% for i in range(0, len(rm.powered.Cables.vol.numbers)) %}
10
+ Cable_<<i+1>> = Region[ {<<rm.powered.Cables.vol.numbers[i]>>} ];
11
+ CableBnd_<<i+1>> = Region[ {<<rm.powered.Cables.surf.numbers[i]>>} ];
12
+ {% endfor %}
13
+
14
+ Air = Region[ {<<rm.air.vol.number>>} ];
15
+ BndAir = Region[ {<<rm.air.surf.number>>} ];
16
+ ArbitraryPointsAir = Region[ {<<rm.air.point.numbers|join(', ')>>} ];
17
+
18
+ Coils = Region[ {<<rm.powered.ExcitationCoils.vol.numbers|join(', ')>>} ];
19
+ BndCoils = Region[ {<<rm.powered.ExcitationCoils.surf.numbers|join(', ')>>} ];
20
+ {% for i in range(0, len(rm.powered.ExcitationCoils.vol.numbers)) %}
21
+ Coil_<<i+1>> = Region[ {<<rm.powered.ExcitationCoils.vol.numbers[i]>>} ];
22
+ CoilBnd_<<i+1>> = Region[ {<<rm.powered.ExcitationCoils.surf.numbers[i]>>} ];
23
+ {% endfor %}
24
+
25
+ // Cuts
26
+ CableCuts = Region[ {<<rm.powered.Cables.cochain.numbers|join(', ')>>} ];
27
+ CoilCuts = Region[ {<<rm.powered.ExcitationCoils.cochain.numbers|join(', ')>>} ];
28
+ Cuts = Region[ {CableCuts, CoilCuts} ]; // All the cuts
29
+ // Individual cuts for the cables
30
+ {% for i in range(0, len(rm.powered.Cables.cochain.numbers)) %}
31
+ CableCut_<<i+1>> = Region[ {<<rm.powered.Cables.cochain.numbers[i]>>} ];
32
+ {% endfor %}
33
+ // Individual cuts for the coils
34
+ {% for i in range(0, len(rm.powered.ExcitationCoils.cochain.numbers)) %}
35
+ CoilCut_<<i+1>> = Region[ {<<rm.powered.ExcitationCoils.cochain.numbers[i]>>} ];
36
+ {% endfor %}
37
+
38
+ // Gauge points - only air region
39
+ ArbitraryPoints = Region[ {ArbitraryPointsAir} ];
40
+ // Domain definitions
41
+ OmegaCC = Region[ {Air, Coils} ];
42
+ OmegaC = Region[ {Cables} ];
43
+ Omega = Region[ {OmegaC, OmegaCC} ];
44
+ BndOmegaC = Region[ {BndCables} ];
45
+ BndOmega_ha = Region[ {BndOmegaC} ];
46
+ // useful for function space definition
47
+ Omega_AndBnd = Region[ {Omega, BndAir} ];
48
+ OmegaC_AndBnd = Region[ {OmegaC, BndOmegaC} ];
49
+ OmegaCC_AndBnd = Region[ {OmegaCC, BndOmegaC, BndAir} ];
50
+
51
+ // Hysteresis regions
52
+ {% if dm.magnet.solve.rohm.enable or dm.magnet.solve.rohf.enable %}
53
+ MagnLinDomain = Region[ {Air, Coils} ];
54
+ MagnHystDomain = Region[ {Cables} ];
55
+ {% else %}
56
+ MagnLinDomain = Region[ {Air, Coils, Cables} ];
57
+ MagnHystDomain = Region[ {} ];
58
+ {% endif %}
59
+
60
+ // Formulation definitions
61
+ {% if dm.magnet.solve.formulation_parameters.hphia %}
62
+ Omega_h_OmegaCC_AndBnd = Region[ {BndOmegaC} ];
63
+ Omega_h_AndBnd = Region[ {OmegaC, BndOmegaC} ];
64
+ Omega_a_AndBnd = Region[ {OmegaCC, BndOmegaC, BndAir} ];
65
+ Omega_a = Region[ {OmegaCC} ];
66
+ {% else %}
67
+ Omega_h_OmegaCC_AndBnd = Region[ {OmegaCC, BndOmegaC, BndAir} ];
68
+ Omega_h_AndBnd = Region[ {Omega, BndAir} ];
69
+ Omega_a_AndBnd = Region[ {} ];
70
+ Omega_a = Region[ {} ];
71
+ {% endif %}
72
+
73
+ Gamma_h = Region[ {BndAir} ];
74
+ Gamma_e = Region[ {} ];
75
+ GammaAll = Region[ {Gamma_h, Gamma_e} ];
76
+
77
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
78
+ // Regions for electrical circuit for transport current and voltage
79
+ CurrentSource = Region[ {10000000} ];
80
+ PoweringCircuit = Region[ {CurrentSource} ]; // Groups containg all circuit elements for the transport current
81
+ ParallelResistor = Region[ {10000001} ];
82
+ PoweringCircuit += Region[ {ParallelResistor} ];
83
+ {% endif %}
84
+ }
85
+
86
+ Function{
87
+ // ------- GEOMETRY PARAMETERS -------
88
+ N_cables = <<len(rm.powered.Cables.vol.numbers)>>;
89
+ // Mixed formulation normal vector orientation
90
+ normal_sign = 1; // could be -1 depending on how the geometry is built
91
+
92
+ // ------------ DISCC MODEL PARAMETERS ------------
93
+ // TO DO: generalize if several cables don't share the same properties
94
+ // Independent inputs
95
+ gamma_c = <<dm.magnet.solve.discc.gamma_c>>;
96
+ gamma_a = <<dm.magnet.solve.discc.gamma_a>>;
97
+ lambda_a = <<dm.magnet.solve.discc.lambda_a>>;
98
+ Rc = <<dm.magnet.solve.discc.crossing_coupling_resistance>>;
99
+ Ra = <<dm.magnet.solve.discc.adjacent_coupling_resistance>>;
100
+ pitch_length = <<dm.magnet.solve.general_parameters.strand_transposition_length>>;
101
+ n_strands = <<dm.magnet.solve.general_parameters.n_strands>>;
102
+ strand_filling_factor = <<dm.magnet.solve.general_parameters.strand_filling_factor>>;
103
+ cable_height = <<dm.magnet.geometry.cables_definition[0].height>>;
104
+ cable_width = <<dm.magnet.geometry.cables_definition[0].width>>;
105
+ // Equivalent conductivity tensor for the IS coupling current density field in DISCC
106
+ strand_surf = strand_filling_factor * cable_width * cable_height / n_strands; // function of the cable size, number of strands and filling factor
107
+ ref_periodicity_length = pitch_length/n_strands; // just for the definition of the contact resistivity based on the contact resistances
108
+ rc = Rc * ref_periodicity_length * cable_width*2/n_strands * 0.5; // Ohm.m2, multiplication by 0.5 because the shape is a rhombus and not a rectangle
109
+ ra = Ra * ref_periodicity_length * cable_height/2; // Ohm.m2
110
+ common_mult = 2*pitch_length*pitch_length/(strand_filling_factor*cable_width*cable_width*cable_height); // (-)
111
+ sigma_IS_xx = gamma_a * common_mult * (1/ra);
112
+ sigma_IS_yy_crossing = gamma_c * common_mult * (1/rc);
113
+ sigma_IS_yy_adjacent = lambda_a * common_mult * (1/ra);
114
+ sigma_IS_yy = sigma_IS_yy_crossing + sigma_IS_yy_adjacent;
115
+ sigma_IS[] = TensorDiag[sigma_IS_xx, sigma_IS_yy, 1];
116
+ // Current grading factor
117
+ ks_factor = 0.0;
118
+ alpha_ks[] = 1 /(1 - ks_factor * 2 * X[] / cable_width); // TO DO: generalize (like this, it requires specific cable position and orientation)
119
+
120
+ // ------- MATERIAL PARAMETERS - MAGNETIC -------
121
+ mu0 = Pi*4e-7; // [H/m]
122
+ nu0 = 1.0/mu0; // [m/H]
123
+ mu[Air] = mu0;
124
+ nu[Air] = nu0;
125
+ mu[Coils] = mu0;
126
+ nu[Coils] = nu0;
127
+
128
+ // ------- MATERIAL PARAMETERS - ELECTRIC -------
129
+ // TO DO:
130
+ // - include b-dependence
131
+ // - include T-dependence
132
+ // Current sharing inputs
133
+ strand_ic = <<dm.magnet.solve.current_sharing.superconductor_Ic>>;
134
+ n = <<dm.magnet.solve.current_sharing.superconductor_n_value>>; // [-] power law index, one key parameter for the power law
135
+ ec = 1e-4;
136
+ jc_scaled[] = strand_ic / strand_surf * strand_filling_factor; // strand_filling_factor
137
+ rho_matrix_scaled[] = <<dm.magnet.solve.current_sharing.matrix_resistance>> * strand_surf/strand_filling_factor; // scaled resistivity
138
+ // Current sharing functions
139
+ e_joule[] = CS_e_joule[$1, rho_matrix_scaled[], jc_scaled[], n]{ec};
140
+ dedj_joule[] = CS_de_joule_dj[$1, rho_matrix_scaled[], jc_scaled[], n]{ec};
141
+
142
+ // Resistivity for linear case (if we don't model the power law with current sharing) - used for debugging only
143
+ rho[Cables] = <<dm.magnet.solve.general_parameters.rho_cables>>;
144
+
145
+ {% if dm.magnet.solve.rohm.enable %}
146
+ // ------- ROHM ------
147
+ // TO DO:
148
+ // - include I-dependence
149
+ // - include T-dependence
150
+ // ROHM Model for cables - cell parameters from csv
151
+ N_rohm = <<len(mp.rohm['alpha'])>>;
152
+ weight_sc = strand_filling_factor; // strand filling factor
153
+ tau_sc = <<dm.magnet.solve.rohm.tau_scaling>>;
154
+ {% for i in range(1, 1+len(mp.rohm['alpha'])) %}
155
+
156
+ {% if i == 1 %}
157
+ w_rohm_<<i>> = <<mp.rohm['alpha'][i]>> * weight_sc; // + (1 - weight_sc); // first cell already contains eddy, such must not be scaled up. Instead, we add a linear contribution directly to the b(h) function
158
+ {% else %}
159
+ w_rohm_<<i>> = <<mp.rohm['alpha'][i]>> * weight_sc;
160
+ {% endif %}
161
+ kappa_rohm_<<i>> = <<mp.rohm['kappa'][i]>>;
162
+ tau_e_rohm_<<i>> = <<mp.rohm['tau_e'][i]>> * tau_sc;
163
+ tau_c_rohm_<<i>> = <<mp.rohm['tau_c'][i]>> * tau_sc;
164
+ chi_rohm_<<i>> = <<mp.rohm['chi'][i]>>;
165
+ {% endfor %}
166
+
167
+ // Multiplier for the field-dependent irreversibilty parameter
168
+ list_f_kappa = {0.00000000e+00, 1.00000000e+00, 9.39597315e-02, 9.70532886e-01,
169
+ 1.87919463e-01, 9.08385278e-01, 2.81879195e-01, 8.25986815e-01,
170
+ 3.75838926e-01, 7.38862115e-01, 4.69798658e-01, 6.63868696e-01,
171
+ 5.63758389e-01, 6.07033231e-01, 6.57718121e-01, 5.62773567e-01,
172
+ 7.51677852e-01, 5.26772394e-01, 8.45637584e-01, 4.96552160e-01,
173
+ 9.39597315e-01, 4.70616295e-01, 1.03355705e+00, 4.47956409e-01,
174
+ 1.12751678e+00, 4.27859492e-01, 1.22147651e+00, 4.09816324e-01,
175
+ 1.31543624e+00, 3.93747334e-01, 1.40939597e+00, 3.79298723e-01,
176
+ 1.50335570e+00, 3.66109142e-01, 1.59731544e+00, 3.53990385e-01,
177
+ 1.69127517e+00, 3.42796324e-01, 1.78523490e+00, 3.32399089e-01,
178
+ 1.87919463e+00, 3.22699151e-01, 1.97315436e+00, 3.13616338e-01,
179
+ 2.06711409e+00, 3.05079435e-01, 2.16107383e+00, 2.97028765e-01,
180
+ 2.25503356e+00, 2.89415278e-01, 2.34899329e+00, 2.82196893e-01,
181
+ 2.44295302e+00, 2.75334654e-01, 2.53691275e+00, 2.68796409e-01,
182
+ 2.63087248e+00, 2.62555621e-01, 2.72483221e+00, 2.56585778e-01,
183
+ 2.81879195e+00, 2.50864851e-01, 2.91275168e+00, 2.45374155e-01,
184
+ 3.00671141e+00, 2.40096149e-01, 3.10067114e+00, 2.35014644e-01,
185
+ 3.19463087e+00, 2.30115890e-01, 3.28859060e+00, 2.25388074e-01,
186
+ 3.38255034e+00, 2.20818839e-01, 3.47651007e+00, 2.16397919e-01,
187
+ 3.57046980e+00, 2.12116612e-01, 3.66442953e+00, 2.07965874e-01,
188
+ 3.75838926e+00, 2.03937695e-01, 3.85234899e+00, 2.00025201e-01,
189
+ 3.94630872e+00, 1.96221977e-01, 4.04026846e+00, 1.92521514e-01,
190
+ 1.07114094e+01, 4.22119189e-02, 1.08053691e+01, 4.07794262e-02,
191
+ 1.08993289e+01, 3.93539509e-02, 1.09932886e+01, 3.79351159e-02,
192
+ 1.10872483e+01, 3.65225668e-02, 1.11812081e+01, 3.51159648e-02,
193
+ 1.12751678e+01, 3.37149413e-02, 1.13691275e+01, 3.23190965e-02,
194
+ 1.14630872e+01, 3.09280383e-02, 1.15570470e+01, 2.95413741e-02,
195
+ 1.16510067e+01, 2.81586397e-02, 1.17449664e+01, 2.67793730e-02,
196
+ 1.18389262e+01, 2.54030907e-02, 1.19328859e+01, 2.40292464e-02,
197
+ 1.20268456e+01, 2.26572523e-02, 1.21208054e+01, 2.12864688e-02,
198
+ 1.22147651e+01, 1.99161765e-02, 1.23087248e+01, 1.85455626e-02,
199
+ 1.24026846e+01, 1.71737023e-02, 1.24966443e+01, 1.57994954e-02,
200
+ 1.25906040e+01, 1.44216598e-02, 1.26845638e+01, 1.30386263e-02,
201
+ 1.27785235e+01, 1.16483848e-02, 1.28724832e+01, 1.02483184e-02,
202
+ 1.29664430e+01, 8.83483853e-03, 1.30604027e+01, 7.40244796e-03,
203
+ 1.31543624e+01, 5.94103353e-03, 1.32483221e+01, 4.45222537e-03,
204
+ 1.33422819e+01, 3.13219576e-03, 1.34362416e+01, 2.03642832e-03,
205
+ 1.35302013e+01, 1.16778951e-03, 1.36241611e+01, 5.31251257e-04,
206
+ 1.37181208e+01, 1.36044320e-04, 1.38120805e+01, 5.43279830e-07,
207
+ 1.39060403e+01, 0.00000000e+00, 1.40000000e+01, 0.00000000e+00};
208
+ // Field-dependent parameters
209
+ f_kappa[] = InterpolationLinear[$1]{List[list_f_kappa]};
210
+ f_chi[] = (1 - $1/14)/(1 + $1/5);
211
+ // f_kappa[] = (1 - $1/13)/(1 + $1/3); // TO DO: refine this scaling and introduce dependence on transport current
212
+ // f_chi[] = (1 - $1/13)/(1 + $1/6); // TO DO: idem
213
+
214
+ /* --- Functions for one cell only
215
+ Function for reversible field only, for one cell
216
+ $1: new field
217
+ $2: reversible field at previous time step
218
+ $3: rev+eddy+coupling field at previous time step
219
+ $4: w_k, weight for the considered cell k
220
+ $5: kappa_k, uncoupled irreversibility parameter for the considered cell k
221
+ $6: chi_k, coupled (minus uncoupled) irreversibility parameter for the considered cell k
222
+ $7: tau_c_k, coupling current time constant for the considered cell k
223
+ $8: tau_e_k, eddy current time constant for the considered cell k
224
+ */
225
+ hrev_k[] = ROHM_hRev[$1, $2, $3, $4, $5, $6, $7, $8, $DTime];
226
+
227
+ /* Function for rev+eddy+coupling field, for one cell
228
+ $1: new field
229
+ $2: reversible field at previous time step
230
+ $3: rev+eddy+coupling field at previous time step
231
+ $4: irreversibility parameter for the considered cell k
232
+ */
233
+ g_k[] = ROHM_g[$1, $2, $3, $4];
234
+ // Derivative of the reversible field, for one cell
235
+ // Same parameters as the function for the reversible field $1 -> $8
236
+ dhrev_k[] = ROHM_dhRev_dH[$1, $2, $3, $4, $5, $6, $7, $8, $DTime];
237
+
238
+ /* Coupling field from time derivative of flux density b_k
239
+ $1: \dot b_k
240
+ $2: norm of b
241
+ $3: tau_c_k
242
+ $4: chi_k
243
+ */
244
+ hcoupling[] = ROHM_hCoupling[$1, f_chi[$2], $3, $4];
245
+
246
+ /* --- Main hysteresis law
247
+ $1: new field
248
+ $2*k: reversible field at previous time step for cell k
249
+ $2*k+1: g = rev+eddy+coupling field at previous time step for cell k
250
+ $2*N+2: norm of b, for field-dependent parameters
251
+ */
252
+ bhyst[] = ROHM_bHyst[$1, <<len(mp.rohm['alpha'])>>,
253
+ {% for i in range(1, 1+len(mp.rohm['alpha'])) %} $<<i*2>>, $<<i*2+1>>, w_rohm_<<i>>, f_kappa[$<<2*len(mp.rohm['alpha'])+2>>]*kappa_rohm_<<i>>, f_chi[$<<2*len(mp.rohm['alpha'])+2>>]*chi_rohm_<<i>>, tau_c_rohm_<<i>>, tau_e_rohm_<<i>>, {% endfor %} $DTime, weight_sc];
254
+
255
+ // Derivative w.r.t. new field
256
+ dbhystdh[] = ROHM_dbHyst_dH[$1, <<len(mp.rohm['alpha'])>>,
257
+ {% for i in range(1, 1+len(mp.rohm['alpha'])) %} $<<i*2>>, $<<i*2+1>>, w_rohm_<<i>>, f_kappa[$<<2*len(mp.rohm['alpha'])+2>>]*kappa_rohm_<<i>>, f_chi[$<<2*len(mp.rohm['alpha'])+2>>]*chi_rohm_<<i>>, tau_c_rohm_<<i>>, tau_e_rohm_<<i>>, {% endfor %} $DTime, weight_sc];
258
+
259
+ {% else %}
260
+ // Non-hysteretic material (no ROHM model)
261
+ mu[Cables] = mu0;
262
+ nu[Cables] = nu0;
263
+ {% endif %}
264
+
265
+ {% if dm.magnet.solve.rohf.enable %}
266
+ // ------- ROHF ------
267
+ // TO DO:
268
+ // - include b-dependence
269
+ // - include T-dependence
270
+ Lint0 = (mu0 / (4*Pi)) * strand_surf / strand_filling_factor;
271
+ N_rohf = <<len(mp.rohf['alpha'])>>;
272
+ {% for i in range(1, 1+len(mp.rohf['alpha'])) %}
273
+
274
+ w_rohf_<<i>> = <<mp.rohf['alpha'][i]>>;
275
+ kappa_rohf_<<i>> = <<mp.rohf['kappa'][i]>> * strand_filling_factor / strand_surf;
276
+ tau_e_rohf_<<i>> = <<mp.rohf['tau_e'][i]>>;
277
+ {% endfor %}
278
+
279
+ /* --- Test for a hysteresis element: gives the reversible current density in the static case
280
+ $1: new current density
281
+ $2: previous reversible + eddy current density
282
+ $3: irreversibility parameter
283
+ */
284
+ /* --- Reversible current density per element
285
+ $1: new current density
286
+ $2: previous reversible current density
287
+ $2: previous reversible + eddy current density
288
+ $3: irreversibility parameter
289
+ $4: eddy time constant
290
+ */
291
+ jrev_k[] = ROHF_jrev[$1, $2, $3, $4, $5, $DTime];
292
+ jreveddy_k[] = ROHF_jreveddy[$1, $2, $3];
293
+
294
+ /* --- Main hysteresis law
295
+ $1: new current density
296
+ $(2*k): previous reversible current densities
297
+ $(2*k+1: previous reversible + eddy current densities
298
+ */
299
+ fluxdens[] = ROHF_fluxDensity[Lint0, $1, $DTime, <<len(mp.rohf['alpha'])>>,
300
+ {% for i in range(1, 1+len(mp.rohf['alpha'])) %} w_rohf_<<i>>, $<<2*i>>, $<<2*i+1>>,
301
+ kappa_rohf_<<i>>, tau_e_rohf_<<i>>{% if not loop.last %}, {% endif %}
302
+ {% endfor %}
303
+ ];
304
+
305
+ dfluxdensdj[] = ROHF_dFluxDensity_dJ[Lint0, $1, $DTime, <<len(mp.rohf['alpha'])>>,
306
+ {% for i in range(1, 1+len(mp.rohf['alpha'])) %} w_rohf_<<i>>, $<<2*i>>, $<<2*i+1>>,
307
+ kappa_rohf_<<i>>, tau_e_rohf_<<i>>{% if not loop.last %}, {% endif %}
308
+ {% endfor %}
309
+ ];
310
+
311
+ // --- Flux density based on known jrevs
312
+ // $1 to $N: reversible current densities
313
+ fluxdens_jrev[] = ROHF_fluxDensity_jrev[Lint0, <<len(mp.rohf['alpha'])>>,
314
+ {% for i in range(1, 1+len(mp.rohf['alpha'])) %} w_rohf_<<i>>, $<<i>> {% if not loop.last %}, {% endif %}
315
+ {% endfor %}
316
+ ];
317
+
318
+ {% endif %}
319
+
320
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
321
+ // Parallel resistor
322
+ {% if isinstance(dm.magnet.solve.source_parameters.parallel_resistor, float) %}
323
+ R[ParallelResistor] = <<dm.magnet.solve.source_parameters.parallel_resistor>>; // Resistance of the parallel resistor
324
+ {% else %}
325
+ R[ParallelResistor] = 1.0; // Default resistance of 1 Ohm for the parallel resistor
326
+ {% endif %}
327
+ {% endif %}
328
+
329
+ // ------- SOURCE PARAMETERS -------
330
+ bmax = <<dm.magnet.solve.source_parameters.sine.field_amplitude>>; // Maximum applied magnetic induction [T]
331
+ f = <<dm.magnet.solve.source_parameters.sine.frequency>>; // Frequency of applied field [Hz]
332
+ Imax = <<dm.magnet.solve.source_parameters.sine.current_amplitude>>; // Maximum transport current [A]
333
+
334
+ {% if dm.magnet.solve.frequency_domain_solver.frequency_sweep.run_sweep %}
335
+ nbFreq = <<dm.magnet.solve.frequency_domain_solver.frequency_sweep.number_of_frequencies>>; // How many frequencies in the frequency domain?
336
+ freq = LogSpace[Log10[<<dm.magnet.solve.frequency_domain_solver.frequency_sweep.start_frequency>>], Log10[<<dm.magnet.solve.frequency_domain_solver.frequency_sweep.end_frequency>>], nbFreq];
337
+ {% endif %}
338
+
339
+ // Direction and value of applied field
340
+ {% if dm.magnet.solve.source_parameters.source_type == 'sine' %} // Sine wave source (potentially with DC component)
341
+ time_multiplier = 1;
342
+
343
+ ramp_duration = -0.05/f;
344
+
345
+ constant_I_transport[] = ($Time < ramp_duration ) ? InterpolationLinear[$Time]{List[{0,0,ramp_duration,<<dm.magnet.solve.source_parameters.sine.superimposed_DC.current_magnitude>>}]} : <<dm.magnet.solve.source_parameters.sine.superimposed_DC.current_magnitude>>;
346
+ I_transport[] = constant_I_transport[] + <<dm.magnet.solve.source_parameters.sine.current_amplitude>> * Sin[2*Pi*f * $Time];
347
+
348
+ constant_field_direction[] = Vector[0., 1., 0.];
349
+ directionApplied[] = Vector[Cos[<<dm.magnet.solve.source_parameters.field_angle>>*Pi/180], Sin[<<dm.magnet.solve.source_parameters.field_angle>>*Pi/180], 0.];
350
+
351
+ constant_b[] = ($Time < ramp_duration ) ? InterpolationLinear[$Time]{List[{0,0,ramp_duration,<<dm.magnet.solve.source_parameters.sine.superimposed_DC.field_magnitude>>}]} : <<dm.magnet.solve.source_parameters.sine.superimposed_DC.field_magnitude>>;
352
+ constant_b_prev[] = ($Time-$DTime < ramp_duration ) ? InterpolationLinear[$Time-$DTime]{List[{0,0,ramp_duration,<<dm.magnet.solve.source_parameters.sine.superimposed_DC.field_magnitude>>}]} : <<dm.magnet.solve.source_parameters.sine.superimposed_DC.field_magnitude>>;
353
+
354
+ hsVal[] = nu0 * constant_b[] * constant_field_direction[] + nu0 * <<dm.magnet.solve.source_parameters.sine.field_amplitude>> * Sin[2*Pi*f * $Time] * directionApplied[];// * 200 * (X[] - 0.00625);
355
+ hsVal_prev[] = nu0 * constant_b_prev[] * constant_field_direction[] + nu0 * <<dm.magnet.solve.source_parameters.sine.field_amplitude>> * Sin[2*Pi*f * ($Time-$DTime)] * directionApplied[];// * 200 * (X[] - 0.00625);
356
+
357
+ {% elif dm.magnet.solve.source_parameters.source_type == 'piecewise' %}
358
+ time_multiplier = <<dm.magnet.solve.source_parameters.piecewise.time_multiplier>>;
359
+ applied_field_multiplier = <<dm.magnet.solve.source_parameters.piecewise.applied_field_multiplier>>;
360
+ transport_current_multiplier = <<dm.magnet.solve.source_parameters.piecewise.transport_current_multiplier>>;
361
+ directionApplied[] = Vector[Cos[<<dm.magnet.solve.source_parameters.field_angle>>*Pi/180], Sin[<<dm.magnet.solve.source_parameters.field_angle>>*Pi/180], 0.];
362
+
363
+ {% if dm.magnet.solve.source_parameters.piecewise.source_csv_file %} // Source from CSV file
364
+ timeList() = {<<ed['time']|join(', ')>>};
365
+ bappList() = {<<ed['b']|join(', ')>>};
366
+ IList() = {<<ed['I']|join(', ')>>};
367
+ time_bapp_List() = ListAlt[timeList(), bappList()];
368
+ time_I_List() = ListAlt[timeList(), IList()];
369
+
370
+ hsVal[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{List[time_bapp_List()]} * directionApplied[];
371
+ hsVal_prev[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time-$DTime)/time_multiplier]]{List[time_bapp_List()]} * directionApplied[];
372
+ I_transport[] = transport_current_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{List[time_I_List()]};
373
+
374
+ {% else %} // Source from parameters
375
+ times_source_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.times|join(', ')>>};
376
+ transport_currents_relative_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.transport_currents_relative|join(', ')>>};
377
+ applied_fields_relative_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.applied_fields_relative|join(', ')>>};
378
+
379
+ hsVal[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), applied_fields_relative_piecewise_linear()]} * directionApplied[];
380
+ hsVal_prev[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time-$DTime)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), applied_fields_relative_piecewise_linear()]} * directionApplied[];
381
+ I_transport[] = transport_current_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), transport_currents_relative_piecewise_linear()]};
382
+ {% endif %}
383
+ {% endif %}
384
+
385
+ // For the natural boundary condition (restricted to fields of constant direction for the moment, should be generalized)
386
+ dbsdt[] = mu0 * (hsVal[] - hsVal_prev[]) / $DTime; // must be a finite difference to avoid error accumulation
387
+
388
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
389
+ // Excitation coils from file
390
+ timeList() = {<<ed['time']|join(', ')>>};
391
+ {% if dm.magnet.solve.source_parameters.excitation_coils.source_csv_file %}
392
+ {% for i in range(1, 1+len(rm.powered.ExcitationCoils.vol.numbers)) %}
393
+ I_<<i>>_list() = {<<ed['I'+str(i)]|join(', ')>>};
394
+ time_I_<<i>>_List() = ListAlt[timeList(), I_<<i>>_list()];
395
+ I_<<i>>[] = InterpolationLinear[Max[0,($Time)]]{List[time_I_<<i>>_List()]};
396
+ {% endfor %}
397
+ {% else %}
398
+ I_1[] = + 2016 * (($Time < 2.0) ? 0.0 : 1.0) * Sin[2*Pi*f*$Time];
399
+ I_2[] = - 2016 * (($Time < 2.0) ? 0.0 : 1.0) * Sin[2*Pi*f*$Time];
400
+ js[Coil_1] = + 2016/(5e-3 * 1.4e-3) * (($Time < 2.0) ? 0.0 : 1.0) * Sin[2*Pi*f*$Time] * Vector[0,0,1];
401
+ js[Coil_2] = - 2016/(5e-3 * 1.4e-3) * (($Time < 2.0) ? 0.0 : 1.0) * Sin[2*Pi*f*$Time] * Vector[0,0,1];
402
+ {% endif %}
403
+ {% endif %}
404
+
405
+ // ------- NUMERICAL PARAMETERS -------
406
+ timeStart = 0.; // Initial time [s]
407
+
408
+ {% if dm.magnet.solve.source_parameters.source_type == 'sine'%}
409
+ timeFinal = <<dm.magnet.solve.numerical_parameters.sine.number_of_periods_to_simulate>>/f; // Final time for source definition (s)
410
+ dt = 1 / (f*<<dm.magnet.solve.numerical_parameters.sine.timesteps_per_period>>); // Time step (initial if adaptive) (s)
411
+ dt_max = dt; // Fixed maximum time step
412
+ dt_max_var[] = dt_max;
413
+ {% else %}
414
+ timeFinal = <<dm.magnet.solve.numerical_parameters.piecewise.time_to_simulate>>;
415
+
416
+ {% if dm.magnet.solve.numerical_parameters.piecewise.variable_max_timestep %}
417
+ times_max_timestep_piecewise_linear() = {<<dm.magnet.solve.numerical_parameters.piecewise.times_max_timestep_piecewise_linear|join(', ')>>};
418
+ max_timestep_piecewise_linear() = {<<dm.magnet.solve.numerical_parameters.piecewise.max_timestep_piecewise_linear|join(', ')>>};
419
+ dt = max_timestep_piecewise_linear(0);
420
+ dt_max_var[] = InterpolationLinear[Max[0,$Time]]{ListAlt[times_max_timestep_piecewise_linear(), max_timestep_piecewise_linear()]};
421
+ {% else %}
422
+ dt = timeFinal / <<dm.magnet.solve.numerical_parameters.piecewise.timesteps_per_time_to_simulate>>;
423
+ dt_max = dt; // Fixed maximum time step
424
+ dt_max_var[] = dt_max;
425
+ {% endif %}
426
+
427
+ {% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear%}
428
+ control_time_instants_list() = {<<dm.magnet.solve.source_parameters.piecewise.times|join(', ')>>, 1e99}; // last one is just to avoid 'seg. fault' errors
429
+ {% endif %}
430
+
431
+ {% endif %}
432
+
433
+ iter_max = 50; // Maximum number of iterations (after which we exit the iterative loop)
434
+ extrapolationOrder = 1; // Extrapolation order for predictor
435
+ tol_energy = 1e-6; // Tolerance on the relative change of the power indicator
436
+ writeInterval = dt; // Time interval to save the solution [s]
437
+
438
+ // ------- Source Current -------
439
+ Flag_save_hs = 0; // For debugging purposes, to see what are the computed source current and fields for stranded conductors
440
+ Is0[] = Vector[0, 0, 1]; // source current of unit amplitude (A)
441
+
442
+ // ------- SIMULATION NAME -------
443
+ name = "txt_files";
444
+ resDirectory = StrCat["./",name];
445
+ infoResidualFile = StrCat[resDirectory,"/residual.txt"];
446
+ outputPowerFull = StrCat[resDirectory,"/power_full.txt"]; // File updated during runtime
447
+ outputPowerROHM = StrCat[resDirectory,"/power_ROHM.txt"]; // File updated during runtime
448
+ outputPowerROHF = StrCat[resDirectory,"/power_ROHF.txt"]; // File updated during runtime
449
+ pcrossingFile = StrCat[resDirectory,"/p_crossing.txt"];
450
+ crashReportFile = StrCat[resDirectory,"/crash_report.txt"];
451
+
452
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
453
+ h_from_file[] = VectorField[XYZ[]]; // After GmshRead[] in Resolution, this vector field contains the solution from a .pos file that can be accessed at any point XYZ[]
454
+ {% endif %}
455
+
456
+ }
457
+
458
+ Constraint {
459
+ { Name phi ;
460
+ Case {
461
+ {% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %} // For natural boundary condition (in formulation)
462
+ {Region ArbitraryPoints ; Value 0.0 ;} // Fix the magnetic potential to zero on the boundaries of the filaments and the outer matrix boundary
463
+ {% elif dm.magnet.solve.source_parameters.boundary_condition_type == 'Essential' %}
464
+ {Region BndAir ; Type Assign ; Value XYZ[]*directionApplied[] ; TimeFunction hsVal[] * directionApplied[] ;} // Essential boundary condition (not compatible with transport current)
465
+ {% endif %}
466
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
467
+ {Region Omega ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
468
+ {% endif %}
469
+ }
470
+ }
471
+ { Name a ;
472
+ Case {
473
+ {Region GammaAll ; Value -X[] * mu0 ; TimeFunction hsVal[] ;}
474
+ }
475
+ }
476
+ { Name h ; Case {} }
477
+ { Name Voltage ; Case {} }
478
+ { Name k ; Case {} }
479
+
480
+ { Name Current ;
481
+ Case {
482
+ {% if not dm.magnet.solve.source_parameters.parallel_resistor %}
483
+ {% for i in range(len(rm.powered.Cables.cochain.numbers)) %}
484
+ {% if dm.magnet.solve.source_parameters.cable_current_multipliers is none %}
485
+ {Region CableCut_<<i+1>> ; Type Assign ; Value 1.0 ; TimeFunction I_transport[] ;}
486
+ {% else %}
487
+ {Region CableCut_<<i+1>> ; Type Assign ; Value <<dm.magnet.solve.source_parameters.cable_current_multipliers[i]>> ; TimeFunction I_transport[] ;}
488
+ {% endif %}
489
+ {% endfor %}
490
+ {% endif %}
491
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
492
+ {Region Cuts ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
493
+ {% endif %}
494
+ }
495
+ }
496
+
497
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
498
+ {% for i in range(0, len(rm.powered.ExcitationCoils.vol.numbers)) %}
499
+ { Name GaugeCondition_hs_coil_<<i+1>> ; Type Assign ;
500
+ Case {
501
+ { Region Coil_<<i+1>> ; SubRegion CoilBnd_<<i+1>> ; Value 0. ; }
502
+ }
503
+ }
504
+ {% endfor %}
505
+ { Name Current_hs_coil ; Type Assign ;
506
+ Case {
507
+ { Region Cuts; Value 1.0;}
508
+ }
509
+ }
510
+ { Name Current_coil ; Type Assign ;
511
+ Case {
512
+ {% for i in range(0, len(rm.powered.ExcitationCoils.vol.numbers)) %}
513
+ { Region Coil_<<i+1>>; Value 1.0; TimeFunction I_<<i+1>>[];}
514
+ {% endfor %}
515
+ }
516
+ }
517
+ {% endif %}
518
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
519
+ { Name Current_Cir_transport ;
520
+ Case {
521
+ {Region CurrentSource ; Value 1.0 ; TimeFunction I_transport[] ;}
522
+ }
523
+ } // Empty to avoid warnings
524
+ { Name Voltage_Cir_transport ; Case {} } // Empty to avoid warnings
525
+ {Name ElectricalCircuit_transport ; Type Network ;
526
+ Case circuit1 {
527
+ // TO DO HERE
528
+ {% for i in range(len(rm.powered.Cables.cochain.numbers)) %}
529
+ {% if dm.magnet.solve.source_parameters.cable_current_multipliers[i] > 0.0 %}
530
+ {Region CableCut_<<i+1>> ; Branch {<<i>>, <<i+1>>} ;}
531
+ {% else %}
532
+ {Region CableCut_<<i+1>> ; Branch {<<i+1>>, <<i>>} ;}
533
+ {% endif %}
534
+ {% endfor %}
535
+ {Region CurrentSource ; Branch { <<len(rm.powered.Cables.cochain.numbers)>>, 0 } ;}
536
+ {Region ParallelResistor ; Branch { <<len(rm.powered.Cables.cochain.numbers)>>, 0 } ;}
537
+ }
538
+ }
539
+ {% endif %}
540
+ }
541
+
542
+ Jacobian {
543
+ { Name Vol ;
544
+ Case {
545
+ {Region All ; Jacobian Vol ;}
546
+ }
547
+ }
548
+ { Name Sur ;
549
+ Case {
550
+ { Region All ; Jacobian Sur ; }
551
+ }
552
+ }
553
+ }
554
+
555
+ Integration {
556
+ { Name Int ;
557
+ Case {
558
+ { Type Gauss ;
559
+ Case {
560
+ { GeoElement Point ; NumberOfPoints 1 ; }
561
+ { GeoElement Line ; NumberOfPoints 3 ; }
562
+ { GeoElement Triangle ; NumberOfPoints 3 ; }
563
+ { GeoElement Quadrangle ; NumberOfPoints 4 ; }
564
+ }
565
+ }
566
+ }
567
+ }
568
+ // For hysteretic element, integration of {b} and bhyst[{h}], which should be accounted for as constant per element
569
+ { Name Int_b ;
570
+ Case {
571
+ { Type Gauss ;
572
+ Case {
573
+ { GeoElement Triangle ; NumberOfPoints 1 ; }
574
+ { GeoElement Quadrangle ; NumberOfPoints 1 ; }
575
+ }
576
+ }
577
+ }
578
+ }
579
+ }
580
+
581
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
582
+ For i In {1 : <<len(rm.powered.ExcitationCoils.vol.numbers)>>}
583
+ FunctionSpace {
584
+ // Function space for the source field (defined during pre-resolution, and then included as a sub-space in the main h_space)
585
+ { Name hs_coil_space~{i}; Type Form1;
586
+ BasisFunction {
587
+ { Name psie; NameOfCoef he; Function BF_Edge;
588
+ Support Coil~{i}; Entity EdgesOf[All, Not CoilBnd~{i}]; }
589
+ { Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
590
+ Support Omega; Entity GroupsOfEdgesOf[CoilCut~{i}]; }
591
+ }
592
+ Constraint {
593
+ { NameOfCoef he; EntityType EdgesOfTreeIn; EntitySubType StartingOn;
594
+ NameOfConstraint GaugeCondition_hs_coil~{i}; }
595
+ { NameOfCoef Ii ; EntityType GroupsOfEdgesOf ; NameOfConstraint Current_hs_coil ; }
596
+ }
597
+ }
598
+ }
599
+ Formulation{
600
+ // Formulation for source currents in coils
601
+ { Name js_to_hs_coil~{i} ; Type FemEquation ;
602
+ Quantity {
603
+ { Name hs ; Type Local ; NameOfSpace hs_coil_space~{i} ; }
604
+ }
605
+ Equation {
606
+ Galerkin { [ Dof{d hs}, {d hs} ] ;
607
+ In Coil~{i} ; Jacobian Vol ; Integration Int ; }
608
+ Galerkin { [ - Is0[]/SurfaceArea[], {d hs} ] ;
609
+ In Coil~{i} ; Jacobian Vol ; Integration Int ; }
610
+ }
611
+ }
612
+ }
613
+ Resolution{
614
+ { Name js_to_hs_coil~{i} ;
615
+ System {
616
+ { Name Sys_Mag ; NameOfFormulation js_to_hs_coil~{i} ; }
617
+ }
618
+ Operation {
619
+ Generate Sys_Mag ; Solve Sys_Mag ;
620
+ }
621
+ }
622
+ }
623
+ EndFor
624
+ {% endif %}
625
+
626
+ FunctionSpace {
627
+ // Function space for magnetic field h in h-conform formulation. Main field for the magnetodynamic problem.
628
+ // h = sum phi_n * grad(psi_n) (nodes in Omega_CC with boundary)
629
+ // + sum h_e * psi_e (edges in Omega_C)
630
+ // + sum I_i * c_i (cuts, global basis functions for net current intensity)
631
+ // + [TBC]
632
+ { Name h_space; Type Form1;
633
+ BasisFunction {
634
+ { Name gradpsin; NameOfCoef phin; Function BF_GradNode;
635
+ Support Omega_h_OmegaCC_AndBnd; Entity NodesOf[OmegaCC]; } // Extend support to boundary for surface integration (e.g. useful for weak B.C.)
636
+ { Name gradpsin; NameOfCoef phin2; Function BF_GroupOfEdges;
637
+ Support OmegaC; Entity GroupsOfEdgesOnNodesOf[BndOmegaC]; } // To treat properly the Omega_CC-Omega_C boundary
638
+ { Name psie; NameOfCoef he; Function BF_Edge;
639
+ Support OmegaC_AndBnd; Entity EdgesOf[All, Not BndOmegaC]; }
640
+ { Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
641
+ Support Omega_h_AndBnd; Entity GroupsOfEdgesOf[CableCuts]; } // The region Cuts contains the union of all the relevant cuts (cohomology basis function support)
642
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable and not dm.magnet.solve.formulation_parameters.hphia %}
643
+ { Name sb_coil ; NameOfCoef Ic ; // Global Basis Function
644
+ Function BF_Global {
645
+ Quantity hs ;
646
+ Formulation js_to_hs_coil {<<len(rm.powered.ExcitationCoils.vol.numbers)>>} ;
647
+ Group Coils ; Resolution js_to_hs_coil {<<len(rm.powered.ExcitationCoils.vol.numbers)>>} ;
648
+ } ;
649
+ Support Omega ; Entity Global [Coils] ; }
650
+ {% endif %}
651
+ }
652
+ GlobalQuantity {
653
+ { Name I ; Type AliasOf ; NameOfCoef Ii ; }
654
+ { Name V ; Type AssociatedWith ; NameOfCoef Ii ; }
655
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable and not dm.magnet.solve.formulation_parameters.hphia %}
656
+ { Name Ic ; Type AliasOf ; NameOfCoef Ic ; }
657
+ { Name Vc ; Type AssociatedWith ; NameOfCoef Ic ; }
658
+ {% endif %}
659
+ }
660
+ Constraint {
661
+ { NameOfCoef he; EntityType EdgesOf; NameOfConstraint h; }
662
+ { NameOfCoef phin; EntityType NodesOf; NameOfConstraint phi; }
663
+ { NameOfCoef phin2; EntityType NodesOf; NameOfConstraint phi; }
664
+ { NameOfCoef Ii ; EntityType GroupsOfEdgesOf ; NameOfConstraint Current ; }
665
+ { NameOfCoef V ; EntityType GroupsOfNodesOf ; NameOfConstraint Voltage ; }
666
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable and not dm.magnet.solve.formulation_parameters.hphia %}
667
+ { NameOfCoef Ic ; EntityType Region ; NameOfConstraint Current_coil ; }
668
+ { NameOfCoef Vc ; EntityType Region ; NameOfConstraint Voltage_coil ; }
669
+ {% endif %}
670
+ }
671
+ }
672
+ // Function space for the interstrand coupling currents
673
+ { Name k_space; Type Form1;
674
+ BasisFunction {
675
+ { Name kc; NameOfCoef ke; Function BF_Edge;
676
+ Support Region[{OmegaC_AndBnd}]; Entity EdgesOf[All, Not BndOmegaC]; } // Extend support to boundary for surface integration (e.g. useful for weak B.C.)
677
+ }
678
+ Constraint {
679
+ { NameOfCoef ke; EntityType EdgesOf; NameOfConstraint k; }
680
+ }
681
+ }
682
+ {% if dm.magnet.solve.rohm.enable %}
683
+ // Function space for b from ROHM.
684
+ { Name b_or_h_space ; Type Vector;
685
+ BasisFunction {
686
+ { Name sex ; NameOfCoef aex ; Function BF_VolumeX ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
687
+ { Name sey ; NameOfCoef aey ; Function BF_VolumeY ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
688
+ }
689
+ }
690
+ // Function space for internal state variable with ROHM (h_rev for each cell)
691
+ For k In {1:N_rohm}
692
+ { Name hrev~{k} ; Type Form1;
693
+ BasisFunction {
694
+ { Name psie; NameOfCoef he; Function BF_Edge;
695
+ Support MagnHystDomain; Entity EdgesOf[All]; }
696
+ // { Name sex ; NameOfCoef aex ; Function BF_VolumeX ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
697
+ // { Name sey ; NameOfCoef aey ; Function BF_VolumeY ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
698
+ }
699
+ }
700
+ // We can also recompute it, instead of saving it. To be seen which approach is the best.
701
+ { Name g~{k} ; Type Form1;
702
+ BasisFunction {
703
+ { Name psie; NameOfCoef he; Function BF_Edge;
704
+ Support MagnHystDomain; Entity EdgesOf[All]; }
705
+ // { Name vex ; NameOfCoef bex ; Function BF_VolumeX ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
706
+ // { Name vey ; NameOfCoef bey ; Function BF_VolumeY ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
707
+ }
708
+ }
709
+ EndFor
710
+ {% endif %}
711
+ {% if dm.magnet.solve.rohf.enable %}
712
+ // Function space for j from ROHF. Element-wise constant functions
713
+ { Name flux_space ; Type Vector;
714
+ BasisFunction {
715
+ { Name sez ; NameOfCoef aez ; Function BF_VolumeZ ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
716
+ }
717
+ }
718
+ // Function space for internal state variable with ROHF (j_rev for each cell)
719
+ For k In {1:N_rohf}
720
+ { Name jrev~{k} ; Type Vector;
721
+ BasisFunction {
722
+ { Name psiv; NameOfCoef jv; Function BF_VolumeZ;
723
+ Support MagnHystDomain; Entity VolumesOf[All]; }
724
+ }
725
+ }
726
+ { Name jreveddy~{k} ; Type Vector;
727
+ BasisFunction {
728
+ { Name psive; NameOfCoef jve; Function BF_VolumeZ;
729
+ Support MagnHystDomain; Entity VolumesOf[All]; }
730
+ }
731
+ }
732
+ EndFor
733
+ {% endif %}
734
+ // Function space for vector potential in the mixed formulation
735
+ { Name a_space_2D; Type Form1P;
736
+ BasisFunction {
737
+ { Name psin; NameOfCoef an; Function BF_PerpendicularEdge;
738
+ Support Omega_a_AndBnd; Entity NodesOf[All]; }
739
+ { Name psin2; NameOfCoef an2; Function BF_PerpendicularEdge_2E;
740
+ Support Omega_a_AndBnd; Entity EdgesOf[BndOmegaC]; }
741
+ }
742
+ Constraint {
743
+ { NameOfCoef an; EntityType NodesOf; NameOfConstraint a; }
744
+ }
745
+ }
746
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
747
+ // Function space for the circuit domain
748
+ { Name ElectricalCircuit_transport; Type Scalar;
749
+ BasisFunction {
750
+ { Name sn; NameOfCoef Icoef; Function BF_Region;
751
+ Support PoweringCircuit; Entity PoweringCircuit; }
752
+ }
753
+ GlobalQuantity {
754
+ { Name Ip ; Type AliasOf ; NameOfCoef Icoef ; }
755
+ { Name Vp ; Type AssociatedWith ; NameOfCoef Icoef ; }
756
+ }
757
+ Constraint {
758
+ { NameOfCoef Ip ; EntityType Region ; NameOfConstraint Current_Cir_transport ; }
759
+ { NameOfCoef Vp ; EntityType Region ; NameOfConstraint Voltage_Cir_transport ; }
760
+ }
761
+ }
762
+ {% endif %}
763
+ }
764
+
765
+ Formulation{
766
+ // h-formulation
767
+ { Name MagDyn_hphi; Type FemEquation;
768
+ Quantity {
769
+ // Functions for the out-of-plane (OOP) problem
770
+ { Name h; Type Local; NameOfSpace h_space; }
771
+ { Name hp; Type Local; NameOfSpace h_space; }
772
+ { Name I; Type Global; NameOfSpace h_space[I]; }
773
+ { Name V; Type Global; NameOfSpace h_space[V]; }
774
+ {% if dm.magnet.solve.rohm.enable %}
775
+ // ROHM model
776
+ { Name b; Type Local; NameOfSpace b_or_h_space; }
777
+ For k In {1:N_rohm}
778
+ { Name hrev~{k}; Type Local; NameOfSpace hrev~{k};}
779
+ { Name g~{k}; Type Local; NameOfSpace g~{k};}
780
+ EndFor
781
+ {% endif %}
782
+ {% if dm.magnet.solve.rohf.enable %}
783
+ // ROHF model
784
+ { Name flux; Type Local; NameOfSpace flux_space; }
785
+ For k In {1:N_rohf}
786
+ { Name jrev~{k}; Type Local; NameOfSpace jrev~{k}; }
787
+ { Name jreveddy~{k}; Type Local; NameOfSpace jreveddy~{k}; }
788
+ EndFor
789
+ {% endif %}
790
+ // IS coupling currents
791
+ { Name k_IS; Type Local; NameOfSpace k_space; }
792
+ {% if dm.magnet.solve.formulation_parameters.hphia %}
793
+ // h-phi-a
794
+ { Name a; Type Local; NameOfSpace a_space_2D; }
795
+ {% else %}
796
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
797
+ // excitation coils
798
+ { Name Ic ; Type Global; NameOfSpace h_space[Ic]; }
799
+ { Name Vc ; Type Global; NameOfSpace h_space[Vc]; }
800
+ {% endif %}
801
+ {% endif %}
802
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
803
+ { Name Ip ; Type Global; NameOfSpace ElectricalCircuit_transport[Ip]; }
804
+ { Name Vp ; Type Global; NameOfSpace ElectricalCircuit_transport[Vp]; }
805
+ {% endif %}
806
+ }
807
+ Equation {
808
+ // --- Axial currents problem ---
809
+ // Time derivative of b (NonMagnDomain)
810
+ Galerkin { [ mu[] * Dof{h} / $DTime , {h} ];
811
+ In MagnLinDomain; Integration Int; Jacobian Vol; }
812
+ Galerkin { [ -mu[] * {h}[1] / $DTime , {h} ];
813
+ In MagnLinDomain; Integration Int; Jacobian Vol; }
814
+
815
+ {% if dm.magnet.solve.rohf.enable %}
816
+ // ROHF model for the current flowing in the strands
817
+ {% if not dm.magnet.solve.rohm.enable %}
818
+ // Time derivative of b (in MagnHystDomain if no ROHM)
819
+ Galerkin { [ mu[] * Dof{h} / $DTime , {h} ];
820
+ In MagnHystDomain; Integration Int; Jacobian Vol; }
821
+ Galerkin { [ -mu[] * {h}[1] / $DTime , {h} ];
822
+ In MagnHystDomain; Integration Int; Jacobian Vol; }
823
+ {% endif %}
824
+ Galerkin { [ fluxdens[{d h}{% for i in range(1, 1+len(mp.rohf['alpha'])) %}, {jrev_<<i>>}[1], {jreveddy_<<i>>}[1]{% endfor %}] / $DTime , {d h} ];
825
+ In MagnHystDomain; Integration Int; Jacobian Vol; }
826
+ Galerkin { [ dfluxdensdj[{d h}{% for i in range(1, 1+len(mp.rohf['alpha'])) %}, {jrev_<<i>>}[1], {jreveddy_<<i>>}[1]{% endfor %}] * Dof{d h} / $DTime , {d hp} ];
827
+ In MagnHystDomain; Integration Int; Jacobian Vol; }
828
+ Galerkin { [ - dfluxdensdj[{d h}{% for i in range(1, 1+len(mp.rohf['alpha'])) %}, {jrev_<<i>>}[1], {jreveddy_<<i>>}[1]{% endfor %}] * {d h} / $DTime , {d hp} ];
829
+ In MagnHystDomain; Integration Int; Jacobian Vol; }
830
+ Galerkin { [ - {flux}[1] / $DTime , {d h} ];
831
+ In MagnHystDomain; Integration Int; Jacobian Vol; }
832
+ {% endif %}
833
+ {% if dm.magnet.solve.rohm.enable %}
834
+ // ROHM
835
+ // Templated for N cells
836
+ Galerkin { [ bhyst[{h},{% for i in range(1, 1+len(mp.rohm['alpha'])) %} {hrev_<<i>>}[1], {g_<<i>>}[1],{% endfor %} Norm[{b}]] / $DTime , {h} ];
837
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
838
+ Galerkin { [ dbhystdh[{h},{% for i in range(1, 1+len(mp.rohm['alpha'])) %} {hrev_<<i>>}[1], {g_<<i>>}[1],{% endfor %} Norm[{b}]] * Dof{h} / $DTime , {hp}];
839
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
840
+ Galerkin { [ - dbhystdh[{h},{% for i in range(1, 1+len(mp.rohm['alpha'])) %} {hrev_<<i>>}[1], {g_<<i>>}[1],{% endfor %} Norm[{b}]] * {h} / $DTime , {hp}];
841
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
842
+ Galerkin { [ - {b}[1] / $DTime , {h} ];
843
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
844
+ {% endif %}
845
+
846
+ {% if dm.magnet.solve.general_parameters.superconductor_linear %}
847
+ // Eddy current (linear OmegaC)
848
+ Galerkin { [ rho[] * Dof{d h} , {d h} ];
849
+ In OmegaC; Integration Int; Jacobian Vol; }
850
+ {% else %}
851
+ Galerkin { [ e_joule[{d h}] , {d h} ]; // h based
852
+ In OmegaC; Integration Int; Jacobian Vol; }
853
+ Galerkin { [ dedj_joule[{d h}] * Dof{d h} , {d hp} ];
854
+ In OmegaC; Integration Int; Jacobian Vol; } // For Newton-Raphson method
855
+ Galerkin { [ - dedj_joule[{d h}] * {d h} , {d hp} ];
856
+ In OmegaC; Integration Int; Jacobian Vol; } // For Newton-Raphson method
857
+ {% endif %}
858
+
859
+ // Induced currents (Global var)
860
+ GlobalTerm { [ Dof{V} , {I} ] ; In CableCuts ; }
861
+
862
+ // Insterstrand coupling current coupling term
863
+ Galerkin { [ Dof{d k_IS} , {d h} ];
864
+ In OmegaC; Integration Int; Jacobian Vol; }
865
+ // Interstrand coupling current formulation
866
+ Galerkin { [ - sigma_IS[] * Dof{k_IS} , {k_IS} ];
867
+ In OmegaC; Integration Int; Jacobian Vol; }
868
+ Galerkin { [ alpha_ks[] * Dof{d h} , {d k_IS} ];
869
+ In OmegaC; Integration Int; Jacobian Vol; }
870
+
871
+ // a-formulation in the mixed formulation
872
+ {% if dm.magnet.solve.formulation_parameters.hphia %}
873
+ Galerkin { [ nu[] * Dof{d a} , {d a} ];
874
+ In Omega_a; Integration Int; Jacobian Vol; }
875
+ // Coupling terms
876
+ Galerkin { [ + normal_sign * Dof{a} /\ Normal[] /$DTime , {h}];
877
+ In BndOmega_ha; Integration Int; Jacobian Sur; }
878
+ Galerkin { [ - normal_sign * {a}[1] /\ Normal[] /$DTime , {h}];
879
+ In BndOmega_ha; Integration Int; Jacobian Sur; }
880
+ Galerkin { [ normal_sign * Dof{h} /\ Normal[] , {a}];
881
+ In BndOmega_ha; Integration Int; Jacobian Sur; }
882
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
883
+ Galerkin { [ -js[] , {a} ];
884
+ In Coils; Integration Int; Jacobian Vol; }
885
+ {% endif %}
886
+ {% else %}
887
+ // Natural boundary condition
888
+ Galerkin { [ - dbsdt[] * Normal[] , {dInv h} ];
889
+ In BndAir; Integration Int; Jacobian Sur; }
890
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
891
+ GlobalTerm { [ Dof{Vc} , {Ic} ] ; In CoilCuts ; }
892
+ {% endif %}
893
+ {% endif %}
894
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
895
+ GlobalTerm{ [ Dof{Vp} , {Ip} ]; In ParallelResistor; }
896
+ GlobalTerm{ [ R[] * Dof{Ip} , {Ip} ]; In ParallelResistor; }
897
+ // Circuit network for transport current and voltage
898
+ GlobalEquation {
899
+ Type Network ; NameOfConstraint ElectricalCircuit_transport ;
900
+ { Node {I}; Loop {V}; Equation {V}; In CableCuts ; }
901
+ { Node {Ip}; Loop {Vp}; Equation {Vp}; In PoweringCircuit; }
902
+ }
903
+ {% endif %}
904
+ }
905
+ }
906
+ // Frequency domain formulation
907
+ { Name MagDyn_hphi_freq; Type FemEquation;
908
+ Quantity {
909
+ // Functions for the out-of-plane (OOP) problem
910
+ { Name h; Type Local; NameOfSpace h_space; }
911
+ { Name I; Type Global; NameOfSpace h_space[I]; }
912
+ { Name V; Type Global; NameOfSpace h_space[V]; }
913
+ { Name k_IS; Type Local; NameOfSpace k_space; }
914
+ }
915
+ Equation {
916
+ // --- OOP problem ---
917
+ // Time derivative of b (NonMagnDomain)
918
+ Galerkin { DtDof[ mu[] * Dof{h}, {h} ];
919
+ In Omega; Integration Int; Jacobian Vol; }
920
+
921
+ Galerkin { [ Dof{d k_IS} , {d h} ];
922
+ In OmegaC; Integration Int; Jacobian Vol; }
923
+
924
+ // Natural boundary condition for normal flux density (useful when transport current is an essential condition)
925
+ {% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %}
926
+ Galerkin { [ - Complex[0, 2*Pi*$f*bmax]*Vector[Cos[<<dm.magnet.solve.source_parameters.field_angle>>*Pi/180], Sin[<<dm.magnet.solve.source_parameters.field_angle>>*Pi/180], 0.] * Normal[] , {dInv h} ];
927
+ In BndAir; Integration Int; Jacobian Sur; }
928
+ {% endif %}
929
+
930
+ Galerkin { [ - sigma_IS[] * Dof{k_IS} , {k_IS} ];
931
+ In OmegaC; Integration Int; Jacobian Vol; }
932
+ Galerkin { [ alpha_ks[] * Dof{d h} , {d k_IS} ];
933
+ In OmegaC; Integration Int; Jacobian Vol; }
934
+
935
+ // Global term
936
+ GlobalTerm { [ Dof{V} , {I} ] ; In Cuts ; }
937
+ }
938
+ }
939
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
940
+ // Projection formulation for initial condition
941
+ { Name Projection_h_to_h; Type FemEquation;
942
+ Quantity {
943
+ { Name h; Type Local; NameOfSpace h_space; }
944
+ }
945
+ Equation{
946
+ // For the current formulation, it seems to be accurate enough to project the field directly (and not its curl as an intermediate to reconstruct it).
947
+ // Validity of this to be checked again if we go to different meshes between the initial condition and the following simulation.
948
+ Galerkin { [ Dof{h}, {h} ] ;
949
+ In Omega ; Jacobian Vol ; Integration Int ; }
950
+ Galerkin { [ - h_from_file[], {h} ] ;
951
+ In Omega ; Jacobian Vol ; Integration Int ; }
952
+ }
953
+ }
954
+ {% endif %}
955
+ {% if dm.magnet.solve.rohm.enable %}
956
+ // Update of b in hysteresis model
957
+ { Name Update_b; Type FemEquation ;
958
+ Quantity {
959
+ { Name h; Type Local; NameOfSpace h_space; }
960
+ { Name b ; Type Local ; NameOfSpace b_or_h_space ; }
961
+ For k In {1:N_rohm}
962
+ { Name hrev~{k} ; Type Local ; NameOfSpace hrev~{k};}
963
+ { Name g~{k} ; Type Local ; NameOfSpace g~{k};}
964
+ EndFor
965
+ }
966
+ Equation {
967
+ Galerkin { [ Dof{b} , {b} ];
968
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
969
+ // Templated for N cells
970
+ Galerkin { [ - bhyst[{h},{% for i in range(1, 1+len(mp.rohm['alpha'])) %} {hrev_<<i>>}[1], {g_<<i>>}[1],{% endfor %} Norm[{b}]] , {b} ];
971
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
972
+ }
973
+ }
974
+ // Update of internal variables
975
+ For k In {1:N_rohm}
976
+ { Name Update_hrev~{k} ; Type FemEquation ;
977
+ Quantity {
978
+ { Name h; Type Local; NameOfSpace h_space; }
979
+ { Name b; Type Local; NameOfSpace b_or_h_space; }
980
+ { Name hrev~{k} ; Type Local ; NameOfSpace hrev~{k};}
981
+ { Name g~{k} ; Type Local ; NameOfSpace g~{k};}
982
+ }
983
+ Equation {
984
+ Galerkin { [ Dof{hrev~{k}}, {hrev~{k}} ];
985
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
986
+ Galerkin { [ - hrev_k[{h}, {hrev~{k}}[1], {g~{k}}[1], w_rohm~{k}, f_kappa[Norm[{b}]]*kappa_rohm~{k}, f_chi[Norm[{b}]]*chi_rohm~{k}, tau_c_rohm~{k}, tau_e_rohm~{k}], {hrev~{k}} ] ;
987
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
988
+ Galerkin { [ Dof{g~{k}}, {g~{k}} ];
989
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
990
+ Galerkin { [ - g_k[{h}, {hrev~{k}}[1], {g~{k}}[1], f_kappa[Norm[{b}]]*kappa_rohm~{k}], {g~{k}} ] ;
991
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
992
+ }
993
+ }
994
+ EndFor
995
+ {% endif %}
996
+ {% if dm.magnet.solve.rohf.enable %}
997
+ // Update of flux in hysteresis model
998
+ { Name Update_flux; Type FemEquation ;
999
+ Quantity {
1000
+ { Name h; Type Local; NameOfSpace h_space; }
1001
+ { Name flux; Type Local; NameOfSpace flux_space; }
1002
+ For k In {1:N_rohf}
1003
+ { Name jrev~{k} ; Type Local ; NameOfSpace jrev~{k};}
1004
+ { Name jreveddy~{k} ; Type Local ; NameOfSpace jreveddy~{k};}
1005
+ EndFor
1006
+ }
1007
+ Equation {
1008
+ Galerkin { [ Dof{flux} , {flux} ];
1009
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1010
+ // Templated for N cells
1011
+ Galerkin { [ - fluxdens[{d h} {% for i in range(1, 1+len(mp.rohf['alpha'])) %}, {jrev_<<i>>}[1], {jreveddy_<<i>>}[1]{% endfor %}], {flux} ];
1012
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1013
+ }
1014
+ }
1015
+ // Update of internal variables
1016
+ For k In {1:N_rohf}
1017
+ { Name Update_jrev~{k} ; Type FemEquation ;
1018
+ Quantity {
1019
+ { Name h; Type Local; NameOfSpace h_space; }
1020
+ { Name jrev~{k} ; Type Local ; NameOfSpace jrev~{k};}
1021
+ { Name jreveddy~{k}; Type Local; NameOfSpace jreveddy~{k}; }
1022
+ }
1023
+ Equation {
1024
+ Galerkin { [ Dof{jrev~{k}}, {jrev~{k}} ];
1025
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1026
+ Galerkin { [ - jrev_k[{d h}, {jrev~{k}}[1], {jreveddy~{k}}[1], kappa_rohf~{k}, tau_e_rohf~{k}], {jrev~{k}} ] ;
1027
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1028
+ Galerkin { [ Dof{jreveddy~{k}}, {jreveddy~{k}} ];
1029
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1030
+ Galerkin { [ - jreveddy_k[{d h}, {jreveddy~{k}}[1], kappa_rohf~{k}], {jreveddy~{k}} ] ;
1031
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1032
+ }
1033
+ }
1034
+ EndFor
1035
+ {% endif %}
1036
+ }
1037
+
1038
+ Macro CustomIterativeLoop
1039
+ // Compute first solution guess and residual at step $TimeStep
1040
+ Generate[A];
1041
+ Solve[A]; Evaluate[ $syscount = $syscount + 1 ];
1042
+ Generate[A]; GetResidual[A, $res0];
1043
+ Evaluate[ $res = $res0 ];
1044
+ Evaluate[ $iter = 0 ];
1045
+ Evaluate[ $convCrit = 1e99 ];
1046
+ PostOperation[MagDyn_energy];
1047
+ Print[{$iter, $res, $res / $res0, $indicLoss},
1048
+ Format "%g %14.12e %14.12e %14.12e", File infoResidualFile];
1049
+ // ----- Enter the iterative loop (hand-made) -----
1050
+ While[$convCrit > 1 && $res / $res0 <= 1e10 && $iter < iter_max]{
1051
+ Solve[A]; Evaluate[ $syscount = $syscount + 1 ];
1052
+ {% if dm.magnet.solve.rohm.enable %}
1053
+ Generate[B_OR_H]; Solve[B_OR_H]; // update {b} so that the field-dependent parameter is updated for the convergence criterion
1054
+ {% endif %}
1055
+ {% if dm.magnet.solve.rohf.enable %}
1056
+ Generate[FLUX]; Solve[FLUX]; // update {flux} so that the field-dependent parameter is updated for the convergence criterion
1057
+ {% endif %}
1058
+ Generate[A]; GetResidual[A, $res];
1059
+ Evaluate[ $iter = $iter + 1 ];
1060
+ Evaluate[ $indicLossOld = $indicLoss];
1061
+ PostOperation[MagDyn_energy];
1062
+ Print[{$iter, $res, $res / $res0, $indicLoss},
1063
+ Format "%g %14.12e %14.12e %14.12e", File infoResidualFile]; // Here, the loss is not the real one, as the memory fields used to compute it are not updated yet (for efficiency). To be possibly modified if this gets annoying.
1064
+ // Evaluate the convergence indicator
1065
+ Evaluate[ $relChangeACLoss = Abs[($indicLossOld - $indicLoss)/((Abs[$indicLossOld]>1e-7 || $iter < 10) ? $indicLossOld:1e-7)] ];
1066
+ Evaluate[ $convCrit = $relChangeACLoss/tol_energy];
1067
+ }
1068
+ Return
1069
+
1070
+ Resolution {
1071
+ { Name MagDyn;
1072
+ System {
1073
+ {Name A; NameOfFormulation MagDyn_hphi;}
1074
+ {% if dm.magnet.solve.rohm.enable %}
1075
+ {Name B_OR_H; NameOfFormulation Update_b; }
1076
+ For k In {1:N_rohm}
1077
+ {Name CELL_ROHM~{k}; NameOfFormulation Update_hrev~{k}; }
1078
+ EndFor
1079
+ {% endif %}
1080
+ {% if dm.magnet.solve.rohf.enable %}
1081
+ {Name FLUX; NameOfFormulation Update_flux; }
1082
+ For k In {1:N_rohf}
1083
+ {Name CELL_ROHF~{k}; NameOfFormulation Update_jrev~{k}; }
1084
+ EndFor
1085
+ {% endif %}
1086
+ }
1087
+ Operation {
1088
+ // Initialize directories
1089
+ CreateDirectory[resDirectory];
1090
+ DeleteFile[outputPowerFull];
1091
+ DeleteFile[outputPowerROHM];
1092
+ DeleteFile[outputPowerROHF];
1093
+ DeleteFile[infoResidualFile];
1094
+ // Initialize the solution (initial condition)
1095
+ SetTime[ timeStart ];
1096
+ SetDTime[ dt ];
1097
+ SetTimeStep[ 0 ];
1098
+ InitSolution[A];
1099
+ SaveSolution[A]; // Saves the solution x (from Ax = B) to .res file
1100
+ {% if dm.magnet.solve.rohm.enable %}
1101
+ InitSolution[B_OR_H]; SaveSolution[B_OR_H];
1102
+ For k In {1:N_rohm}
1103
+ InitSolution[CELL_ROHM~{k}]; SaveSolution[CELL_ROHM~{k}];
1104
+ EndFor
1105
+ {% endif %}
1106
+ {% if dm.magnet.solve.rohf.enable %}
1107
+ InitSolution[FLUX]; SaveSolution[FLUX];
1108
+ For k In {1:N_rohf}
1109
+ InitSolution[CELL_ROHF~{k}]; SaveSolution[CELL_ROHF~{k}];
1110
+ EndFor
1111
+ {% endif %}
1112
+ Evaluate[ $syscount = 0 ];
1113
+ Evaluate[ $saved = 1 ];
1114
+ Evaluate[ $elapsedCTI = 1 ]; // Number of control time instants already treated
1115
+ Evaluate[ $isCTI = 0 ];
1116
+
1117
+ Evaluate[ $indicLoss = 0 ]; // Put it to zero to avoid warnings
1118
+ Evaluate[ $power_tot = 0 ]; // Put it to zero to avoid warnings
1119
+ Evaluate[ $power_hyst_ROHM = 0 ]; // Put it to zero to avoid warnings
1120
+ Evaluate[ $power_hyst_c_ROHM = 0 ]; // Put it to zero to avoid warnings
1121
+ Evaluate[ $power_coupling_ROHM = 0 ]; // Put it to zero to avoid warnings
1122
+ Evaluate[ $power_eddy_ROHM = 0 ]; // Put it to zero to avoid warnings
1123
+ Evaluate[ $power_IS_coupling = 0 ]; // Put it to zero to avoid warnings
1124
+ Evaluate[ $power_hyst_ROHF = 0 ]; // Put it to zero to avoid warnings
1125
+ Evaluate[ $power_eddy_ROHF = 0 ]; // Put it to zero to avoid warnings
1126
+ Evaluate[ $power_ohmic = 0 ]; // Put it to zero to avoid warnings
1127
+ // ----- Enter implicit Euler time integration loop (hand-made) -----
1128
+ // Avoid too close steps at the end. Stop the simulation if the step becomes ridiculously small
1129
+ SetExtrapolationOrder[ extrapolationOrder ];
1130
+ // Print[{$Time}, Format "%g 0.0 0.0 0.0 0.0 0.0", File outputPower];
1131
+ While[$Time < timeFinal] {
1132
+ SetTime[ $Time + $DTime ]; // Time instant at which we are looking for the solution
1133
+ SetTimeStep[ $TimeStep + 1 ];
1134
+ {% if dm.magnet.solve.rohm.enable %}
1135
+ Generate[B_OR_H];
1136
+ For k In {1:N_rohm}
1137
+ Generate[CELL_ROHM~{k}];
1138
+ EndFor
1139
+ {% endif %}
1140
+ {% if dm.magnet.solve.rohf.enable %}
1141
+ Generate[FLUX];
1142
+ For k In {1:N_rohf}
1143
+ Generate[CELL_ROHF~{k}];
1144
+ EndFor
1145
+ {% endif %}
1146
+
1147
+ {% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear and dm.magnet.solve.source_parameters.source_type == 'piecewise'%}
1148
+ // Make sure all CTI are exactly chosen
1149
+ Evaluate[ $isCTI = 0 ];
1150
+ Test[$Time >= time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} - 1e-7 ]{
1151
+ Evaluate[ $isCTI = 1, $prevDTime = $DTime ]; // Also save the previous time step to restart from it after the CTI
1152
+ SetDTime[ time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} - $Time + $DTime ];
1153
+ SetTime[ time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} ]; // To compute exactly at the asked time instant
1154
+ Print[{$Time}, Format "*** Control time instant: %g s."];
1155
+ }
1156
+ {% endif %}
1157
+ // Iterative loop defined as a macro above
1158
+ Print[{$Time, $DTime, $TimeStep}, Format "Start new time step. Time: %g s. Time step: %g s. Step: %g."];
1159
+ Call CustomIterativeLoop;
1160
+ // Has it converged? If yes, save solution and possibly increase the time step...
1161
+ Test[ $iter < iter_max && ($res / $res0 <= 1e10 || $res0 == 0)]{
1162
+ Print[{$Time, $DTime, $iter}, Format "Converged time %g s with time step %g s in %g iterations."];
1163
+ // Save the solution of few time steps (small correction to avoid bad rounding)
1164
+ // Test[ $Time >= $saved * writeInterval - 1e-7 || $Time + $DTime >= timeFinal]{
1165
+ Test[ 1 ]{
1166
+ // Test[ $Time >= $saved * $DTime - 1e-7 || $Time + $DTime >= timeFinal]{
1167
+ SaveSolution[A];
1168
+ {% if dm.magnet.solve.rohm.enable %}
1169
+ Generate[B_OR_H]; Solve[B_OR_H]; SaveSolution[B_OR_H];
1170
+ For k In {1:N_rohm}
1171
+ Generate[CELL_ROHM~{k}]; Solve[CELL_ROHM~{k}]; SaveSolution[CELL_ROHM~{k}];
1172
+ EndFor
1173
+ {% endif %}
1174
+ {% if dm.magnet.solve.rohf.enable %}
1175
+ Generate[FLUX]; Solve[FLUX]; SaveSolution[FLUX];
1176
+ For k In {1:N_rohf}
1177
+ Generate[CELL_ROHF~{k}]; Solve[CELL_ROHF~{k}]; SaveSolution[CELL_ROHF~{k}];
1178
+ EndFor
1179
+ {% endif %}
1180
+
1181
+ PostOperation[MagDyn_energy_full];
1182
+ Print[{$Time, $saved}, Format "Saved time %g s (saved solution number %g). Output power infos:"];
1183
+ Print[{$Time, $power_tot, $power_hyst_ROHM, $power_hyst_c_ROHM, $power_coupling_ROHM, $power_eddy_ROHM, $power_IS_coupling, $power_hyst_ROHF, $power_eddy_ROHF, $power_ohmic},
1184
+ Format "%g %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e", File outputPowerFull];
1185
+ }
1186
+
1187
+ {% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear and dm.magnet.solve.source_parameters.source_type == 'piecewise' %}
1188
+ // Consider the time step before the control time instant (if relevant) and increment $elapsedCTI
1189
+ Test[ $isCTI == 1 ]{
1190
+ Evaluate[ $elapsedCTI = $elapsedCTI + 1 ];
1191
+ SetDTime[ $prevDTime ];
1192
+ }
1193
+ {% endif %}
1194
+ // Increase the step if we converged sufficiently "fast" (and not a control time instant)
1195
+ Test[ $iter < iter_max / 4 && $DTime < dt_max_var[] && $isCTI == 0 ]{
1196
+ Evaluate[ $dt_new = Min[$DTime * 2, dt_max_var[]] ];
1197
+ Print[{$dt_new}, Format "*** Fast convergence: increasing time step to %g"];
1198
+ SetDTime[$dt_new];
1199
+ }
1200
+ Test[ $DTime > dt_max_var[]]{
1201
+ Evaluate[ $dt_new = dt_max_var[] ];
1202
+ Print[{$dt_new}, Format "*** Variable maximum time-stepping: reducing time step to %g"];
1203
+ SetDTime[$dt_new];
1204
+ }
1205
+ }
1206
+ // ...otherwise, reduce the time step and try again
1207
+ {
1208
+ Evaluate[ $dt_new = $DTime / 2 ];
1209
+ Print[{$iter, $dt_new},
1210
+ Format "*** Non convergence (iter %g): recomputing with reduced step %g"];
1211
+ RemoveLastSolution[A];
1212
+ {% if dm.magnet.solve.rohm.enable %}
1213
+ RemoveLastSolution[B_OR_H];
1214
+ {% endif %}
1215
+ {% if dm.magnet.solve.rohf.enable %}
1216
+ RemoveLastSolution[FLUX];
1217
+ {% endif %}
1218
+ SetTime[$Time - $DTime];
1219
+ SetTimeStep[$TimeStep - 1];
1220
+ SetDTime[$dt_new];
1221
+ // If it gets ridicoulously small, end the simulation, and report the information in crash file.
1222
+ Test[ $dt_new < dt_max_var[]/10000 ]{
1223
+ Print[{$iter, $dt_new, $Time},
1224
+ Format "*** Non convergence (iter %g): time step %g too small, stopping the simulation at time %g s.", File crashReportFile];
1225
+ // Print[A];
1226
+ Exit;
1227
+ }
1228
+ }
1229
+ } // ----- End time loop -----
1230
+ // Print information about the resolution and the nonlinear iterations
1231
+ Print[{$syscount}, Format "Total number of linear systems solved: %g"];
1232
+ }
1233
+ }
1234
+ // Frequency domain resolution
1235
+ { Name MagDyn_freq;
1236
+ System {
1237
+ {Name A; NameOfFormulation MagDyn_hphi_freq; Type ComplexValue;}
1238
+ }
1239
+ Operation {
1240
+ // Initialize directories
1241
+ CreateDirectory[resDirectory];
1242
+ DeleteFile[pcrossingFile];
1243
+ DeleteFile[infoResidualFile];
1244
+ SetTimeStep[ 1 ];
1245
+
1246
+ {% if dm.magnet.solve.frequency_domain_solver.frequency_sweep.run_sweep %}
1247
+ For i In {0:nbFreq-1}
1248
+ SetFrequency[A, freq(i)];
1249
+ Evaluate[$f = freq(i)];
1250
+ Print[{$f, $TimeStep}, Format "Start new solution. f: %g Hz. Solution: %g."];
1251
+ Generate[A]; Solve[A]; SaveSolution[A];
1252
+ PostOperation[MagDyn_energy];
1253
+ Print[{$indicTotalLoss}, Format " - computed loss: %g."];
1254
+ SetTimeStep[$TimeStep + 1];
1255
+ EndFor
1256
+ {% else %}
1257
+ SetFrequency[A, f];
1258
+ Evaluate[$f = f];
1259
+ Print[{$f, $TimeStep}, Format "Start new solution. f: %g Hz. Solution: %g."];
1260
+ Generate[A]; Solve[A]; SaveSolution[A];
1261
+ PostOperation[MagDyn_energy];
1262
+ Print[{$indicTotalLoss}, Format " - computed loss: %g."];
1263
+ {% endif %}
1264
+ }
1265
+ }
1266
+
1267
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
1268
+ { Name Projection_h_to_h;
1269
+ System {
1270
+ {Name Projection_h_to_h; NameOfFormulation Projection_h_to_h; DestinationSystem A ;}
1271
+ }
1272
+ Operation {
1273
+ GmshRead[StrCat["../", "<<dm.magnet.solve.initial_conditions.pos_file_to_init_from>>", ".pos"]]; // This file has to be in format without mesh (no -v2, here with GmshParsed format)
1274
+ Generate[Projection_h_to_h]; Solve[Projection_h_to_h];
1275
+ TransferSolution[Projection_h_to_h];
1276
+ }
1277
+ }
1278
+ {% endif %}
1279
+ }
1280
+
1281
+
1282
+
1283
+ PostProcessing {
1284
+ { Name MagDyn_hphi; NameOfFormulation MagDyn_hphi;
1285
+ Quantity {
1286
+ // ----------------------------
1287
+ // ------- LOCAL fields -------
1288
+ // ----------------------------
1289
+ { Name phi; Value{ Local{ [ {dInv h} ] ;
1290
+ In OmegaCC; Jacobian Vol; } } }
1291
+ { Name h; Value{ Local{ [ {h} ] ;
1292
+ In Omega; Jacobian Vol; } } }
1293
+ { Name k; Value{ Local{ [ {k_IS} ] ;
1294
+ In OmegaC; Jacobian Vol; } } }
1295
+ { Name j; Value{ Local{ [ {d h} ] ;
1296
+ In OmegaC; Jacobian Vol; } } }
1297
+ { Name jz; Value{ Local{ [ CompZ[{d h}] ] ;
1298
+ In OmegaC; Jacobian Vol; } } }
1299
+ { Name b; Value {
1300
+ Term { [ mu[] * {h} ] ; In MagnLinDomain; Jacobian Vol; }
1301
+ {% if dm.magnet.solve.rohm.enable %}
1302
+ Term { [ {b} ] ; In MagnHystDomain; Jacobian Vol; }
1303
+ {% else %}
1304
+ Term { [ mu[] * {h} ] ; In MagnHystDomain; Jacobian Vol; }
1305
+ {% endif %}
1306
+ {% if dm.magnet.solve.formulation_parameters.hphia %}
1307
+ Term { [ {d a} ] ; In Omega_a; Jacobian Vol; }
1308
+ {% endif %}
1309
+ }
1310
+ }
1311
+ { Name hsVal; Value{ Term { [ hsVal[] ]; In Omega; } } }
1312
+ {% if dm.magnet.solve.rohf.enable %}
1313
+ { Name flux; Value{ Local{ [ {flux} ] ;
1314
+ In MagnHystDomain; Jacobian Vol; } } }
1315
+ {% endif %}
1316
+ {% if dm.magnet.solve.rohm.enable %}
1317
+ { Name m; Value{ Local{ [ {b} - mu0*{h} ] ;
1318
+ In MagnHystDomain; Jacobian Vol; } } }
1319
+ {% endif %}
1320
+ {% if dm.magnet.solve.formulation_parameters.hphia %}
1321
+ { Name a; Value{ Local{ [ {a} ] ;
1322
+ In Omega; Jacobian Vol; } } }
1323
+ {% endif %}
1324
+ // ----------------------------
1325
+ // ----- GLOBAL quantities ----
1326
+ // ----------------------------
1327
+ { Name I; Value { Term{ [ {I} ] ; In Cuts; } } }
1328
+ { Name V; Value { Term{ [ {V} ] ; In Cuts; } } }
1329
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
1330
+ { Name Ip; Value { Term{ [ {Ip} ] ; In PoweringCircuit; } } }
1331
+ { Name Vp; Value { Term{ [ {Vp} ] ; In PoweringCircuit; } } }
1332
+ {% endif %}
1333
+ { Name magnetization; Value{ Integral{ [ 0.5 * XYZ[] /\ {d h} ] ;
1334
+ In OmegaC; Integration Int; Jacobian Vol; } } } // Magnetization from current density only (does not include effects from ROHM)
1335
+ // ----------------------------
1336
+ // ----- POWER quantities -----
1337
+ // ----------------------------
1338
+ // NB: (h+h[1])/2 instead of h -> to avoid a constant sign error accumulation
1339
+ { Name power_tot_with_stored_energy_change; // WARNING: contains stored energy change! -> not only pure loss, so can be negative. Useful for convergence criterion
1340
+ Value{
1341
+ // DISCC model, IS coupling currents
1342
+ Integral{ [ (sigma_IS[] * {k_IS}) * {k_IS}] ;
1343
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1344
+ {% if dm.magnet.solve.rohm.enable %}
1345
+ // ROHM model (contains stored energy change! -> not only pure loss)
1346
+ Integral{ [ (bhyst[{h},{% for i in range(1, 1+len(mp.rohm['alpha'])) %} {hrev_<<i>>}[1], {g_<<i>>}[1],{% endfor %} Norm[{b}]] - {b}[1]) / $DTime * ({h}+{h}[1])/2 ] ;
1347
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1348
+ {% endif %}
1349
+ {% if dm.magnet.solve.rohf.enable %}
1350
+ // ROHF model (contains stored energy change! -> not only pure loss)
1351
+ Integral{ [ ({flux} - {flux}[1]) / $DTime * ({d h}+{d h}[1])/2 ] ;
1352
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1353
+ {% endif %}
1354
+ {% if dm.magnet.solve.general_parameters.superconductor_linear %}
1355
+ // Joule loss from linear Ohm's law
1356
+ Integral{ [rho[] * {d h} * {d h}] ;
1357
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1358
+ {% else %}
1359
+ // Joule loss from current sharing (CS)
1360
+ Integral{ [e_joule[{d h}] * {d h}] ;
1361
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1362
+ {% endif %}
1363
+ }
1364
+ }
1365
+ { Name power_tot; // Only the lossy contributions (should always be positive)
1366
+ Value{
1367
+ // DISCC model, IS coupling currents
1368
+ Integral{ [ (sigma_IS[] * {k_IS}) * {k_IS}] ;
1369
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1370
+ {% if dm.magnet.solve.rohm.enable %}
1371
+ // ROHM - Hyst uncoupled and eddy
1372
+ For k In {1:N_rohm}
1373
+ Integral { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w_rohm~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1374
+ In MagnHystDomain; Integration Int ; Jacobian Vol; }
1375
+ Integral { [ w_rohm~{k} * tau_e_rohm~{k} * mu0 * SquNorm[Dt[{hrev~{k}}]] ] ;
1376
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1377
+ EndFor
1378
+ // ROHM - Hyst coupled and IF coupling
1379
+ For k In {2:N_rohm}
1380
+ Integral { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}] * w_rohm~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]/tau_c_rohm~{k}) ] ;
1381
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1382
+ Integral { [ mu0 * SquNorm[hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]]/tau_c_rohm~{k} * w_rohm~{k} ] ;
1383
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1384
+ EndFor
1385
+ {% endif %}
1386
+ {% if dm.magnet.solve.rohf.enable %}
1387
+ // ROHF - Hyst and eddy
1388
+ For k In {1:N_rohf}
1389
+ Integral { [ 0.5 * ({d h} - {jreveddy~{k}} + {d h}[1] - {jreveddy~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{jrev~{k}}] ] ;
1390
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1391
+ Integral { [ w_rohf~{k} * tau_e_rohf~{k} * Lint0 * SquNorm[Dt[{jrev~{k}}]] ] ;
1392
+ In MagnHystDomain ; Integration Int ; Jacobian Vol; }
1393
+ EndFor
1394
+ {% endif %}
1395
+ {% if dm.magnet.solve.general_parameters.superconductor_linear %}
1396
+ // Joule loss from linear Ohm's law
1397
+ Integral{ [rho[] * {d h} * {d h}] ;
1398
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1399
+ {% else %}
1400
+ // Joule loss from current sharing (CS)
1401
+ Integral{ [e_joule[{d h}] * {d h}] ;
1402
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1403
+ {% endif %}
1404
+ }
1405
+ }
1406
+ { Name power_tot_local;
1407
+ Value{
1408
+ {% if dm.magnet.solve.rohm.enable %}
1409
+ // ROHM - Hyst uncoupled and eddy
1410
+ For k In {1:N_rohm}
1411
+ Term { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w_rohm~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1412
+ In MagnHystDomain; Jacobian Vol; }
1413
+ Term { [ w_rohm~{k} * tau_e_rohm~{k} * mu0 * SquNorm[Dt[{hrev~{k}}]] ] ;
1414
+ In MagnHystDomain ; Jacobian Vol; }
1415
+ EndFor
1416
+ // ROHM - Hyst coupled and IF coupling
1417
+ For k In {2:N_rohm}
1418
+ Term { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}] * w_rohm~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]/tau_c_rohm~{k}) ] ;
1419
+ In MagnHystDomain ; Jacobian Vol; }
1420
+ Term { [ mu0 * SquNorm[hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]]/tau_c_rohm~{k} * w_rohm~{k} ] ;
1421
+ In MagnHystDomain ; Jacobian Vol; }
1422
+ EndFor
1423
+ {% endif %}
1424
+ {% if dm.magnet.solve.rohf.enable %}
1425
+ // ROHF - Hyst and eddy
1426
+ For k In {1:N_rohf}
1427
+ Term { [ 0.5 * ({d h} - {jreveddy~{k}} + {d h}[1] - {jreveddy~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{jrev~{k}}] ] ;
1428
+ In MagnHystDomain ; Jacobian Vol;}
1429
+ Term { [ w_rohf~{k} * tau_e_rohf~{k} * Lint0 * SquNorm[Dt[{jrev~{k}}]] ] ;
1430
+ In MagnHystDomain ; Jacobian Vol;}
1431
+ EndFor
1432
+ {% endif %}
1433
+ {% if dm.magnet.solve.general_parameters.superconductor_linear %}
1434
+ // Joule loss from linear Ohm's law
1435
+ Term{ [rho[] * {d h} * {d h}] ;
1436
+ In OmegaC ; Jacobian Vol; }
1437
+ {% else %}
1438
+ // Joule loss from current sharing (CS)
1439
+ Term{ [e_joule[{d h}] * {d h}] ;
1440
+ In OmegaC ; Jacobian Vol; }
1441
+ {% endif %}
1442
+ // DISCC model, IS coupling currents
1443
+ Term{ [ (sigma_IS[] * {k_IS}) * {k_IS}] ;
1444
+ In OmegaC ; Jacobian Vol; }
1445
+
1446
+ }
1447
+ }
1448
+ // ----- DISCC related power quantity -----
1449
+ { Name power_IS_coupling;
1450
+ Value{
1451
+ Integral{ [ (sigma_IS[] * {k_IS}) * {k_IS}] ;
1452
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1453
+ }
1454
+ }
1455
+ {% if dm.magnet.solve.rohm.enable %}
1456
+ // ----- ROHM related power quantities -----
1457
+ { Name power_hyst_ROHM;
1458
+ Value{
1459
+ For k In {1:N_rohm}
1460
+ Integral { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w_rohm~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1461
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1462
+ EndFor
1463
+ }
1464
+ }
1465
+ { Name power_eddy_ROHM;
1466
+ Value{
1467
+ For k In {1:N_rohm}
1468
+ Integral { [ w_rohm~{k} * tau_e_rohm~{k} * mu0 * SquNorm[Dt[{hrev~{k}}]] ] ;
1469
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1470
+ EndFor
1471
+ }
1472
+ }
1473
+ { Name power_coupling_ROHM;
1474
+ Value{
1475
+ For k In {2:N_rohm} // starts at k=2 to avoid division by 0 in the first cell, coupling time constant MUST indeed be zero for the first cell for this to make sense
1476
+ Integral { [ mu0 * SquNorm[hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]]/tau_c_rohm~{k} * w_rohm~{k} ] ;
1477
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1478
+ EndFor
1479
+ }
1480
+ }
1481
+ { Name power_hyst_c_ROHM;
1482
+ Value{
1483
+ For k In {2:N_rohm} // starts at k=2 to avoid division by 0 in the first cell, coupling time constant MUST indeed be zero for the first cell for this to make sense
1484
+ Integral { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}] * w_rohm~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]/tau_c_rohm~{k}) ] ;
1485
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1486
+ EndFor
1487
+ }
1488
+ }
1489
+ { Name power_tot_local_ROHM;
1490
+ Value{
1491
+ For k In {1:N_rohm}
1492
+ Term { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w_rohm~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1493
+ In MagnHystDomain; Jacobian Vol; }
1494
+ Term { [ w_rohm~{k} * tau_e_rohm~{k} * mu0 * SquNorm[Dt[{hrev~{k}}]] ] ;
1495
+ In MagnHystDomain ; Jacobian Vol; }
1496
+ EndFor
1497
+ For k In {2:N_rohm} // starts at k=2 to avoid division by 0 in the first cell, coupling time constant MUST indeed be zero for the first cell for this to make sense
1498
+ Term { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}] * w_rohm~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]/tau_c_rohm~{k}) ] ;
1499
+ In MagnHystDomain ; Jacobian Vol; }
1500
+ Term { [ mu0 * SquNorm[hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c_rohm~{k}, chi_rohm~{k}]]/tau_c_rohm~{k} * w_rohm~{k} ] ;
1501
+ In MagnHystDomain ; Jacobian Vol; }
1502
+ EndFor
1503
+ }
1504
+ }
1505
+ {% endif %}
1506
+ {% if dm.magnet.solve.rohf.enable %}
1507
+ // ----- ROHM related power quantities -----
1508
+ { Name power_hyst_ROHF;
1509
+ Value{
1510
+ For k In {1:N_rohf}
1511
+ Integral { [ 0.5 * ({d h} - {jreveddy~{k}} + {d h}[1] - {jreveddy~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{jrev~{k}}] ] ;
1512
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1513
+ EndFor
1514
+ }
1515
+ }
1516
+ { Name power_eddy_ROHF;
1517
+ Value{
1518
+ For k In {1:N_rohf}
1519
+ Integral { [ w_rohf~{k} * tau_e_rohf~{k} * Lint0 * SquNorm[Dt[{jrev~{k}}]] ] ;
1520
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1521
+ EndFor
1522
+ }
1523
+ }
1524
+ { Name power_total_local_ROHF;
1525
+ Value{
1526
+ For k In {1:N_rohf}
1527
+ Term { [ 0.5 * ({d h} - {jreveddy~{k}} + {d h}[1] - {jreveddy~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{jrev~{k}}] ] ;
1528
+ In MagnHystDomain ; Jacobian Vol;}
1529
+ Term { [ w_rohf~{k} * tau_e_rohf~{k} * Lint0 * SquNorm[Dt[{jrev~{k}}]] ] ;
1530
+ In MagnHystDomain ; Jacobian Vol;}
1531
+ EndFor
1532
+ }
1533
+ }
1534
+ {% endif %}
1535
+ // ----- Joule power quantities -----
1536
+ { Name power_ohmic;
1537
+ Value{
1538
+ {% if dm.magnet.solve.general_parameters.superconductor_linear %}
1539
+ Integral{ [rho[] * {d h} * {d h}] ;
1540
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1541
+ {% else %}
1542
+ Integral{ [e_joule[{d h}] * {d h}] ;
1543
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1544
+ {% endif %}
1545
+ }
1546
+ }
1547
+ { Name power_local_ohmic;
1548
+ Value{
1549
+ {% if dm.magnet.solve.general_parameters.superconductor_linear %}
1550
+ Term{ [rho[] * {d h} * {d h}] ;
1551
+ In OmegaC ; Jacobian Vol; }
1552
+ {% else %}
1553
+ Term{ [e_joule[{d h}] * {d h}] ;
1554
+ In OmegaC ; Jacobian Vol; }
1555
+ {% endif %}
1556
+ }
1557
+ }
1558
+ }
1559
+ }
1560
+ { Name MagDyn_hphi_freq; NameOfFormulation MagDyn_hphi_freq;
1561
+ Quantity {
1562
+ { Name phi; Value{ Local{ [ {dInv h} ] ;
1563
+ In OmegaCC; Jacobian Vol; } } }
1564
+ { Name h; Value{ Local{ [ {h} ] ;
1565
+ In Omega; Jacobian Vol; } } }
1566
+ { Name k; Value{ Local{ [ {k_IS} ] ;
1567
+ In OmegaC; Jacobian Vol; } } }
1568
+ { Name b; Value { Local { [ mu[] * {h} ] ;
1569
+ In MagnLinDomain; Jacobian Vol; } } }
1570
+ { Name j; Value{ Local{ [ {d h} ] ;
1571
+ In Omega; Jacobian Vol; } } }
1572
+ { Name jz; Value{ Local{ [ CompZ[{d h}] ] ;
1573
+ In Omega; Jacobian Vol; } } }
1574
+ { Name power_crossing;
1575
+ Value{
1576
+ Local{ [0.5 * (sigma_IS[] * {k_IS}) * Conj[{k_IS}]] ;
1577
+ In OmegaC ; Jacobian Vol; }
1578
+ }
1579
+ }
1580
+ { Name total_power_crossing;
1581
+ Value{
1582
+ Integral{ [0.5 * (sigma_IS[] * {k_IS}) * Conj[{k_IS}]] ;
1583
+ In OmegaC ; Integration Int ; Jacobian Vol; }
1584
+ }
1585
+ }
1586
+ { Name I; Value { Term{ [ {I} ] ; In Cuts; } } }
1587
+ { Name V; Value { Term{ [ {V} ] ; In Cuts; } } }
1588
+ }
1589
+ }
1590
+ }
1591
+ PostOperation {
1592
+ { Name MagDyn;
1593
+ NameOfPostProcessing MagDyn_hphi;
1594
+ Operation {
1595
+ // Local field solutions
1596
+ {% if dm.magnet.postproc.generate_pos_files %}
1597
+ Print[ j, OnElementsOf Cables , File StrCat["js.pos"], Name "js [A/m2]" ];
1598
+ Print[ k, OnElementsOf Cables , File StrCat["k.pos"], Name "k [V]" ];
1599
+ Print[ b, OnElementsOf Omega , File StrCat["b.pos"], Name "b [T]" ];
1600
+ //Print[ h, OnElementsOf Omega , File StrCat["h.pos"], Name "h [A/m]" ];
1601
+ Print[ power_tot_local, OnElementsOf Cables , File StrCat["p_tot.pos"], Name "p_tot [W/m3]" ];
1602
+ {% if dm.magnet.solve.rohm.enable %}
1603
+ Print[ m, OnElementsOf Cables , File StrCat["m.pos"], Name "m [T]" ];
1604
+ {% endif %}
1605
+ {% if dm.magnet.solve.rohf.enable %}
1606
+ // Print[ flux, OnElementsOf MagnHystDomain , File StrCat["flux_ROHF.pos"], Name "flux_ROHF [Wb/m]" ];
1607
+ {% endif %}
1608
+ {% endif %}
1609
+ // Global solutions
1610
+ Print[ I, OnRegion Cuts, File StrCat[resDirectory, "/It.txt"], Format SimpleTable];
1611
+ Print[ V, OnRegion Cuts, File StrCat[resDirectory, "/Vt.txt"], Format SimpleTable];
1612
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
1613
+ Print[ Ip, OnRegion PoweringCircuit, File StrCat[resDirectory,"/Ip.txt"], Format SimpleTable];
1614
+ Print[ Vp, OnRegion PoweringCircuit, File StrCat[resDirectory,"/Vp.txt"], Format SimpleTable];
1615
+ {% endif %}
1616
+ {% if dm.magnet.postproc.save_last_magnetic_field != "None" %}
1617
+ // Last magnetic field solution for projection. Note the special format GmshParsed required for proper GmshRead[] operation in the later pre-resolution.
1618
+ Print[ h, OnElementsOf Omega, Format GmshParsed , File StrCat["../", "<<dm.magnet.postproc.save_last_magnetic_field>>", ".pos"], Name "h [A/m]", LastTimeStepOnly ];
1619
+ {% endif %}
1620
+ {% for i in range(0, len(rm.powered.Cables.vol.numbers)) %}
1621
+ Print[ power_tot[Cable_<<i+1>>], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_cable_<<i+1>>.txt"] ];
1622
+ {% endfor %}
1623
+
1624
+ // Print[ power_tot[Omega], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_tot.txt"] ];
1625
+ // Print[ power_IS_coupling[Omega], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_IS.txt"] ];
1626
+ // {% if dm.magnet.solve.rohm.enable %}
1627
+ // Print[ power_hyst_ROHM[Cables], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_hyst_ROHM.txt"]];
1628
+ // Print[ power_eddy_ROHM[Cables], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_eddy_ROHM.txt"]];
1629
+ // Print[ power_hyst_c_ROHM[Cables], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_hyst_c_ROHM.txt"]];
1630
+ // Print[ power_coupling_ROHM[Cables], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_coupling_ROHM.txt"]];
1631
+ // {% endif %}
1632
+ // {% if dm.magnet.solve.rohf.enable %}
1633
+ // Print[ power_hyst_ROHF[Omega], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_hyst_ROHF.txt"]];
1634
+ // Print[ power_eddy_ROHF[Omega], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_eddy_ROHF.txt"]];
1635
+ // {% endif %}
1636
+ // Print[ power_ohmic[Omega], OnGlobal, Format TimeTable, File StrCat[resDirectory,"/power_ohmic.txt"]];
1637
+ }
1638
+ }
1639
+ { Name MagDyn_energy; LastTimeStepOnly 1 ;
1640
+ NameOfPostProcessing MagDyn_hphi;
1641
+ Operation {
1642
+ Print[ power_tot_with_stored_energy_change[Omega], OnGlobal, Format Table, StoreInVariable $indicLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1643
+ }
1644
+ }
1645
+ { Name MagDyn_energy_full; LastTimeStepOnly 1 ;
1646
+ NameOfPostProcessing MagDyn_hphi;
1647
+ Operation {
1648
+ Print[ power_tot[Omega], OnGlobal, Format Table, StoreInVariable $power_tot, File StrCat[resDirectory,"/dummy.txt"] ];
1649
+ Print[ power_IS_coupling[Omega], OnGlobal, Format Table, StoreInVariable $power_IS_coupling, File StrCat[resDirectory,"/dummy.txt"] ];
1650
+ {% if dm.magnet.solve.rohm.enable %}
1651
+ Print[ power_hyst_ROHM[Omega], OnGlobal, Format Table, StoreInVariable $power_hyst_ROHM, File StrCat[resDirectory,"/dummy.txt"] ];
1652
+ Print[ power_eddy_ROHM[Omega], OnGlobal, Format Table, StoreInVariable $power_eddy_ROHM, File StrCat[resDirectory,"/dummy.txt"] ];
1653
+ Print[ power_hyst_c_ROHM[Omega], OnGlobal, Format Table, StoreInVariable $power_hyst_c_ROHM, File StrCat[resDirectory,"/dummy.txt"] ];
1654
+ Print[ power_coupling_ROHM[Omega], OnGlobal, Format Table, StoreInVariable $power_coupling_ROHM, File StrCat[resDirectory,"/dummy.txt"] ];
1655
+ {% endif %}
1656
+ {% if dm.magnet.solve.rohf.enable %}
1657
+ Print[ power_hyst_ROHF[Omega], OnGlobal, Format Table, StoreInVariable $power_hyst_ROHF, File StrCat[resDirectory,"/dummy.txt"] ];
1658
+ Print[ power_eddy_ROHF[Omega], OnGlobal, Format Table, StoreInVariable $power_eddy_ROHF, File StrCat[resDirectory,"/dummy.txt"] ];
1659
+ {% endif %}
1660
+ Print[ power_ohmic[Omega], OnGlobal, Format Table, StoreInVariable $power_ohmic, File StrCat[resDirectory,"/dummy.txt"] ];
1661
+ }
1662
+ }
1663
+ }