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,1742 @@
1
+ Group {
2
+ // ------- PROBLEM DEFINITION -------
3
+ // Filaments
4
+ Strands = Region[{<<rm.powered.Strands.vol.numbers|join(', ')>>}];
5
+ BndStrands = Region[{<<rm.powered.Strands.surf.numbers|join(', ')>>}];
6
+
7
+ // Individual regions for the strands
8
+ {% for i in range(0, len(rm.powered.Strands.vol.numbers)) %}
9
+ Strand_<<i+1>> = Region[{<<rm.powered.Strands.vol.numbers[i]>>}];
10
+ StrandBnd_<<i+1>> = Region[{<<rm.powered.Strands.surf.numbers[i]>>}];
11
+ {% endfor %}
12
+
13
+ Coating = Region[{<<rm.powered.Coating.vol.numbers[0]>>}];
14
+ CoatingBnd = Region[{<<rm.powered.Coating.surf_out.numbers[0]>>}];
15
+
16
+ Air = Region[ {<<rm.air.vol.number>>} ];
17
+ BndAir = Region[ {<<rm.air.surf.number>>} ];
18
+ InnerBndAir = Region[ {<<rm.air.point.numbers|join(', ')>>} ];
19
+
20
+ Coils = Region[{<<rm.powered.ExcitationCoils.vol.numbers|join(', ')>>}];
21
+ BndCoils = Region[{<<rm.powered.ExcitationCoils.surf.numbers|join(', ')>>}];
22
+ {% for i in range(0, len(rm.powered.ExcitationCoils.vol.numbers)) %}
23
+ Coil_<<i+1>> = Region[{<<rm.powered.ExcitationCoils.vol.numbers[i]>>}];
24
+ CoilBnd_<<i+1>> = Region[{<<rm.powered.ExcitationCoils.surf.numbers[i]>>}];
25
+ {% endfor %}
26
+
27
+ // Cuts
28
+ StrandCuts = Region[{<<rm.powered.Strands.cochain.numbers|join(', ')>>}];
29
+ CoatingCut = Region[{<<rm.powered.Coating.cochain.numbers[0]>>}]; // Coating cut
30
+ CoilCuts = Region[{<<rm.powered.ExcitationCoils.cochain.numbers|join(', ')>>}];
31
+ Cuts = Region[{StrandCuts, CoatingCut, CoilCuts}]; // All the cuts
32
+ // Individual cuts for the strands
33
+ {% for i in range(0, len(rm.powered.Strands.cochain.numbers)) %}
34
+ Cut_<<i+1>> = Region[{<<rm.powered.Strands.cochain.numbers[i]>>}];
35
+ {% endfor %}
36
+ // Individual cuts for the strands
37
+ {% for i in range(0, len(rm.powered.ExcitationCoils.cochain.numbers)) %}
38
+ CutCoil_<<i+1>> = Region[{<<rm.powered.ExcitationCoils.cochain.numbers[i]>>}];
39
+ {% endfor %}
40
+
41
+ // Split into conducting and non-conducting domains, discriminating between stranded regions and massive ones
42
+ LinOmegaC = Region[ {Coating} ];
43
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
44
+ NonLinOmegaC = Region[ {} ];
45
+ OmegaC_stranded = Region[ {Strands} ];
46
+ BndOmegaC_stranded = Region[ {BndStrands} ];
47
+ {% else %}
48
+ NonLinOmegaC = Region[ {Strands} ];
49
+ OmegaC_stranded = Region[ {} ];
50
+ BndOmegaC_stranded = Region[ {} ];
51
+ {% endif %}
52
+
53
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
54
+ MagnLinDomain = Region[ {Air, Coating, Coils} ];
55
+ MagnHystDomain = Region[ {Strands} ];
56
+ {% else %}
57
+ MagnLinDomain = Region[ {Air, Coating, Strands, Coils} ];
58
+ MagnHystDomain = Region[ {} ];
59
+ {% endif %}
60
+
61
+ BndOmegaC = Region[ {CoatingBnd, InnerBndAir, BndStrands} ];
62
+ OmegaC = Region[ {LinOmegaC, NonLinOmegaC} ];
63
+ OmegaCC = Region[ {Air, OmegaC_stranded, Coils} ];
64
+ OmegaC_and_stranded = Region[ {OmegaC, OmegaC_stranded} ];
65
+ Omega = Region[ {OmegaC, OmegaCC} ]; // the whole domain (only surfaces in 2D)
66
+
67
+ OmegaC_AndBnd = Region[{OmegaC, BndOmegaC}]; // useful for function space definition (support of shape functions extended to the boundaries of domains)
68
+ OmegaCC_AndBnd = Region[{OmegaCC, BndOmegaC, BndAir}]; // idem
69
+
70
+ // Here we define points on the boundaries of the filaments and the outer matrix boundary. These points are used to fix the magnetic potential to zero on the boundaries.
71
+ StrandPointsOnBoundaries = Region[{<<rm.powered.Strands.curve.numbers|join(', ')>>}];
72
+ CoatingPointsOnBoundaries = Region[{<<rm.powered.Coating.curve.numbers[0]>>}];
73
+ ArbitraryPoints = Region[{CoatingPointsOnBoundaries, 9}];
74
+
75
+ // Resistors for crossing contact resistance (by contrast with what is done in https://ieeexplore.ieee.org/abstract/document/10812063, oblique resistance are not used separately, but considered directly in the crossing ones)
76
+ Resistors_crossing = Region[{}];
77
+ {% for i in range(1, int(len(rm.powered.Strands.cochain.numbers)/2)) %}
78
+ R_crossing_<<i>> = Region[{<<5000+i>>}];
79
+ Resistors_crossing += Region[{R_crossing_<<i>>}];
80
+ {% endfor %}
81
+
82
+ // Resistors for adjacent contact resistance
83
+ Resistors_adjacent = Region[{}];
84
+ {% for i in range(1, len(rm.powered.Strands.vol.numbers)+1) %}
85
+ R_adjacent_<<i>> = Region[{<<10000+i>>}];
86
+ Resistors_adjacent += Region[{R_adjacent_<<i>>}];
87
+ {% endfor %}
88
+
89
+ Resistors = Region[{Resistors_crossing, Resistors_adjacent}];
90
+
91
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
92
+ // Regions for electrical circuit for transport current and voltage
93
+ CurrentSource = Region[ {10000000} ];
94
+ PoweringCircuit = Region[ {CurrentSource} ]; // Groups containg all circuit elements for the transport current
95
+ ParallelResistor = Region[ {10000001} ];
96
+ PoweringCircuit += Region[ {ParallelResistor} ];
97
+ {% endif %}
98
+ }
99
+
100
+ Function{
101
+ // ------- GEOMETRY PARAMETERS -------
102
+ N_strands = <<len(rm.powered.Strands.vol.numbers)>>; // Number of strands
103
+ N_crossing_resistors = N_strands/2 - 1; // Number of crossing resistors
104
+ ell = 1.0 * <<dm.conductors[dm.magnet.solve.conductor_name].cable.strand_twist_pitch>> / <<len(rm.powered.Strands.vol.numbers)>>; // Periodicity length
105
+
106
+ // ------- MATERIAL PARAMETERS - MAGNETIC -------
107
+ mu0 = Pi*4e-7; // [H/m]
108
+ nu0 = 1.0/mu0; // [m/H]
109
+
110
+ // Further steps to be done in case this model is used as a standalone model (not done here as the nonlinear version of this Rutherford model is currently only used
111
+ // as a verification model for the HomogenizedConductor model, so the current implementation is kept for simplicity, for now):
112
+ // - template all this with parameters from input files, and free numbers of cells, for both ROHM and ROHF
113
+ // - use compiled C++ functions instead of scripted ones as below (as is done for HomogenizedConductor)
114
+ // - include I-dependence in ROHM (not trivial since it combines local and global quantities)
115
+ // - include b-dependence in ROHF & PL/current sharing (for Ic and coercivity, not trivial for the same reason as above)
116
+ // - include temperature dependence in ROHM, ROHF, and other material parameters (easy if we assume uniform temperature)
117
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
118
+ mu[Coating] = mu0;
119
+ nu[Coating] = nu0;
120
+ mu[Air] = mu0;
121
+ nu[Air] = nu0;
122
+ mu[Coils] = mu0;
123
+ nu[Coils] = nu0;
124
+ // ROHM Model for strands
125
+ N = 5;
126
+ // Weights (-)
127
+ w_1 = 0.23;
128
+ w_2 = 0.31;
129
+ w_3 = 0.29;
130
+ w_4 = 0.13;
131
+ w_5 = 0.04;
132
+ // Uncoupled irreversibility parameter (A/m)
133
+ kappa_1 = 0; // A/m, first one must be zero, this is mandatory
134
+ kappa_2 = 0; // A/m
135
+ kappa_3 = 0.25/mu0; // A/m
136
+ kappa_4 = 0.5/mu0; // A/m
137
+ kappa_5 = 0.75/mu0; // A/m
138
+ // Coupled (minus uncoupled) irreversibility parameter (A/m)
139
+ chi_1 = 0; // A/m, first one must be zero, this is mandatory
140
+ chi_2 = 1.5/mu0; // A/m
141
+ chi_3 = 0.7/mu0; // A/m
142
+ chi_4 = 1.2/mu0; // A/m
143
+ chi_5 = 1.2/mu0; // A/m
144
+ // Coupling time constants (s)
145
+ tau_c_Val = 0.35; // s
146
+ tau_c_1 = 0;
147
+ tau_c_2 = 0.5*tau_c_Val;
148
+ tau_c_3 = tau_c_Val;
149
+ tau_c_4 = tau_c_Val;
150
+ tau_c_5 = tau_c_Val;
151
+ // Eddy current time constants (s)
152
+ tau_e_Val = 1e-4; // s
153
+ tau_e_1 = tau_e_Val;
154
+ tau_e_2 = tau_e_Val;
155
+ tau_e_3 = tau_e_Val;
156
+ tau_e_4 = tau_e_Val;
157
+ tau_e_5 = tau_e_Val;
158
+ // Multiplier for the field-dependent irreversibilty parameter
159
+ list_f_kappa = {0.00000000e+00, 1.00000000e+00, 9.39597315e-02, 9.70532886e-01,
160
+ 1.87919463e-01, 9.08385278e-01, 2.81879195e-01, 8.25986815e-01,
161
+ 3.75838926e-01, 7.38862115e-01, 4.69798658e-01, 6.63868696e-01,
162
+ 5.63758389e-01, 6.07033231e-01, 6.57718121e-01, 5.62773567e-01,
163
+ 7.51677852e-01, 5.26772394e-01, 8.45637584e-01, 4.96552160e-01,
164
+ 9.39597315e-01, 4.70616295e-01, 1.03355705e+00, 4.47956409e-01,
165
+ 1.12751678e+00, 4.27859492e-01, 1.22147651e+00, 4.09816324e-01,
166
+ 1.31543624e+00, 3.93747334e-01, 1.40939597e+00, 3.79298723e-01,
167
+ 1.50335570e+00, 3.66109142e-01, 1.59731544e+00, 3.53990385e-01,
168
+ 1.69127517e+00, 3.42796324e-01, 1.78523490e+00, 3.32399089e-01,
169
+ 1.87919463e+00, 3.22699151e-01, 1.97315436e+00, 3.13616338e-01,
170
+ 2.06711409e+00, 3.05079435e-01, 2.16107383e+00, 2.97028765e-01,
171
+ 2.25503356e+00, 2.89415278e-01, 2.34899329e+00, 2.82196893e-01,
172
+ 2.44295302e+00, 2.75334654e-01, 2.53691275e+00, 2.68796409e-01,
173
+ 2.63087248e+00, 2.62555621e-01, 2.72483221e+00, 2.56585778e-01,
174
+ 2.81879195e+00, 2.50864851e-01, 2.91275168e+00, 2.45374155e-01,
175
+ 3.00671141e+00, 2.40096149e-01, 3.10067114e+00, 2.35014644e-01,
176
+ 3.19463087e+00, 2.30115890e-01, 3.28859060e+00, 2.25388074e-01,
177
+ 3.38255034e+00, 2.20818839e-01, 3.47651007e+00, 2.16397919e-01,
178
+ 3.57046980e+00, 2.12116612e-01, 3.66442953e+00, 2.07965874e-01,
179
+ 3.75838926e+00, 2.03937695e-01, 3.85234899e+00, 2.00025201e-01,
180
+ 3.94630872e+00, 1.96221977e-01, 4.04026846e+00, 1.92521514e-01,
181
+ 1.07114094e+01, 4.22119189e-02, 1.08053691e+01, 4.07794262e-02,
182
+ 1.08993289e+01, 3.93539509e-02, 1.09932886e+01, 3.79351159e-02,
183
+ 1.10872483e+01, 3.65225668e-02, 1.11812081e+01, 3.51159648e-02,
184
+ 1.12751678e+01, 3.37149413e-02, 1.13691275e+01, 3.23190965e-02,
185
+ 1.14630872e+01, 3.09280383e-02, 1.15570470e+01, 2.95413741e-02,
186
+ 1.16510067e+01, 2.81586397e-02, 1.17449664e+01, 2.67793730e-02,
187
+ 1.18389262e+01, 2.54030907e-02, 1.19328859e+01, 2.40292464e-02,
188
+ 1.20268456e+01, 2.26572523e-02, 1.21208054e+01, 2.12864688e-02,
189
+ 1.22147651e+01, 1.99161765e-02, 1.23087248e+01, 1.85455626e-02,
190
+ 1.24026846e+01, 1.71737023e-02, 1.24966443e+01, 1.57994954e-02,
191
+ 1.25906040e+01, 1.44216598e-02, 1.26845638e+01, 1.30386263e-02,
192
+ 1.27785235e+01, 1.16483848e-02, 1.28724832e+01, 1.02483184e-02,
193
+ 1.29664430e+01, 8.83483853e-03, 1.30604027e+01, 7.40244796e-03,
194
+ 1.31543624e+01, 5.94103353e-03, 1.32483221e+01, 4.45222537e-03,
195
+ 1.33422819e+01, 3.13219576e-03, 1.34362416e+01, 2.03642832e-03,
196
+ 1.35302013e+01, 1.16778951e-03, 1.36241611e+01, 5.31251257e-04,
197
+ 1.37181208e+01, 1.36044320e-04, 1.38120805e+01, 5.43279830e-07,
198
+ 1.39060403e+01, 0.00000000e+00, 1.40000000e+01, 0.00000000e+00};
199
+ // Field-dependent parameters
200
+ f_kappa[] = InterpolationLinear[$1]{List[list_f_kappa]}; // TO DO: refine this scaling and introduce dependence on transport current if this model is used as standalone
201
+ f_chi[] = (1 - $1/14)/(1 + $1/5); // TO DO: same
202
+
203
+ // --- Test for a hysteresis element: gives the reversible field in the static case
204
+ // $1: new field
205
+ // $2: previous reversible field
206
+ // $3: irreversibility parameter
207
+ U[] = (Norm[$1 - $2] <= $3) ? $2 : ($1 - $3 * ($1 - $2) / Norm[$1 - $2]);
208
+ // Derivative w.r.t. new field
209
+ dUdh[] = (Norm[$1 - $2]#9 <= $3) ? TensorSym[0., 0., 0., 0., 0., 0.] :
210
+ (TensorSym[1., 0., 0., 1., 0., 1.] - $3 / #9 * (TensorSym[1., 0., 0., 1., 0., 1.] - SquDyadicProduct[$1-$2] / (#9)^2 ));
211
+ // --- Test for a hysteresis element: gives the r+e+c field in the dynamic case
212
+ // $1: new field
213
+ // $2: previous reversible field
214
+ // $3: previous rev+eddy+coupling field
215
+ // $4: irreversibility parameter
216
+ Urec[] = (Norm[$1 - $3] <= $4 && ( ($1 - $2) * (($1 - $2)*Norm[$1 - $2] - $4 * ($1 - $2))) <= 0) ? $2 : ($1 - $4 * ($1 - $2) / Norm[$1 - $2]);
217
+ // Derivative w.r.t. new field
218
+ dUrecdh[] = (Norm[$1 - $3] <= $4 && ( ($1 - $2) * (($1 - $2)*Norm[$1 - $2] - $4 * ($1 - $2))) <= 0) ? TensorSym[0., 0., 0., 0., 0., 0.] :
219
+ (TensorSym[1., 0., 0., 1., 0., 1.] - $4 / (Norm[$1-$2]) * (TensorSym[1., 0., 0., 1., 0., 1.] - SquDyadicProduct[$1-$2] / (Norm[$1-$2])^2 ));
220
+
221
+ // --- Functions for one cell only
222
+ // Function for reversible field only, for one cell
223
+ // $1: new field
224
+ // $2: reversible field at previous time step
225
+ // $3: rev+eddy+coupling field at previous time step
226
+ // $4: w_k, weight for the considered cell k
227
+ // $5: kappa_k, uncoupled irreversibility parameter for the considered cell k
228
+ // $6: chi_k, coupled (minus uncoupled) irreversibility parameter for the considered cell k
229
+ // $7: tau_c_k, coupling current time constant for the considered cell k
230
+ // $8: tau_e_k, eddy current time constant for the considered cell k
231
+ // hrev_k[] = (U[$1, $3, $5] + (tau_e/$DTime)#1*$2)/(1+#1) ;
232
+ hrev_k[] = (($7/$DTime)#1 * Norm[Urec[$1, $2, $3, $5] - $2]#3 <= $6 * (1 + #1 + ($8/$DTime)#2)) ?
233
+ (Urec[$1, $2, $3, $5] + (#1+#2)*$2)/(1+#1+#2) :
234
+ (Urec[$1, $2, $3, $5] - $6*(Urec[$1, $2, $3, $5] - $2)/(#3) + #2*$2)/(1+#2); // Careful here division by norm (cannot be exactly zero because of the test above, but could be very small for the first cell!)
235
+ // Function for rev+eddy+coupling field, for one cell
236
+ // $1: new field
237
+ // $2: reversible field at previous time step
238
+ // $3: rev+eddy+coupling field at previous time step
239
+ // $4: irreversibility parameter for the considered cell k
240
+ g_k[] = Urec[$1, $2, $3, $4];
241
+ // Derivative of the reversible field, for one cell
242
+ // Same parameters as the function for the reversible field $1 -> $8
243
+ dhrev_k[] = (($7/$DTime)#1 * Norm[Urec[$1, $2, $3, $5] - $2]#3 <= $6 * (1 + #1 + ($8/$DTime)#2)) ?
244
+ (dUrecdh[$1, $2, $3, $5])/(1+#1+#2) :
245
+ (dUrecdh[$1, $2, $3, $5] - $6 * 1/(#3)*(TensorSym[1., 0., 0., 1., 0., 1.]-SquDyadicProduct[Urec[$1, $2, $3, $5]-$2]/(#3)^2) * dUrecdh[$1, $2, $3, $5])/(1+#2);
246
+ // Coupling field from time derivative of flux density b_k
247
+ // $1: \dot b_k
248
+ // $2: norm of b
249
+ // $3: tau_c_k
250
+ // $4: chi_k
251
+ hcoupling[] = ($3/mu0 * Norm[$1] <= f_chi[$2] * $4) ? $3/mu0 * $1 : f_chi[$2] * $4 * $1 / Norm[$1];
252
+
253
+ // --- Main hysteresis law
254
+ // $1: new field
255
+ // $2*k: reversible field at previous time step for cell k
256
+ // $2*k+1: g = rev+eddy+coupling field at previous time step for cell k
257
+ // $2*N+2: norm of b, for field-dependent parameters
258
+ bhyst[] = mu0 * ( w_1 * hrev_k[$1, $2, $3, w_1, f_kappa[$12]*kappa_1, f_chi[$12]*chi_1, tau_c_1, tau_e_1]
259
+ + w_2 * hrev_k[$1, $4, $5, w_2, f_kappa[$12]*kappa_2, f_chi[$12]*chi_2, tau_c_2, tau_e_2]
260
+ + w_3 * hrev_k[$1, $6, $7, w_3, f_kappa[$12]*kappa_3, f_chi[$12]*chi_3, tau_c_3, tau_e_3]
261
+ + w_4 * hrev_k[$1, $8, $9, w_4, f_kappa[$12]*kappa_4, f_chi[$12]*chi_4, tau_c_4, tau_e_4]
262
+ + w_5 * hrev_k[$1, $10,$11,w_5, f_kappa[$12]*kappa_5, f_chi[$12]*chi_5, tau_c_5, tau_e_5]);
263
+ // Derivative w.r.t. new field
264
+ dbhystdh[] = mu0 * ( w_1 * TensorDiag[1., 1., 1.]/(1+tau_e_1/$DTime)
265
+ + w_2 * dhrev_k[$1, $4, $5, w_2, f_kappa[$12]*kappa_2, f_chi[$12]*chi_2, tau_c_2, tau_e_2]
266
+ + w_3 * dhrev_k[$1, $6, $7, w_3, f_kappa[$12]*kappa_3, f_chi[$12]*chi_3, tau_c_3, tau_e_3]
267
+ + w_4 * dhrev_k[$1, $8, $9, w_4, f_kappa[$12]*kappa_4, f_chi[$12]*chi_4, tau_c_4, tau_e_4]
268
+ + w_5 * dhrev_k[$1, $10,$11,w_5, f_kappa[$12]*kappa_5, f_chi[$12]*chi_5, tau_c_5, tau_e_5]);
269
+ {% else %}
270
+ mu[Omega] = mu0;
271
+ nu[Omega] = nu0;
272
+ {% endif %}
273
+
274
+ // ------- MATERIAL PARAMETERS - ELECTRIC -------
275
+ // Contact resistances for circuit equations
276
+ R[Resistors_crossing] = 0.5 * <<dm.magnet.solve.general_parameters.crossing_coupling_resistance>>; // (Ohm) // Crossing contact resistance between strands, multiplication by 0.5 to account for oblique resistors which are not modelled separately (for better symmetry in results)
277
+ R[Resistors_adjacent] = <<dm.magnet.solve.general_parameters.adjacent_coupling_resistance>>; // (Ohm) // Adjacent contact resistance between strands
278
+ // Coating region resistivity
279
+ rho[LinOmegaC] = <<dm.magnet.solve.general_parameters.rho_coating>>; // (Ohm*m)
280
+ // Strand resistivity
281
+ rho[Strands] = <<dm.magnet.solve.general_parameters.rho_strands>>; // (Ohm*m) when modelled as massive conductors
282
+
283
+ {% if dm.magnet.solve.formulation_parameters.rohf %}
284
+ // ROHF model for stranded strands
285
+ Lint0 = mu0 / (4*Pi);
286
+ // ROHF Model Parameters
287
+ N_rohf = 5;
288
+ // Weights (-)
289
+ w_rohf_1 = 0.01;
290
+ w_rohf_2 = 0.05;
291
+ w_rohf_3 = 0.1;
292
+ w_rohf_4 = 0.5;
293
+ w_rohf_5 = 2.0;
294
+ // Irreversibility parameters (A)
295
+ kappa_rohf_1 = 0; // A, must be zero, this is MANDATORY!
296
+ kappa_rohf_2 = 120; // A
297
+ kappa_rohf_3 = 220; // A
298
+ kappa_rohf_4 = 250; // A
299
+ kappa_rohf_5 = 350; // A
300
+ // Eddy current time constants (s)
301
+ tau_e_rohf_1 = 1.5e-5; // s
302
+ tau_e_rohf_2 = 2e-4; // s
303
+ tau_e_rohf_3 = 2e-4; // s
304
+ tau_e_rohf_4 = 2e-4; // s
305
+ tau_e_rohf_5 = 2e-4; // s
306
+
307
+ // --- Reversible current in dynamic case
308
+ // $1: new current
309
+ // $2: previous reversible + eddy current (G)
310
+ // $3: irreversibility parameter
311
+ G[] = (Norm[$1 - $2]#1 <= $3) ? $2 : $1 - $3 * ($1 - $2) / #1;
312
+ dGdI[] = (Norm[$1 - $2] <= $3) ? 0.0 : 1.0;
313
+ // $1: new current
314
+ // $2: previous reversible current
315
+ // $3: previous reversible + eddy current (G)
316
+ // $4: irreversibility parameter
317
+ // $5: time constant
318
+ Irev_k[] = G[$1, $3, $4]#1 - $5 / ($DTime + $5) * (#1 - $2);
319
+ dIrev_kdI[] = dGdI[$1, $3, $4]#1 - $5 * #1 / ($DTime + $5);
320
+ G_k[] = G[$1, $2, $3];
321
+ // --- Main hysteresis law, written as the difference with respect to the linear case
322
+ // $1: new total current
323
+ // $(2*k): reversible current at previous time step for cell k
324
+ // $(2*k+1): reversible current + eddy (G) at previous time step for cell k
325
+ DeltaFluxhyst[] = Lint0 * (w_rohf_1 * Irev_k[$1, $2, $3, kappa_rohf_1, tau_e_rohf_1]
326
+ + w_rohf_2 * Irev_k[$1, $4, $5, kappa_rohf_2, tau_e_rohf_2]
327
+ + w_rohf_3 * Irev_k[$1, $6, $7, kappa_rohf_3, tau_e_rohf_3]
328
+ + w_rohf_4 * Irev_k[$1, $8, $9, kappa_rohf_4, tau_e_rohf_4]
329
+ + w_rohf_5 * Irev_k[$1, $10,$11,kappa_rohf_5, tau_e_rohf_5]
330
+ - 0*$1); // this contribution is removed in the formulation directly (and not here, hence the 0*)
331
+
332
+ dDeltaFluxhystdI[] = Lint0 * (w_rohf_1 * dIrev_kdI[$1, $2, $3, kappa_rohf_1, tau_e_rohf_1] //1.0
333
+ + w_rohf_2 * dIrev_kdI[$1, $4, $5, kappa_rohf_2, tau_e_rohf_2]
334
+ + w_rohf_3 * dIrev_kdI[$1, $6, $7, kappa_rohf_3, tau_e_rohf_3]
335
+ + w_rohf_4 * dIrev_kdI[$1, $8, $9, kappa_rohf_4, tau_e_rohf_4]
336
+ + w_rohf_5 * dIrev_kdI[$1, $10,$11,kappa_rohf_5, tau_e_rohf_5]
337
+ - 0*1); // this contribution is removed in the formulation directly (and not here, hence the 0*)
338
+
339
+ DeltaFluxhyst_prev[] = Lint0 *(w_rohf_1 * $2
340
+ + w_rohf_2 * $3
341
+ + w_rohf_3 * $4
342
+ + w_rohf_4 * $5
343
+ + w_rohf_5 * $6
344
+ - 0*$1); // this contribution is removed in the formulation directly (and not here, hence the 0*)
345
+
346
+ {% endif %}
347
+
348
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
349
+ // --- Transport current - Resistive Voltage relationship in the strand
350
+ // Power law for the superconducting filaments
351
+ Ic[] = <<dm.magnet.solve.general_parameters.superconductor_Ic>>; // Critical current of the strand (A)
352
+ n = <<dm.magnet.solve.general_parameters.superconductor_n_value>>; // Power law index (n)
353
+ ec = 1e-4; // Voltage per unit length at critical current (V/m)
354
+ // Resistance (per unit length) of the conducting matrix
355
+ R_matrix[] = <<dm.magnet.solve.general_parameters.matrix_resistance>>; // rho_matrix/area_matrix;
356
+ // Simplified current sharing relationship (power law until derivative equals matrix resistance, then constant slope; continuous and continuously differentiable)
357
+ I_threshold[] = (R_matrix[] * Ic[]^n / (n * ec))^(1/(n-1));
358
+ V_resistance[] = (Abs[$1] < I_threshold[]) ? ec * (Abs[$1]/Ic[])^n * Sign[$1] : (R_matrix[] * (Abs[$1] - I_threshold[]) + ec * (I_threshold[]/Ic[])^n) * Sign[$1] ;
359
+ dV_resistance_dI[] = (Abs[$1] < I_threshold[]) ? ec/Ic[] * n * (Abs[$1]/Ic[])^(n-1) : R_matrix[];
360
+ {% endif %}
361
+
362
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
363
+ {% if isinstance(dm.magnet.solve.source_parameters.parallel_resistor, float) %}
364
+ R[ParallelResistor] = <<dm.magnet.solve.source_parameters.parallel_resistor>>; // Resistance of the parallel resistor
365
+ {% else %}
366
+ R[ParallelResistor] = 1.0; // Default resistance of 1 Ohm for the parallel resistor
367
+ {% endif %}
368
+ {% endif %}
369
+
370
+ // ------- SOURCE PARAMETERS -------
371
+ bmax = <<dm.magnet.solve.source_parameters.sine.field_amplitude>>; // Maximum applied magnetic induction [T]
372
+ f = <<dm.magnet.solve.source_parameters.sine.frequency>>; // Frequency of applied field [Hz]
373
+ Imax = <<dm.magnet.solve.source_parameters.sine.current_amplitude>>; // Maximum transport current [A]
374
+
375
+ {% if dm.magnet.solve.frequency_domain_solver.frequency_sweep.run_sweep %}
376
+ nbFreq = <<dm.magnet.solve.frequency_domain_solver.frequency_sweep.number_of_frequencies>>; // How many frequencies in the frequency domain?
377
+ 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];
378
+ {% endif %}
379
+
380
+ // Direction and value of applied field
381
+ {% if dm.magnet.solve.source_parameters.source_type == 'sine' %} // Sine wave source (potentially with DC component)
382
+ time_multiplier = 1;
383
+
384
+ ramp_duration = -0.05/f;
385
+
386
+ 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>>;
387
+ I_transport[] = constant_I_transport[] + <<dm.magnet.solve.source_parameters.sine.current_amplitude>> * Sin[2*Pi*f * $Time];
388
+
389
+ constant_field_direction[] = Vector[0., 1., 0.];
390
+ directionApplied[] = Vector[Cos[<<dm.magnet.solve.source_parameters.sine.field_angle>>*Pi/180], Sin[<<dm.magnet.solve.source_parameters.sine.field_angle>>*Pi/180], 0.];
391
+
392
+ 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>>;
393
+ 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>>;
394
+
395
+ 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);
396
+ 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);
397
+
398
+ {% elif dm.magnet.solve.source_parameters.source_type == 'piecewise' %}
399
+ time_multiplier = <<dm.magnet.solve.source_parameters.piecewise.time_multiplier>>;
400
+ applied_field_multiplier = <<dm.magnet.solve.source_parameters.piecewise.applied_field_multiplier>>;
401
+ transport_current_multiplier = <<dm.magnet.solve.source_parameters.piecewise.transport_current_multiplier>>;
402
+ directionApplied[] = Vector[Cos[<<dm.magnet.solve.source_parameters.piecewise.field_angle>>*Pi/180], Sin[<<dm.magnet.solve.source_parameters.piecewise.field_angle>>*Pi/180], 0.];
403
+
404
+ {% if dm.magnet.solve.source_parameters.piecewise.source_csv_file %} // Source from CSV file
405
+ timeList() = {<<ed['time']|join(', ')>>};
406
+ bappList() = {<<ed['b']|join(', ')>>};
407
+ IList() = {<<ed['I']|join(', ')>>};
408
+ time_bapp_List() = ListAlt[timeList(), bappList()];
409
+ time_I_List() = ListAlt[timeList(), IList()];
410
+
411
+ hsVal[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{List[time_bapp_List()]} * directionApplied[];
412
+ hsVal_prev[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time-$DTime)/time_multiplier]]{List[time_bapp_List()]} * directionApplied[];
413
+ I_transport[] = transport_current_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{List[time_I_List()]};
414
+
415
+ {% else %} // Source from parameters
416
+ times_source_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.times|join(', ')>>};
417
+ transport_currents_relative_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.transport_currents_relative|join(', ')>>};
418
+ applied_fields_relative_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.applied_fields_relative|join(', ')>>};
419
+
420
+ hsVal[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), applied_fields_relative_piecewise_linear()]} * directionApplied[];
421
+ hsVal_prev[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time-$DTime)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), applied_fields_relative_piecewise_linear()]} * directionApplied[];
422
+ I_transport[] = transport_current_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), transport_currents_relative_piecewise_linear()]};
423
+ {% endif %}
424
+ {% endif %}
425
+
426
+ // For the natural boundary condition (restricted to fields of constant direction for the moment, should be generalized)
427
+ dbsdt[] = mu0 * (hsVal[] - hsVal_prev[]) / $DTime; // must be a finite difference to avoid error accumulation
428
+
429
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
430
+ // Excitation coils from file
431
+ timeList() = {<<ed['time']|join(', ')>>};
432
+ {% if dm.magnet.solve.source_parameters.excitation_coils.source_csv_file %}
433
+ {% for i in range(1, 1+len(rm.powered.ExcitationCoils.vol.numbers)) %}
434
+ I_<<i>>_list() = {<<ed['I'+str(i)]|join(', ')>>};
435
+ time_I_<<i>>_List() = ListAlt[timeList(), I_<<i>>_list()];
436
+ I_<<i>>[] = InterpolationLinear[Max[0,($Time)]]{List[time_I_<<i>>_List()]};
437
+ {% endfor %}
438
+ {% else %}
439
+ I_1[] = + 2016 * (($Time < 2.0) ? 0.0 : 1.0) * Sin[2*Pi*f*$Time]; // For E-CLIQ test case in https://arxiv.org/abs/2510.24618
440
+ I_2[] = - 2016 * (($Time < 2.0) ? 0.0 : 1.0) * Sin[2*Pi*f*$Time]; // For E-CLIQ test case in https://arxiv.org/abs/2510.24618
441
+ {% endif %}
442
+ {% endif %}
443
+
444
+ // ------- NUMERICAL PARAMETERS -------
445
+ timeStart = 0.; // Initial time [s]
446
+
447
+ {% if dm.magnet.solve.source_parameters.source_type == 'sine'%}
448
+ timeFinal = <<dm.magnet.solve.numerical_parameters.sine.number_of_periods_to_simulate>>/f; // Final time for source definition (s)
449
+ dt = 1 / (f*<<dm.magnet.solve.numerical_parameters.sine.timesteps_per_period>>); // Time step (initial if adaptive) (s)
450
+ dt_max = dt; // Fixed maximum time step
451
+ dt_max_var[] = dt_max;
452
+ {% else %}
453
+ timeFinal = <<dm.magnet.solve.numerical_parameters.piecewise.time_to_simulate>>;
454
+
455
+ {% if dm.magnet.solve.numerical_parameters.piecewise.variable_max_timestep %}
456
+ times_max_timestep_piecewise_linear() = {<<dm.magnet.solve.numerical_parameters.piecewise.times_max_timestep_piecewise_linear|join(', ')>>};
457
+ max_timestep_piecewise_linear() = {<<dm.magnet.solve.numerical_parameters.piecewise.max_timestep_piecewise_linear|join(', ')>>};
458
+ dt = max_timestep_piecewise_linear(0);
459
+ dt_max_var[] = InterpolationLinear[Max[0,$Time]]{ListAlt[times_max_timestep_piecewise_linear(), max_timestep_piecewise_linear()]};
460
+ {% else %}
461
+ dt = timeFinal / <<dm.magnet.solve.numerical_parameters.piecewise.timesteps_per_time_to_simulate>>;
462
+ dt_max = dt; // Fixed maximum time step
463
+ dt_max_var[] = dt_max;
464
+ {% endif %}
465
+
466
+ {% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear%}
467
+ control_time_instants_list() = {<<dm.magnet.solve.source_parameters.piecewise.times|join(', ')>>, 1e99}; // last one is just to avoid 'seg. fault' errors
468
+ {% endif %}
469
+
470
+ {% endif %}
471
+
472
+ iter_max = 200; // Maximum number of iterations (after which we exit the iterative loop)
473
+ extrapolationOrder = 1; // Extrapolation order for predictor
474
+ tol_energy = 1e-6; // Tolerance on the relative change of the power indicator
475
+ writeInterval = dt; // Time interval to save the solution [s]
476
+
477
+ // ------- Source Current -------
478
+ Flag_save_hs = 0; // For debugging purposes, to see what are the computed source current and fields for stranded conductors
479
+ Is0[] = Vector[0, 0, 1]; // source current of unit amplitude (A)
480
+
481
+ // ------- SIMULATION NAME -------
482
+ name = "txt_files";
483
+ resDirectory = StrCat["./",name];
484
+ infoResidualFile = StrCat[resDirectory,"/residual.txt"];
485
+ outputPowerROHM = StrCat[resDirectory,"/power_ROHM.txt"]; // File updated during runtime
486
+ outputPowerROHF = StrCat[resDirectory,"/power_ROHF.txt"];
487
+ crashReportFile = StrCat[resDirectory,"/crash_report.txt"];
488
+
489
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
490
+ 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[]
491
+ {% endif %}
492
+
493
+ }
494
+
495
+ Constraint {
496
+ { Name phi ;
497
+ Case {
498
+ {% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %} // For natural boundary condition (in formulation)
499
+ {Region ArbitraryPoints ; Value 0.0 ;} // Fix the magnetic potential to zero on the boundaries of the filaments and the outer matrix boundary
500
+ {% elif dm.magnet.solve.source_parameters.boundary_condition_type == 'Essential' %}
501
+ {Region BndAir ; Type Assign ; Value XYZ[]*directionApplied[] ; TimeFunction hsVal[] * directionApplied[] ;} // Essential boundary condition (not compatible with transport current)
502
+ {% endif %}
503
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
504
+ {Region Omega ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
505
+ {% endif %}
506
+ }
507
+ }
508
+ { Name Current ;
509
+ Case {
510
+ {% if dm.magnet.solve.frequency_domain_solver.enable %}
511
+ {Region CoatingCut ; Value Complex[Imax,0];} // Contraint for the total transport current
512
+ {% else %}
513
+ {% if not dm.magnet.solve.source_parameters.parallel_resistor %}
514
+ {Region CoatingCut ; Type Assign ; Value 1.0 ; TimeFunction I_transport[] ;} // Contraint for the total transport current
515
+ {% endif %}
516
+ {% endif %}
517
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
518
+ {Region Cuts ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
519
+ {% endif %}
520
+ // {Region Cuts ; Type Assign ; Value 0. ;} // for debugging (or to model fully uncoupled filaments without transport current)
521
+ }
522
+ }
523
+ { Name Voltage ; Case {} } // Empty to avoid warnings
524
+ { Name Voltage_s ; Case {} } // Empty to avoid warnings
525
+ { Name Current_Cir ;
526
+ Case {
527
+ // { Region Resistors ; Value 0.0 ; }
528
+ // { Region Strands ; Value 0.0 ; }
529
+ }
530
+ }
531
+ { Name Voltage_Cir ; Case {} } // Empty to avoid warnings
532
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
533
+ { Name Current_Cir_transport ;
534
+ Case {
535
+ {Region CurrentSource ; Value 1.0 ; TimeFunction I_transport[] ;}
536
+ }
537
+ } // Empty to avoid warnings
538
+ { Name Voltage_Cir_transport ; Case {} } // Empty to avoid warnings
539
+ {% endif %}
540
+ // This is the key constraint for coupling global quantities: it contains the links between the filaments
541
+ {Name ElectricalCircuit ; Type Network ;
542
+ Case circuit {
543
+ // 1) Branching between strands accounting for transposition
544
+ {% for i in range(1, len(rm.powered.Strands.cochain.numbers)+1) %}
545
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
546
+ {Region Strand_<<i>> ; Branch { <<i>>, <<i % len(rm.powered.Strands.cochain.numbers) + 1 >> } ;}
547
+ {% else %}
548
+ {Region Cut_<<i>> ; Branch { <<i>>, <<i % len(rm.powered.Strands.cochain.numbers) + 1 >> } ;}
549
+ {% endif %}
550
+ {% endfor %}
551
+ // 2) Adding crossing contact resistance connections
552
+ {% for i in range(1, int(len(rm.powered.Strands.cochain.numbers)/2)) %}
553
+ {Region R_crossing_<<i>> ; Branch { <<i+1>>, <<len(rm.powered.Strands.cochain.numbers) - (i-1) >> } ;}
554
+ {% endfor %}
555
+ // // 3) Adding oblique contact resistances (not done anymore; instead, the crossing resistance is twice smaller to account for oblique connections)
556
+ // {% for i in range(1,len(rm.powered.Strands.cochain.numbers)+1) %}
557
+ // {% if i <= int(len(rm.powered.Strands.cochain.numbers)/2) %}
558
+ // {Region R_crossing_oblique_<<i>> ; Branch { <<i>>, <<len(rm.powered.Strands.cochain.numbers) - (i-1) >> } ;}
559
+ // {%else%}
560
+ // {Region R_crossing_oblique_<<i>> ; Branch { <<i%len(rm.powered.Strands.cochain.numbers)+1>>, <<len(rm.powered.Strands.cochain.numbers)+2 -i >> } ;}
561
+ // {%endif%}
562
+ // {% endfor %}
563
+ // 4) Adding adjacent contact resistance connections
564
+ {% for i in range(1, len(rm.powered.Strands.cochain.numbers)+1) %}
565
+ {Region R_adjacent_<<i>> ; Branch { <<i>>, <<i % len(rm.powered.Strands.cochain.numbers) + 1 >> } ;}
566
+ {% endfor %}
567
+ }
568
+ }
569
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
570
+ {Name ElectricalCircuit_transport ; Type Network ;
571
+ Case circuit1 {
572
+ {Region CoatingCut ; Branch { 2, 1 } ;}
573
+ {Region CurrentSource ; Branch { 1, 2 } ;}
574
+ {Region ParallelResistor ; Branch { 1, 2 } ;}
575
+ }
576
+ }
577
+ {% endif %}
578
+ { Name h ; Type Assign ;
579
+ Case {
580
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
581
+ {Region OmegaC ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
582
+ {% endif %}
583
+ }
584
+ }
585
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
586
+ // Gauging condition for the source field
587
+ {% for i in range(0, len(rm.powered.Strands.vol.numbers)) %}
588
+ { Name GaugeCondition_hs_<<i+1>> ; Type Assign ;
589
+ Case {
590
+ { Region Strand_<<i+1>> ; SubRegion StrandBnd_<<i+1>> ; Value 0. ; }
591
+ }
592
+ }
593
+ {% endfor %}
594
+ // Constraint for the source field, such that it is associated with a unit current (basis function)
595
+ { Name Current_hs ; Type Assign ;
596
+ Case {
597
+ { Region Cuts; Value 1.0;}
598
+ }
599
+ }
600
+ { Name Current_s ; Type Assign ;
601
+ Case {
602
+ // { Region OmegaC_stranded; Value 1.0; TimeFunction Sin[2*Pi*f * $Time];}
603
+ }
604
+ }
605
+ {% endif %}
606
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
607
+ {% for i in range(0, len(rm.powered.ExcitationCoils.vol.numbers)) %}
608
+ { Name GaugeCondition_hs_coil_<<i+1>> ; Type Assign ;
609
+ Case {
610
+ { Region Coil_<<i+1>> ; SubRegion CoilBnd_<<i+1>> ; Value 0. ; }
611
+ }
612
+ }
613
+ {% endfor %}
614
+ { Name Current_hs_coil ; Type Assign ;
615
+ Case {
616
+ { Region Cuts; Value 1.0;}
617
+ }
618
+ }
619
+ { Name Current_coil ; Type Assign ;
620
+ Case {
621
+ {% for i in range(0, len(rm.powered.ExcitationCoils.vol.numbers)) %}
622
+ { Region Coil_<<i+1>>; Value 1.0; TimeFunction I_<<i+1>>[];}
623
+ {% endfor %}
624
+ }
625
+ }
626
+ {% endif %}
627
+ }
628
+
629
+ Jacobian {
630
+ { Name Vol ;
631
+ Case {
632
+ {Region All ; Jacobian Vol ;}
633
+ }
634
+ }
635
+ { Name Sur ;
636
+ Case {
637
+ { Region All ; Jacobian Sur ; }
638
+ }
639
+ }
640
+ }
641
+
642
+ Integration {
643
+ { Name Int ;
644
+ Case {
645
+ { Type Gauss ;
646
+ Case {
647
+ { GeoElement Point ; NumberOfPoints 1 ; }
648
+ { GeoElement Line ; NumberOfPoints 3 ; }
649
+ { GeoElement Triangle ; NumberOfPoints 3 ; }
650
+ }
651
+ }
652
+ }
653
+ }
654
+ // For efficient assembly in hysteretic elements, integration of {b} and bhyst[{h}] which are constant per element AND mostly to avoid systematic numerical integration error.
655
+ { Name Int_b ;
656
+ Case {
657
+ { Type Gauss ;
658
+ Case {
659
+ { GeoElement Triangle ; NumberOfPoints 1 ; }
660
+ { GeoElement Quadrangle ; NumberOfPoints 1 ; }
661
+ }
662
+ }
663
+ }
664
+ }
665
+ }
666
+
667
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
668
+ For i In {1 : <<len(rm.powered.Strands.vol.numbers)>>}
669
+ // Source field definition (must be done above the rest)
670
+ FunctionSpace {
671
+ // Function space for the source field (defined during pre-resolution, and then included as a sub-space in the main h_space)
672
+ { Name hs_space~{i}; Type Form1;
673
+ BasisFunction {
674
+ { Name psie; NameOfCoef he; Function BF_Edge;
675
+ Support Strand~{i}; Entity EdgesOf[All, Not StrandBnd~{i}]; }
676
+ { Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
677
+ Support Omega; Entity GroupsOfEdgesOf[Cut~{i}]; }
678
+ }
679
+ Constraint {
680
+ { NameOfCoef he; EntityType EdgesOfTreeIn; EntitySubType StartingOn;
681
+ NameOfConstraint GaugeCondition_hs~{i}; }
682
+ { NameOfCoef Ii ; EntityType GroupsOfEdgesOf ; NameOfConstraint Current_hs ; }
683
+ }
684
+ }
685
+ }
686
+ Formulation{
687
+ // Formulation for source currents in strands
688
+ { Name js_to_hs~{i} ; Type FemEquation ;
689
+ Quantity {
690
+ { Name hs ; Type Local ; NameOfSpace hs_space~{i} ; }
691
+ }
692
+ Equation {
693
+ Galerkin { [ Dof{d hs}, {d hs} ] ;
694
+ In Strand~{i} ; Jacobian Vol ; Integration Int ; }
695
+ Galerkin { [ - Is0[]/SurfaceArea[], {d hs} ] ;
696
+ In Strand~{i} ; Jacobian Vol ; Integration Int ; }
697
+ }
698
+ }
699
+ }
700
+ Resolution{
701
+ { Name js_to_hs~{i} ;
702
+ System {
703
+ { Name Sys_Mag ; NameOfFormulation js_to_hs~{i} ; }
704
+ }
705
+ Operation {
706
+ Generate Sys_Mag ; Solve Sys_Mag ;
707
+ If(Flag_save_hs == 1) PostOperation[js_to_hs~{i}] ; SaveSolution Sys_Mag ; EndIf
708
+ }
709
+ }
710
+ }
711
+ PostProcessing{
712
+ { Name js_to_hs~{i} ; NameOfFormulation js_to_hs~{i} ;
713
+ PostQuantity {
714
+ { Name hs ; Value { Term { [ {hs} ] ; Jacobian Vol ;
715
+ In Omega ; } } }
716
+ { Name js ; Value { Term { [ {d hs} ] ; Jacobian Vol ;
717
+ In Omega ; } } }
718
+ { Name js0 ; Value { Term { [ Is0[]/SurfaceArea[] ] ;
719
+ In Omega ; Jacobian Vol ; } } }
720
+ }
721
+ }
722
+ }
723
+ PostOperation{
724
+ { Name js_to_hs~{i}; NameOfPostProcessing js_to_hs~{i};
725
+ Operation{
726
+ Print[ hs, OnElementsOf Omega , File Sprintf("hs_%g.pos", i), Name "hs [A/m]" ];
727
+ Print[ js, OnElementsOf Strand~{i} , File Sprintf("js_%g.pos", i), Name "js [A/m2]" ];
728
+ Print[ js0, OnElementsOf Strand~{i} , File Sprintf("js0_%g.pos", i), Name "js0 [A/m2]" ];
729
+ }
730
+ }
731
+ }
732
+ EndFor
733
+ {% endif %}
734
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
735
+ For i In {1 : <<len(rm.powered.ExcitationCoils.vol.numbers)>>}
736
+ FunctionSpace {
737
+ // Function space for the source field (defined during pre-resolution, and then included as a sub-space in the main h_space)
738
+ { Name hs_coil_space~{i}; Type Form1;
739
+ BasisFunction {
740
+ { Name psie; NameOfCoef he; Function BF_Edge;
741
+ Support Coil~{i}; Entity EdgesOf[All, Not CoilBnd~{i}]; }
742
+ { Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
743
+ Support Omega; Entity GroupsOfEdgesOf[CutCoil~{i}]; }
744
+ }
745
+ Constraint {
746
+ { NameOfCoef he; EntityType EdgesOfTreeIn; EntitySubType StartingOn;
747
+ NameOfConstraint GaugeCondition_hs_coil~{i}; }
748
+ { NameOfCoef Ii ; EntityType GroupsOfEdgesOf ; NameOfConstraint Current_hs_coil ; }
749
+ }
750
+ }
751
+ }
752
+ Formulation{
753
+ // Formulation for source currents in coils
754
+ { Name js_to_hs_coil~{i} ; Type FemEquation ;
755
+ Quantity {
756
+ { Name hs ; Type Local ; NameOfSpace hs_coil_space~{i} ; }
757
+ }
758
+ Equation {
759
+ Galerkin { [ Dof{d hs}, {d hs} ] ;
760
+ In Coil~{i} ; Jacobian Vol ; Integration Int ; }
761
+ Galerkin { [ - Is0[]/SurfaceArea[], {d hs} ] ;
762
+ In Coil~{i} ; Jacobian Vol ; Integration Int ; }
763
+ }
764
+ }
765
+ }
766
+ Resolution{
767
+ { Name js_to_hs_coil~{i} ;
768
+ System {
769
+ { Name Sys_Mag ; NameOfFormulation js_to_hs_coil~{i} ; }
770
+ }
771
+ Operation {
772
+ Generate Sys_Mag ; Solve Sys_Mag ;
773
+ }
774
+ }
775
+ }
776
+ EndFor
777
+ {% endif %}
778
+
779
+ FunctionSpace {
780
+ // Function space for magnetic field h in h-conform formulation. Main field for the magnetodynamic problem.
781
+ // h = sum phi_n * grad(psi_n) (nodes in Omega_CC with boundary)
782
+ // + sum h_e * psi_e (edges in Omega_C)
783
+ // + sum I_i * c_i (cuts, global basis functions for net current intensity)
784
+ // + [TBC]
785
+ { Name h_space; Type Form1;
786
+ BasisFunction {
787
+ { Name gradpsin; NameOfCoef phin; Function BF_GradNode;
788
+ Support OmegaCC_AndBnd; Entity NodesOf[OmegaCC]; } // Extend support to boundary for surface integration (e.g. useful for weak B.C.)
789
+ { Name gradpsin; NameOfCoef phin2; Function BF_GroupOfEdges;
790
+ Support OmegaC; Entity GroupsOfEdgesOnNodesOf[BndOmegaC]; } // To treat properly the Omega_CC-Omega_C boundary
791
+ { Name psie; NameOfCoef he; Function BF_Edge;
792
+ Support OmegaC_AndBnd; Entity EdgesOf[All, Not BndOmegaC]; }
793
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
794
+ { Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
795
+ Support Omega; Entity GroupsOfEdgesOf[CoatingCut]; } // The region Cuts contains the union of all the relevant cuts (cohomology basis function support)
796
+ { Name sb ; NameOfCoef Is ; // Global Basis Function
797
+ Function BF_Global {
798
+ Quantity hs ;
799
+ Formulation js_to_hs {<<len(rm.powered.Strands.vol.numbers)>>} ;
800
+ Group OmegaC_stranded ; Resolution js_to_hs {<<len(rm.powered.Strands.vol.numbers)>>} ;
801
+ } ;
802
+ Support OmegaC_and_stranded ; Entity Global [OmegaC_stranded] ; }
803
+ {% else %}
804
+ { Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
805
+ Support Omega; Entity GroupsOfEdgesOf[CoatingCut, StrandCuts]; } // The region Cuts contains the union of all the relevant cuts (cohomology basis function support)
806
+ {% endif %}
807
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
808
+ { Name sb_coil ; NameOfCoef Ic ; // Global Basis Function
809
+ Function BF_Global {
810
+ Quantity hs ;
811
+ Formulation js_to_hs_coil {<<len(rm.powered.ExcitationCoils.vol.numbers)>>} ;
812
+ Group Coils ; Resolution js_to_hs_coil {<<len(rm.powered.ExcitationCoils.vol.numbers)>>} ;
813
+ } ;
814
+ Support Omega ; Entity Global [Coils] ; }
815
+ {% endif %}
816
+ }
817
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
818
+ SubSpace{
819
+ { Name hs ; NameOfBasisFunction sb; }
820
+ }
821
+ {% endif %}
822
+ GlobalQuantity {
823
+ { Name I ; Type AliasOf ; NameOfCoef Ii ; }
824
+ { Name V ; Type AssociatedWith ; NameOfCoef Ii ; }
825
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
826
+ { Name Is ; Type AliasOf ; NameOfCoef Is ; }
827
+ { Name Vs ; Type AssociatedWith ; NameOfCoef Is ; }
828
+ {% endif %}
829
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
830
+ { Name Ic ; Type AliasOf ; NameOfCoef Ic ; }
831
+ { Name Vc ; Type AssociatedWith ; NameOfCoef Ic ; }
832
+ {% endif %}
833
+ }
834
+ Constraint {
835
+ { NameOfCoef he; EntityType EdgesOf; NameOfConstraint h; }
836
+ { NameOfCoef phin; EntityType NodesOf; NameOfConstraint phi; }
837
+ { NameOfCoef phin2; EntityType NodesOf; NameOfConstraint phi; }
838
+ { NameOfCoef Ii ;
839
+ EntityType GroupsOfEdgesOf ; NameOfConstraint Current ; }
840
+ { NameOfCoef V ;
841
+ EntityType GroupsOfNodesOf ; NameOfConstraint Voltage ; }
842
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
843
+ { NameOfCoef Is ;
844
+ EntityType Region ; NameOfConstraint Current_s ; }
845
+ { NameOfCoef Vs ;
846
+ EntityType Region ; NameOfConstraint Voltage_s ; }
847
+ {% endif %}
848
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
849
+ { NameOfCoef Ic ;
850
+ EntityType Region ; NameOfConstraint Current_coil ; }
851
+ { NameOfCoef Vc ;
852
+ EntityType Region ; NameOfConstraint Voltage_coil ; }
853
+ {% endif %}
854
+ }
855
+ }
856
+ // Function space for the circuit domain
857
+ { Name ElectricalCircuit; Type Scalar;
858
+ BasisFunction {
859
+ { Name sn; NameOfCoef Ir; Function BF_Region;
860
+ Support Resistors; Entity Resistors; }
861
+ }
862
+ GlobalQuantity {
863
+ { Name Iz ; Type AliasOf ; NameOfCoef Ir ; }
864
+ { Name Vz ; Type AssociatedWith ; NameOfCoef Ir ; }
865
+ }
866
+ Constraint {
867
+ { NameOfCoef Iz ; EntityType Region ; NameOfConstraint Current_Cir ; }
868
+ { NameOfCoef Vz ; EntityType Region ; NameOfConstraint Voltage_Cir ; }
869
+ }
870
+ }
871
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
872
+ // Function space for the circuit domain
873
+ { Name ElectricalCircuit_transport; Type Scalar;
874
+ BasisFunction {
875
+ { Name sn; NameOfCoef Icoef; Function BF_Region;
876
+ Support PoweringCircuit; Entity PoweringCircuit; }
877
+ }
878
+ GlobalQuantity {
879
+ { Name Ip ; Type AliasOf ; NameOfCoef Icoef ; }
880
+ { Name Vp ; Type AssociatedWith ; NameOfCoef Icoef ; }
881
+ }
882
+ Constraint {
883
+ { NameOfCoef Ip ; EntityType Region ; NameOfConstraint Current_Cir_transport ; }
884
+ { NameOfCoef Vp ; EntityType Region ; NameOfConstraint Voltage_Cir_transport ; }
885
+ }
886
+ }
887
+ {% endif %}
888
+ {% if dm.magnet.solve.formulation_parameters.rohf and dm.magnet.solve.formulation_parameters.stranded_strands %}
889
+ // Function space for the reversible current in stranded strands domains modelled with ROHF
890
+ For k In {1:N_rohf}
891
+ { Name IrevStrands~{k}; Type Scalar;
892
+ BasisFunction {
893
+ { Name srevstrand; NameOfCoef Irevstrand; Function BF_Region;
894
+ Support Strands; Entity Strands; }
895
+ }
896
+ GlobalQuantity {
897
+ { Name Irev ; Type AliasOf ; NameOfCoef Irevstrand ; }
898
+ }
899
+ }
900
+ { Name G~{k}; Type Scalar;
901
+ BasisFunction {
902
+ { Name sGtrand; NameOfCoef Gstrand; Function BF_Region;
903
+ Support Strands; Entity Strands; }
904
+ }
905
+ GlobalQuantity {
906
+ { Name G ; Type AliasOf ; NameOfCoef Gstrand ; }
907
+ }
908
+ }
909
+ EndFor
910
+ {% endif %}
911
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
912
+ // Function space for b from ROHM. Element-wise constant functions
913
+ { Name b_space ; Type Vector;
914
+ BasisFunction {
915
+ { Name sex ; NameOfCoef aex ; Function BF_VolumeX ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
916
+ { Name sey ; NameOfCoef aey ; Function BF_VolumeY ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
917
+ }
918
+ }
919
+ // Function space for internal state variable with ROHM (h_rev for each cell). One space per cell.
920
+ For k In {1:N}
921
+ { Name hrev~{k} ; Type Form1;
922
+ BasisFunction {
923
+ { Name psie; NameOfCoef he; Function BF_Edge;
924
+ Support MagnHystDomain; Entity EdgesOf[All]; }
925
+ // { Name sex ; NameOfCoef aex ; Function BF_VolumeX ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
926
+ // { Name sey ; NameOfCoef aey ; Function BF_VolumeY ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
927
+ }
928
+ }
929
+ // We can also recompute the 'g~{k}' below, instead of saving them. To be seen which approach is the most efficient.
930
+ { Name g~{k} ; Type Form1;
931
+ BasisFunction {
932
+ { Name psie; NameOfCoef he; Function BF_Edge;
933
+ Support MagnHystDomain; Entity EdgesOf[All]; }
934
+ // { Name vex ; NameOfCoef bex ; Function BF_VolumeX ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
935
+ // { Name vey ; NameOfCoef bey ; Function BF_VolumeY ; Support MagnHystDomain ; Entity VolumesOf[ All ] ; }
936
+ }
937
+ }
938
+ EndFor
939
+ {% endif %}
940
+ }
941
+
942
+ Formulation{
943
+ // h-formulation
944
+ { Name MagDyn_hphi; Type FemEquation;
945
+ Quantity {
946
+ { Name h; Type Local; NameOfSpace h_space; }
947
+ { Name hp; Type Local; NameOfSpace h_space; }
948
+ { Name I; Type Global; NameOfSpace h_space[I]; }
949
+ { Name V; Type Global; NameOfSpace h_space[V]; }
950
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
951
+ { Name Is ; Type Global; NameOfSpace h_space[Is]; }
952
+ { Name Vs ; Type Global; NameOfSpace h_space[Vs]; }
953
+ {% if dm.magnet.solve.formulation_parameters.rohf %}
954
+ For k In {1:N_rohf}
955
+ { Name Irev~{k} ; Type Global; NameOfSpace IrevStrands~{k}[Irev]; }
956
+ { Name G~{k} ; Type Global; NameOfSpace G~{k}[G]; }
957
+ EndFor
958
+ { Name hs; Type Local; NameOfSpace h_space[hs]; }
959
+ {% endif %}
960
+ {% endif %}
961
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
962
+ { Name b; Type Local; NameOfSpace b_space; }
963
+ For k In {1:N}
964
+ { Name hrev~{k} ; Type Local ; NameOfSpace hrev~{k};}
965
+ { Name g~{k} ; Type Local ; NameOfSpace g~{k};}
966
+ EndFor
967
+ {% endif %}
968
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
969
+ { Name Ic ; Type Global; NameOfSpace h_space[Ic]; }
970
+ { Name Vc ; Type Global; NameOfSpace h_space[Vc]; }
971
+ {% endif %}
972
+ { Name Iz; Type Global; NameOfSpace ElectricalCircuit[Iz]; }
973
+ { Name Vz; Type Global; NameOfSpace ElectricalCircuit[Vz]; }
974
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
975
+ { Name Ip ; Type Global; NameOfSpace ElectricalCircuit_transport[Ip]; }
976
+ { Name Vp ; Type Global; NameOfSpace ElectricalCircuit_transport[Vp]; }
977
+ {% endif %}
978
+ }
979
+ Equation {
980
+ // --- Axial currents problem ---
981
+ // Time derivative of b (NonMagnDomain)
982
+ Galerkin { [ ell* mu[] * Dof{h} / $DTime , {h} ];
983
+ In MagnLinDomain; Integration Int; Jacobian Vol; }
984
+ Galerkin { [ -ell*mu[] * {h}[1] / $DTime , {h} ];
985
+ In MagnLinDomain; Integration Int; Jacobian Vol; }
986
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
987
+ Galerkin { [ ell * bhyst[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] / $DTime , {h} ];
988
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
989
+ Galerkin { [ ell * dbhystdh[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] * Dof{h} / $DTime , {hp}];
990
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
991
+ Galerkin { [ - ell * dbhystdh[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] * {h} / $DTime , {hp}];
992
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
993
+ Galerkin { [ - ell * {b}[1] / $DTime , {h} ];
994
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
995
+
996
+ {% if dm.magnet.solve.formulation_parameters.rohf and dm.magnet.solve.formulation_parameters.stranded_strands%}
997
+ // Removing the contribution from {hs} inside the strands, such that the linear internal flux contribution is not counted twice.
998
+ Galerkin { [ - ell * bhyst[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] / $DTime , {hs} ];
999
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
1000
+ Galerkin { [ - ell * dbhystdh[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] * Dof{h} / $DTime , {hs}];
1001
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
1002
+ Galerkin { [ + ell * dbhystdh[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] * {h} / $DTime , {hs}];
1003
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
1004
+ Galerkin { [ + ell * {b}[1] / $DTime , {hs} ];
1005
+ In MagnHystDomain; Integration Int_b; Jacobian Vol; }
1006
+ {% endif %}
1007
+ {% endif %}
1008
+ // Induced current (linear OmegaC). Nothing with integrals in the strands, they are handled by the circuit equations
1009
+ Galerkin { [ ell * rho[mu0*Norm[{h}]] * Dof{d h} , {d h} ];
1010
+ In OmegaC; Integration Int; Jacobian Vol; }
1011
+ // Natural boundary condition for normal flux density (useful when transport current is an essential condition)
1012
+ {% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %}
1013
+ Galerkin { [ -ell * dbsdt[] * Normal[] , {dInv h} ];
1014
+ In BndAir; Integration Int; Jacobian Sur; }
1015
+ {% endif %}
1016
+ // Global term
1017
+ GlobalTerm { [ Dof{V} , {I} ] ; In CoatingCut ; }
1018
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1019
+ GlobalTerm { [ Dof{Vs} , {Is} ] ; In Strands ; }
1020
+ {% else %}
1021
+ GlobalTerm { [ Dof{V} , {I} ] ; In StrandCuts ; }
1022
+ {% endif %}
1023
+ {% if dm.magnet.solve.source_parameters.excitation_coils.enable %}
1024
+ GlobalTerm { [ Dof{Vc} , {Ic} ] ; In CoilCuts ; }
1025
+ {% endif %}
1026
+ // Resistance equation for the crossing/adjacent contact resistance
1027
+ GlobalTerm{ [ Dof{Vz} , {Iz} ]; In Resistors; }
1028
+ GlobalTerm{ [ R[] * Dof{Iz} , {Iz} ]; In Resistors; }
1029
+ {% if dm.magnet.solve.formulation_parameters.rohf and dm.magnet.solve.formulation_parameters.stranded_strands%}
1030
+ // ROHF model for the current flowing in the strands
1031
+ GlobalTerm{ [ + ell * DeltaFluxhyst[ {Is}, {Irev_1}[1], {G_1}[1], {Irev_2}[1], {G_2}[1], {Irev_3}[1], {G_3}[1], {Irev_4}[1], {G_4}[1], {Irev_5}[1], {G_5}[1]]/$DTime , {Is} ]; In Strands; }
1032
+ GlobalTerm{ [ + ell * dDeltaFluxhystdI[{Is}, {Irev_1}[1], {G_1}[1], {Irev_2}[1], {G_2}[1], {Irev_3}[1], {G_3}[1], {Irev_4}[1], {G_4}[1], {Irev_5}[1], {G_5}[1]]/$DTime * Dof{Is} , {Is} ]; In Strands; }
1033
+ GlobalTerm{ [ - ell * dDeltaFluxhystdI[{Is}, {Irev_1}[1], {G_1}[1], {Irev_2}[1], {G_2}[1], {Irev_3}[1], {G_3}[1], {Irev_4}[1], {G_4}[1], {Irev_5}[1], {G_5}[1]]/$DTime * {Is} , {Is} ]; In Strands; }
1034
+ GlobalTerm{ [ - ell * DeltaFluxhyst_prev[{Is}[1], {Irev_1}[1], {Irev_2}[1], {Irev_3}[1], {Irev_4}[1], {Irev_5}[1]]/$DTime , {Is} ]; In Strands; }
1035
+
1036
+ GlobalTerm{ [ + ell * V_resistance[{Is}] , {Is} ]; In Strands; }
1037
+ GlobalTerm{ [ + ell * dV_resistance_dI[{Is}] * Dof{Is} , {Is} ]; In Strands; }
1038
+ GlobalTerm{ [ - ell * dV_resistance_dI[{Is}] * {Is} , {Is} ]; In Strands; }
1039
+ {% else %}
1040
+ // GlobalTerm{ [ 1e-7 * ell * Dof{Is} , {Is} ]; In Strands; } // For tests only (resistive stranded strand)
1041
+ {% endif %}
1042
+ // Circuit network for the CATI method
1043
+ GlobalEquation {
1044
+ Type Network ; NameOfConstraint ElectricalCircuit ;
1045
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1046
+ { Node {Is}; Loop {Vs}; Equation {Vs}; In Strands ; }
1047
+ {% else %}
1048
+ { Node {I}; Loop {V}; Equation {V}; In Cuts ; }
1049
+ {% endif %}
1050
+ { Node {Iz}; Loop {Vz}; Equation {Vz}; In Resistors; }
1051
+ }
1052
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
1053
+ GlobalTerm{ [ Dof{Vp} , {Ip} ]; In ParallelResistor; }
1054
+ GlobalTerm{ [ R[]*ell * Dof{Ip} , {Ip} ]; In ParallelResistor; }
1055
+ // Circuit network for transport current and voltage
1056
+ GlobalEquation {
1057
+ Type Network ; NameOfConstraint ElectricalCircuit_transport ;
1058
+ { Node {I}; Loop {V}; Equation {V}; In CoatingCut ; }
1059
+ { Node {Ip}; Loop {Vp}; Equation {Vp}; In PoweringCircuit; }
1060
+ }
1061
+ {% endif %}
1062
+ }
1063
+ }
1064
+ // Frequency domain formulation
1065
+ { Name MagDyn_hphi_freq; Type FemEquation;
1066
+ Quantity {
1067
+ { Name h; Type Local; NameOfSpace h_space; }
1068
+ { Name hp; Type Local; NameOfSpace h_space; }
1069
+ { Name I; Type Global; NameOfSpace h_space[I]; }
1070
+ { Name V; Type Global; NameOfSpace h_space[V]; }
1071
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1072
+ { Name Is ; Type Global; NameOfSpace h_space[Is]; }
1073
+ { Name Vs ; Type Global; NameOfSpace h_space[Vs]; }
1074
+ {% endif %}
1075
+ { Name Iz; Type Global; NameOfSpace ElectricalCircuit[Iz]; }
1076
+ { Name Vz; Type Global; NameOfSpace ElectricalCircuit[Vz]; }
1077
+ }
1078
+ Equation {
1079
+ // --- OOP problem ---
1080
+ // Time derivative of b (NonMagnDomain)
1081
+ Galerkin { DtDof[ ell* mu[] * Dof{h}, {h} ];
1082
+ In Omega; Integration Int; Jacobian Vol; }
1083
+ // Induced current (linear OmegaC; nonlinear materials not allowed in the frequency domain)
1084
+ Galerkin { [ ell*rho[] * Dof{d h} , {d h} ];
1085
+ In OmegaC; Integration Int; Jacobian Vol; }
1086
+ // Galerkin { [ ell*rho[] * Dof{d h} , {d h} ];
1087
+ // In OmegaC_stranded; Integration Int; Jacobian Vol; }
1088
+ // Natural boundary condition for normal flux density (useful when transport current is an essential condition)
1089
+ {% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %}
1090
+ Galerkin { [ - ell* Complex[0, 2*Pi*$f*bmax]*Vector[Cos[<<dm.magnet.solve.source_parameters.sine.field_angle>>*Pi/180], Sin[<<dm.magnet.solve.source_parameters.sine.field_angle>>*Pi/180], 0.] * Normal[] , {dInv h} ];
1091
+ In BndAir; Integration Int; Jacobian Sur; }
1092
+ {% endif %}
1093
+ // Global term
1094
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1095
+ GlobalTerm { [ Dof{V} , {I} ] ; In CoatingCut ; }
1096
+ GlobalTerm { [ Dof{Vs} , {Is} ] ; In Strands ; }
1097
+ {% else %}
1098
+ GlobalTerm { [ Dof{V} , {I} ] ; In Cuts ; }
1099
+ {% endif %}
1100
+ // Resistance equation for the crossing contact resistances
1101
+ GlobalTerm{ [ Dof{Vz} , {Iz} ]; In Resistors; }
1102
+ GlobalTerm{ [ R[] * Dof{Iz} , {Iz} ]; In Resistors; }
1103
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1104
+ // Resistance model for the current flowing in the strands. The ROHF model cannot be solved in the frequency domain.
1105
+ // GlobalTerm{ [ ell * 1e-4 * Dof{Is} , {Is} ]; In Strands; } // Just for testing.
1106
+ {% endif %}
1107
+ // Circuit network
1108
+ GlobalEquation {
1109
+ Type Network ; NameOfConstraint ElectricalCircuit ;
1110
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1111
+ { Node {Is}; Loop {Vs}; Equation {Vs}; In Strands ; }
1112
+ {% else %}
1113
+ { Node {I}; Loop {V}; Equation {V}; In Cuts ; }
1114
+ {% endif %}
1115
+ { Node {Iz}; Loop {Vz}; Equation {Vz}; In Resistors; }
1116
+ }
1117
+ }
1118
+ }
1119
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
1120
+ // Projection formulation for initial condition
1121
+ { Name Projection_h_to_h; Type FemEquation;
1122
+ Quantity {
1123
+ { Name h; Type Local; NameOfSpace h_space; }
1124
+ }
1125
+ Equation{
1126
+ // 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).
1127
+ // Validity of this to be checked again if we go to different meshes between the initial condition and the following simulation.
1128
+ Galerkin { [ Dof{h}, {h} ] ;
1129
+ In Omega ; Jacobian Vol ; Integration Int ; }
1130
+ Galerkin { [ - h_from_file[], {h} ] ;
1131
+ In Omega ; Jacobian Vol ; Integration Int ; }
1132
+ }
1133
+ }
1134
+ {% endif %}
1135
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1136
+ // Update of b in hysteresis model
1137
+ { Name Update_b; Type FemEquation ;
1138
+ Quantity {
1139
+ { Name h; Type Local; NameOfSpace h_space; }
1140
+ { Name b ; Type Local ; NameOfSpace b_space ; }
1141
+ For k In {1:N}
1142
+ { Name hrev~{k} ; Type Local ; NameOfSpace hrev~{k};}
1143
+ { Name g~{k} ; Type Local ; NameOfSpace g~{k};}
1144
+ EndFor
1145
+ }
1146
+ Equation {
1147
+ Galerkin { [ Dof{b} , {b} ];
1148
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1149
+ Galerkin { [ - bhyst[{h}, {hrev_1}[1], {g_1}[1], {hrev_2}[1], {g_2}[1], {hrev_3}[1], {g_3}[1], {hrev_4}[1], {g_4}[1], {hrev_5}[1], {g_5}[1], Norm[{b}]] , {b} ];
1150
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1151
+ }
1152
+ }
1153
+ // Update of internal variables
1154
+ For k In {1:N}
1155
+ { Name Update_hrev~{k} ; Type FemEquation ;
1156
+ Quantity {
1157
+ { Name h; Type Local; NameOfSpace h_space; }
1158
+ { Name b ; Type Local ; NameOfSpace b_space ; }
1159
+ { Name hrev~{k} ; Type Local ; NameOfSpace hrev~{k};}
1160
+ { Name g~{k} ; Type Local ; NameOfSpace g~{k};}
1161
+ }
1162
+ Equation {
1163
+ Galerkin { [ Dof{hrev~{k}}, {hrev~{k}} ];
1164
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1165
+ Galerkin { [ - hrev_k[{h}, {hrev~{k}}[1], {g~{k}}[1], w~{k}, f_kappa[Norm[{b}]]*kappa~{k}, f_chi[Norm[{b}]]*chi~{k}, tau_c~{k}, tau_e~{k}], {hrev~{k}} ] ;
1166
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1167
+ Galerkin { [ Dof{g~{k}}, {g~{k}} ];
1168
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1169
+ Galerkin { [ - g_k[{h}, {hrev~{k}}[1], {g~{k}}[1], f_kappa[Norm[{b}]]*kappa~{k}], {g~{k}} ] ;
1170
+ In MagnHystDomain; Jacobian Vol; Integration Int; }
1171
+ }
1172
+ }
1173
+ EndFor
1174
+ {% endif %}
1175
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands and dm.magnet.solve.formulation_parameters.rohf%}
1176
+ For k In {1:N_rohf}
1177
+ { Name Update_Irev~{k} ; Type FemEquation ;
1178
+ Quantity {
1179
+ { Name Is ; Type Global; NameOfSpace h_space[Is]; }
1180
+ { Name Irev~{k} ; Type Global; NameOfSpace IrevStrands~{k}[Irev]; }
1181
+ { Name G~{k} ; Type Global; NameOfSpace G~{k}[G]; }
1182
+ }
1183
+ Equation {
1184
+ GlobalTerm{ [ Dof{Irev~{k}}, {Irev~{k}} ]; In Strands; }
1185
+ GlobalTerm{ [ - Irev_k[{Is}, {Irev~{k}}[1], {G~{k}}[1], kappa_rohf~{k}, tau_e_rohf~{k}], {Irev~{k}} ]; In Strands; }
1186
+ GlobalTerm{ [ Dof{G~{k}}, {G~{k}} ]; In Strands; }
1187
+ GlobalTerm{ [ - G_k[{Is}, {G~{k}}[1], kappa_rohf~{k}], {G~{k}} ]; In Strands; }
1188
+ }
1189
+ }
1190
+ EndFor
1191
+ {% endif %}
1192
+ }
1193
+
1194
+ Macro CustomIterativeLoop
1195
+ // Compute first solution guess and residual at step $TimeStep
1196
+ Generate[A];
1197
+ Solve[A]; Evaluate[ $syscount = $syscount + 1 ];
1198
+ Generate[A]; GetResidual[A, $res0];
1199
+ Evaluate[ $res = $res0 ];
1200
+ Evaluate[ $iter = 0 ];
1201
+ Evaluate[ $convCrit = 1e99 ];
1202
+ PostOperation[MagDyn_energy];
1203
+ Print[{$iter, $res, $res / $res0, $indicTotalLoss},
1204
+ Format "%g %14.12e %14.12e %14.12e", File infoResidualFile];
1205
+ // ----- Enter the iterative loop (hand-made) -----
1206
+ While[$convCrit > 1 && $res / $res0 <= 1e10 && $iter < iter_max]{
1207
+ Solve[A]; Evaluate[ $syscount = $syscount + 1 ];
1208
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1209
+ Generate[B]; Solve[B]; // update {b} so that the field-dependent parameter is updated for the convergence criterion
1210
+ {% endif %}
1211
+ Generate[A]; GetResidual[A, $res];
1212
+ Evaluate[ $iter = $iter + 1 ];
1213
+ Evaluate[ $indicTotalLossOld = $indicTotalLoss];
1214
+ PostOperation[MagDyn_energy];
1215
+ Print[{$iter, $res, $res / $res0, $indicTotalLoss},
1216
+ 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.
1217
+ // Evaluate the convergence indicator
1218
+ Evaluate[ $relChangeACLoss = Abs[($indicTotalLossOld - $indicTotalLoss)/((Abs[$indicTotalLossOld]>1e-7 || $iter < 10) ? $indicTotalLossOld:1e-7)] ];
1219
+ Evaluate[ $convCrit = $relChangeACLoss/tol_energy];
1220
+ }
1221
+ Return
1222
+
1223
+ Resolution {
1224
+ { Name MagDyn;
1225
+ System {
1226
+ {Name A; NameOfFormulation MagDyn_hphi;}
1227
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1228
+ {Name B; NameOfFormulation Update_b; }
1229
+ For k In {1:N}
1230
+ {Name CELL~{k}; NameOfFormulation Update_hrev~{k}; }
1231
+ EndFor
1232
+ {% endif %}
1233
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands and dm.magnet.solve.formulation_parameters.rohf%}
1234
+ For k In {1:N_rohf}
1235
+ {Name CELL_ROHF~{k}; NameOfFormulation Update_Irev~{k}; }
1236
+ EndFor
1237
+ {% endif %}
1238
+ }
1239
+ Operation {
1240
+ // Initialize directories
1241
+ CreateDirectory[resDirectory];
1242
+ DeleteFile[outputPowerROHM];
1243
+ DeleteFile[outputPowerROHF];
1244
+ DeleteFile[infoResidualFile];
1245
+ // Initialize the solution (initial condition)
1246
+ SetTime[ timeStart ];
1247
+ SetDTime[ dt ];
1248
+ SetTimeStep[ 0 ];
1249
+ InitSolution[A];
1250
+ SaveSolution[A]; // Saves the solution x (from Ax = B) to .res file
1251
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1252
+ InitSolution[B]; SaveSolution[B];
1253
+ For k In {1:N}
1254
+ InitSolution[CELL~{k}]; SaveSolution[CELL~{k}];
1255
+ EndFor
1256
+ {% endif %}
1257
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands and dm.magnet.solve.formulation_parameters.rohf%}
1258
+ For k In {1:N_rohf}
1259
+ InitSolution[CELL_ROHF~{k}]; SaveSolution[CELL_ROHF~{k}];
1260
+ EndFor
1261
+ {% endif %}
1262
+ Evaluate[ $syscount = 0 ];
1263
+ Evaluate[ $saved = 1 ];
1264
+ Evaluate[ $elapsedCTI = 1 ]; // Number of control time instants already treated
1265
+ Evaluate[ $isCTI = 0 ];
1266
+
1267
+ Evaluate[ $indicTotalLoss_dyn = 0 ]; // Put it to zero to avoid warnings
1268
+ Evaluate[ $indicCouplingLoss_dyn = 0 ]; // Put it to zero to avoid warnings
1269
+
1270
+ // ----- Enter implicit Euler time integration loop (hand-made) -----
1271
+ // Avoid too close steps at the end. Stop the simulation if the step becomes ridiculously small
1272
+ SetExtrapolationOrder[ extrapolationOrder ];
1273
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1274
+ Print[{$Time}, Format "%g 0.0 0.0 0.0 0.0 0.0", File outputPowerROHM];
1275
+ {% endif %}
1276
+ While[$Time < timeFinal - 1e-10] {
1277
+ SetTime[ $Time + $DTime ]; // Time instant at which we are looking for the solution
1278
+ SetTimeStep[ $TimeStep + 1 ];
1279
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1280
+ Generate[B];
1281
+ For k In {1:N}
1282
+ Generate[CELL~{k}];
1283
+ EndFor
1284
+ {% endif %}
1285
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands and dm.magnet.solve.formulation_parameters.rohf%}
1286
+ For k In {1:N_rohf}
1287
+ Generate[CELL_ROHF~{k}];
1288
+ EndFor
1289
+ {% endif %}
1290
+
1291
+ {% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear and dm.magnet.solve.source_parameters.source_type == 'piecewise'%}
1292
+ // Make sure all CTI are exactly chosen
1293
+ Evaluate[ $isCTI = 0 ];
1294
+ Test[$Time >= time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} - 1e-7 ]{
1295
+ Evaluate[ $isCTI = 1, $prevDTime = $DTime ]; // Also save the previous time step to restart from it after the CTI
1296
+ SetDTime[ time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} - $Time + $DTime ];
1297
+ SetTime[ time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} ]; // To compute exactly at the asked time instant
1298
+ Print[{$Time}, Format "*** Control time instant: %g s."];
1299
+ }
1300
+ {% endif %}
1301
+ // Iterative loop defined as a macro above
1302
+ Print[{$Time, $DTime, $TimeStep}, Format "Start new time step. Time: %g s. Time step: %g s. Step: %g."];
1303
+ Call CustomIterativeLoop;
1304
+ // Has it converged? If yes, save solution and possibly increase the time step...
1305
+ Test[ $iter < iter_max && ($res / $res0 <= 1e10 || $res0 == 0)]{
1306
+ Print[{$Time, $DTime, $iter}, Format "Converged time %g s with time step %g s in %g iterations."];
1307
+ // Save the solution of few time steps (small correction to avoid bad rounding)
1308
+ // Test[ $Time >= $saved * writeInterval - 1e-7 || $Time + $DTime >= timeFinal]{
1309
+ Test[ 1 ]{
1310
+ // Test[ $Time >= $saved * $DTime - 1e-7 || $Time + $DTime >= timeFinal]{
1311
+ SaveSolution[A];
1312
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1313
+ Generate[B]; Solve[B]; SaveSolution[B];
1314
+ For k In {1:N}
1315
+ Generate[CELL~{k}]; Solve[CELL~{k}]; SaveSolution[CELL~{k}];
1316
+ EndFor
1317
+ {% endif %}
1318
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands and dm.magnet.solve.formulation_parameters.rohf%}
1319
+ For k In {1:N_rohf}
1320
+ Generate[CELL_ROHF~{k}]; Solve[CELL_ROHF~{k}]; SaveSolution[CELL_ROHF~{k}];
1321
+ EndFor
1322
+ {% endif %}
1323
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1324
+ PostOperation[MagDyn_energy_full];
1325
+ Print[{$Time, $saved}, Format "Saved time %g s (saved solution number %g). Output power infos:"];
1326
+ Print[{$Time, $indicTotalLoss, $indicHystLoss, $indicHystCLoss, $indicCouplingLoss, $indicEddyLoss}, // the other loss contributions (interstrand and ROHF) are not integrated quantities, but computed from global quantities
1327
+ Format "%g %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e", File outputPowerROHM];
1328
+ {% endif %}
1329
+ // Evaluate[$saved = $saved + 1];
1330
+ }
1331
+
1332
+ {% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear and dm.magnet.solve.source_parameters.source_type == 'piecewise' %}
1333
+ // Consider the time step before the control time instant (if relevant) and increment $elapsedCTI
1334
+ Test[ $isCTI == 1 ]{
1335
+ Evaluate[ $elapsedCTI = $elapsedCTI + 1 ];
1336
+ SetDTime[ $prevDTime ];
1337
+ }
1338
+ {% endif %}
1339
+ // Increase the step if we converged sufficiently "fast" (and not a control time instant)
1340
+ Test[ $iter < iter_max / 4 && $DTime < dt_max_var[] && $isCTI == 0 ]{
1341
+ Evaluate[ $dt_new = Min[$DTime * 2, dt_max_var[]] ];
1342
+ Print[{$dt_new}, Format "*** Fast convergence: increasing time step to %g"];
1343
+ SetDTime[$dt_new];
1344
+ }
1345
+ Test[ $DTime > dt_max_var[]]{
1346
+ Evaluate[ $dt_new = dt_max_var[] ];
1347
+ Print[{$dt_new}, Format "*** Variable maximum time-stepping: reducing time step to %g"];
1348
+ SetDTime[$dt_new];
1349
+ }
1350
+ }
1351
+ // ...otherwise, reduce the time step and try again
1352
+ {
1353
+ Evaluate[ $dt_new = $DTime / 2 ];
1354
+ Print[{$iter, $dt_new},
1355
+ Format "*** Non convergence (iter %g): recomputing with reduced step %g"];
1356
+ RemoveLastSolution[A];
1357
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1358
+ RemoveLastSolution[B];
1359
+ {% endif %}
1360
+ SetTime[$Time - $DTime];
1361
+ SetTimeStep[$TimeStep - 1];
1362
+ SetDTime[$dt_new];
1363
+ // If it gets ridicoulously small, end the simulation, and report the information in crash file.
1364
+ Test[ $dt_new < dt_max_var[]/10000 ]{
1365
+ Print[{$iter, $dt_new, $Time},
1366
+ Format "*** Non convergence (iter %g): time step %g too small, stopping the simulation at time %g s.", File crashReportFile];
1367
+ // Print[A];
1368
+ Exit;
1369
+ }
1370
+ }
1371
+ } // ----- End time loop -----
1372
+ // Print information about the resolution and the nonlinear iterations
1373
+ Print[{$syscount}, Format "Total number of linear systems solved: %g"];
1374
+ }
1375
+ }
1376
+ // Frequency domain resolution
1377
+ { Name MagDyn_freq;
1378
+ System {
1379
+ {Name A; NameOfFormulation MagDyn_hphi_freq; Type ComplexValue;}
1380
+ }
1381
+ Operation {
1382
+ // Initialize directories
1383
+ CreateDirectory[resDirectory];
1384
+ DeleteFile[outputPowerROHM];
1385
+ DeleteFile[outputPowerROHF];
1386
+ DeleteFile[infoResidualFile];
1387
+ SetTimeStep[ 1 ];
1388
+ {% if dm.magnet.solve.frequency_domain_solver.frequency_sweep.run_sweep %}
1389
+ For i In {0:nbFreq-1}
1390
+ SetFrequency[A, freq(i)];
1391
+ Evaluate[$f = freq(i)];
1392
+ Print[{$f, $TimeStep}, Format "Start new solution. f: %g Hz. Solution: %g."];
1393
+ Generate[A]; Solve[A]; SaveSolution[A];
1394
+ PostOperation[MagDyn_energy];
1395
+ Print[{$indicTotalLoss}, Format " - computed loss: %g."];
1396
+ SetTimeStep[$TimeStep + 1];
1397
+ EndFor
1398
+ {% else %}
1399
+ SetFrequency[A, f];
1400
+ Evaluate[$f = f];
1401
+ Print[{$f, $TimeStep}, Format "Start new solution. f: %g Hz. Solution: %g."];
1402
+ Generate[A]; Solve[A]; SaveSolution[A];
1403
+ PostOperation[MagDyn_energy];
1404
+ Print[{$indicTotalLoss}, Format " - computed loss: %g."];
1405
+ {% endif %}
1406
+ }
1407
+ }
1408
+
1409
+ {% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
1410
+ { Name Projection_h_to_h;
1411
+ System {
1412
+ {Name Projection_h_to_h; NameOfFormulation Projection_h_to_h; DestinationSystem A ;}
1413
+ }
1414
+ Operation {
1415
+ 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)
1416
+ Generate[Projection_h_to_h]; Solve[Projection_h_to_h];
1417
+ TransferSolution[Projection_h_to_h];
1418
+ }
1419
+ }
1420
+ {% endif %}
1421
+ }
1422
+
1423
+ PostProcessing {
1424
+ {
1425
+ {% if dm.magnet.solve.frequency_domain_solver.enable %}
1426
+ Name MagDyn_hphi; NameOfFormulation MagDyn_hphi_freq;
1427
+ {% else %}
1428
+ Name MagDyn_hphi; NameOfFormulation MagDyn_hphi;
1429
+ {% endif %}
1430
+ Quantity {
1431
+ { Name phi; Value{ Local{ [ {dInv h} ] ;
1432
+ In OmegaCC_AndBnd; Jacobian Vol; } } }
1433
+ { Name h; Value{ Local{ [ {h} ] ;
1434
+ In Omega; Jacobian Vol; } } }
1435
+ { Name b; Value {
1436
+ Term { [ mu[] * {h} ] ; In MagnLinDomain; Jacobian Vol; }
1437
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1438
+ Term { [ {b} ] ; In MagnHystDomain; Jacobian Vol; }
1439
+ {% endif %}
1440
+ }
1441
+ }
1442
+ { Name b_reaction; Value{
1443
+ Term { [ mu[] * ({h} - hsVal[]) ] ; In MagnLinDomain; Jacobian Vol; }
1444
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1445
+ Term { [ {b} - mu0*hsVal[]] ; In MagnHystDomain; Jacobian Vol; } // this is NOT the magnetization, just the reaction field
1446
+ {% endif %}
1447
+ }
1448
+ }
1449
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1450
+ { Name m; Value{ Local{ [ {b} - mu0*{h} ] ;
1451
+ In MagnHystDomain; Jacobian Vol; } } }
1452
+ {% endif %}
1453
+ { Name j; Value{ Local{ [ {d h} ] ;
1454
+ In Omega; Jacobian Vol; } } }
1455
+ { Name jz; Value{ Local{ [ {d h} * Vector[0,0,1]] ;
1456
+ In Omega; Jacobian Vol; } } }
1457
+ { Name power_interstrand_coupling;
1458
+ Value {
1459
+ Term{ [ 1/ell * {Iz} * {Iz} * R[] ] ; In Resistors; }
1460
+ }
1461
+ }
1462
+ { Name strand_current;
1463
+ Value{
1464
+ Integral{ [ {d h}*Vector[0,0,1] ] ;
1465
+ In Strands ; Integration Int ; Jacobian Vol; }
1466
+ }
1467
+ }
1468
+ { Name coating_current;
1469
+ Value{
1470
+ Integral{ [ {d h}*Vector[0,0,1] ] ;
1471
+ In Coating ; Integration Int ; Jacobian Vol; }
1472
+ }
1473
+ }
1474
+ {% if dm.magnet.solve.frequency_domain_solver.enable %}
1475
+ { Name mean_strand_loss;
1476
+ Value{
1477
+ Integral{ [ Re[ (rho[] * {d h} * Conj[{d h}] ) / 2 ] ] ;
1478
+ In Strands ; Integration Int ; Jacobian Vol; } // only for massive strands (not stranded)
1479
+ }
1480
+ }
1481
+ { Name mean_coupling_loss;
1482
+ Value {
1483
+ Term{ [ ( 1/ell * Re[ {Iz} * Conj[{Iz}] ] * R[] ) / 2 ] ; In Resistors; }
1484
+ }
1485
+ }
1486
+ { Name coupling_loss_per_cycle;
1487
+ Value {
1488
+ Term{ [ ( 1/ell * Re[ {Iz} * Conj[{Iz}] ] * R[] ) / (2*$f) ] ; In Resistors; }
1489
+ }
1490
+ }
1491
+ { Name Iz_magnitude; Value { Term{ [ Sqrt[ {Iz} * Conj[{Iz}] ] ] ; In Resistors; } } }
1492
+ {% endif %}
1493
+ { Name totalLoss; // Obsolete!
1494
+ Value{
1495
+ // Separate OmegaC into Matrix and nonlinear (resistivities take different argument types)
1496
+ Integral{ [rho[{d h}, mu0*Norm[{h}]] * {d h} * {d h}] ; // j*e = rho*j^2 (filaments)
1497
+ In NonLinOmegaC ; Integration Int ; Jacobian Vol; }
1498
+ Integral{ [rho[mu0*Norm[{h}]] * {d h} * {d h}] ; // j*e = rho*j^2 (eddy)
1499
+ In LinOmegaC ; Integration Int ; Jacobian Vol; }
1500
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1501
+ For k In {1:N}
1502
+ Integral { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1503
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1504
+ Integral { [ w~{k} * tau_e~{k} * mu0 * SquNorm[Dt[{hrev~{k}}]] ] ;
1505
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1506
+ EndFor
1507
+ For k In {2:N} // 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
1508
+ Integral { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}] * w~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}]/tau_c~{k}) ] ;
1509
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1510
+ Integral { [ mu0 * SquNorm[hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}]]/tau_c~{k} * w~{k} ] ;
1511
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1512
+ EndFor
1513
+ {% endif %}
1514
+ {% if dm.magnet.solve.formulation_parameters.rohf %}
1515
+ // Pirr ROHF
1516
+ For k In {1:N_rohf}
1517
+ Term{ [ 0.5 * ({Is} - {G~{k}} + {Is}[1] - {G~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{Irev~{k}}] ] ; In Strands; }
1518
+ // Term{ [ 0.5 * ({Is} - {Irev~{k}} - tau_e_rohf~{k} * Dt[{Irev~{k}}] + {Is}[1] - {Irev~{k}}[1] - tau_e_rohf~{k} * Dt[{Irev~{k}}[1]]) * w_rohf~{k} * Lint0 * Dt[{Irev~{k}}] ] ; In Strands; }
1519
+ EndFor
1520
+ // Peddy ROHF
1521
+ For k In {1:N_rohf}
1522
+ Term{ [ w_rohf~{k} * tau_e_rohf~{k} * Lint0 * SquNorm[Dt[{Irev~{k}}]] ] ; In Strands; }
1523
+ EndFor
1524
+ Term{ [ {Is} * V_resistance[{Is}] ] ; In Strands; }
1525
+ {% endif %}
1526
+ }
1527
+ }
1528
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1529
+ { Name power_hyst;
1530
+ Value{
1531
+ For k In {1:N}
1532
+ Integral { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1533
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1534
+ // Integral { [ ({h} - {g~{k}}[1]) * w~{k} * mu0 * ({hrev~{k}} - {hrev~{k}}[1])/$DTime ] ;
1535
+ EndFor
1536
+ }
1537
+ }
1538
+ { Name power_hyst_c;
1539
+ Value{
1540
+ For k In {2:N} // 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
1541
+ Integral { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}] * w~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}]/tau_c~{k}) ] ;
1542
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1543
+ EndFor
1544
+ }
1545
+ }
1546
+ { Name power_hyst_hyst_c_local;
1547
+ Value{
1548
+ For k In {1:N}
1549
+ Term { [ 0.5 * ({h} - {g~{k}} + {h}[1] - {g~{k}}[1]) * w~{k} * mu0 * Dt[{hrev~{k}}] ] ;
1550
+ In MagnHystDomain; Jacobian Vol; }
1551
+ EndFor
1552
+ For k In {2:N}
1553
+ Term { [ hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}] * w~{k} * (mu0 * Dt[{hrev~{k}}] - mu0 * hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}]/tau_c~{k}) ] ;
1554
+ In MagnHystDomain ; Jacobian Vol; }
1555
+ EndFor
1556
+ }
1557
+ }
1558
+ { Name power_eddy;
1559
+ Value{
1560
+ For k In {1:N}
1561
+ Integral { [ w~{k} * tau_e~{k} * mu0 * SquNorm[Dt[{hrev~{k}}]] ] ;
1562
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1563
+ EndFor
1564
+ }
1565
+ }
1566
+ { Name power_coupling;
1567
+ Value{
1568
+ For k In {2:N} // 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
1569
+ Integral { [ mu0 * SquNorm[hcoupling[mu0*Dt[{hrev~{k}}], Norm[mu0*{hrev~{k}}], tau_c~{k}, chi~{k}]]/tau_c~{k} * w~{k} ] ;
1570
+ In MagnHystDomain ; Jacobian Vol; Integration Int; }
1571
+ EndFor
1572
+ }
1573
+ }
1574
+ {% endif %}
1575
+ // { Name surfaceArea; Value{ Local{ [ SurfaceArea[] ] ;
1576
+ // In Coating; Jacobian Vol; } } }
1577
+ { Name I; Value { Term{ [ {I} ] ; In CoatingCut; } } }
1578
+ { Name V; Value { Term{ [ {V} ] ; In CoatingCut; } } }
1579
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
1580
+ { Name Ip; Value { Term{ [ {Ip} ] ; In PoweringCircuit; } } }
1581
+ { Name Vp; Value { Term{ [ {Vp} ] ; In PoweringCircuit; } } }
1582
+ {% endif %}
1583
+ { Name V_unitlen; Value { Term{ [ 1/ell * {V} ] ; In CoatingCut; } } }
1584
+ { Name Iz; Value { Term{ [ {Iz} ] ; In Resistors; } } }
1585
+ { Name Vz; Value { Term{ [ {Vz} ] ; In Resistors; } } }
1586
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1587
+ { Name Is; Value { Term{ [ {Is} ] ; In Strands; } } }
1588
+ { Name Vs; Value { Term{ [ {Vs} ] ; In Strands; } } }
1589
+ { Name Vs_unitlen; Value { Term{ [ 1/ell * {Vs} ] ; In Strands; } } }
1590
+ {% endif %}
1591
+ {% if dm.magnet.solve.formulation_parameters.rohf %}
1592
+ // All ROHF quantities are defined on unit length
1593
+ { Name delta_fluxhyst; Value { Term{ [ DeltaFluxhyst_prev[{Is}, {Irev_1}, {Irev_2}, {Irev_3}, {Irev_4}, {Irev_5}] ] ; In Strands; } } }
1594
+ { Name delta_flux_local; Value { Term{ [ DeltaFluxhyst_prev[{Is}, {Irev_1}, {Irev_2}, {Irev_3}, {Irev_4}, {Irev_5}] ] ; In Strands; Jacobian Vol; } } }
1595
+ { Name delta_voltage_rohf; Value { Term{ [ Dt[ DeltaFluxhyst_prev[{Is}, {Irev_1}, {Irev_2}, {Irev_3}, {Irev_4}, {Irev_5}] ] ] ; In Strands; } } }
1596
+ { Name power_hyst_rohf;
1597
+ Value{
1598
+ For k In {1:N_rohf}
1599
+ Term{ [ 0.5 *({Is} - {G~{k}} + {Is}[1] - {G~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{Irev~{k}}] ]; In Strands; }
1600
+ EndFor
1601
+ }
1602
+ }
1603
+ { Name power_hyst_rohf_local;
1604
+ Value{
1605
+ For k In {1:N_rohf}
1606
+ Term{ [ 0.5 * ({Is} - {G~{k}} + {Is}[1] - {G~{k}}[1]) * w_rohf~{k} * Lint0 * Dt[{Irev~{k}}] / SurfaceArea[] ]; In Strands; Jacobian Vol;}
1607
+ EndFor
1608
+ }
1609
+ }
1610
+ { Name power_eddy_rohf;
1611
+ Value{
1612
+ For k In {1:N_rohf}
1613
+ Term{ [ w_rohf~{k} * tau_e_rohf~{k} * Lint0 * SquNorm[Dt[{Irev~{k}}]] ]; In Strands; }
1614
+ EndFor
1615
+ }
1616
+ }
1617
+ { Name power_joule;
1618
+ Value{
1619
+ Term{ [ {Is} * V_resistance[{Is}] ] ; In Strands; }
1620
+ }
1621
+ }
1622
+ {% endif %}
1623
+ // Applied field (useful for magnetization plots)
1624
+ { Name hsVal; Value{ Term { [ hsVal[] ]; In Omega; } } }
1625
+ // Magnetization: integral of 1/2 * (r /\ j) in a conducting (sub-)domain
1626
+ { Name magnetization; Value{ Integral{ [ 0.5 * XYZ[] /\ {d h} ] ;
1627
+ In OmegaC_and_stranded; Integration Int; Jacobian Vol; } } }
1628
+ // Magnetic energy
1629
+ { Name magnetic_energy; Value{ Integral{ [ 0.5 * mu[] * {h} * {h} ] ;
1630
+ In Omega; Integration Int; Jacobian Vol; } } }
1631
+ }
1632
+ }
1633
+ }
1634
+ PostOperation {
1635
+ { Name MagDyn;
1636
+ NameOfPostProcessing MagDyn_hphi;
1637
+ Operation {
1638
+ // Local field solutions
1639
+ {% if dm.magnet.postproc.generate_pos_files%}
1640
+ Print[ b, OnElementsOf Omega , File StrCat["b.pos"], Name "b [T]" ];
1641
+ // Print[ surfaceArea, OnElementsOf Coating , File StrCat["surface.pos"], Name "surface [T]" ];
1642
+ // Print[ h, OnElementsOf Omega , File StrCat["h.pos"], Name "h [A/m]" ];
1643
+ // Print[ b_reaction, OnElementsOf Omega , File StrCat["br.pos"], Name "br [T]" ];
1644
+ Print[ j, OnElementsOf OmegaC_and_stranded , File StrCat["j.pos"], Name "j [A/m2]" ];
1645
+ Print[ jz, OnElementsOf OmegaC_and_stranded , File StrCat["jz.pos"], Name "jz [A/m2]" ];
1646
+ // Print[ j, OnElementsOf Coils , File StrCat["js.pos"], Name "js [A/m2]" ];
1647
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1648
+ Print[ m, OnElementsOf MagnHystDomain , File StrCat["m.pos"], Name "m [T]" ];
1649
+ {% endif %}
1650
+ {% endif %}
1651
+ // Print[ b, OnPoint{3.86e-4,3.86e-4,0}, Format TimeTable, File StrCat[resDirectory, "/b_strand_1.txt"]];
1652
+ // Print[ h, OnPoint{3.86e-4,3.86e-4,0}, Format TimeTable, File StrCat[resDirectory, "/h_strand_1.txt"]];
1653
+ // Print[ b, OnPoint{2.309e-3,3.86e-4,0}, Format TimeTable, File StrCat[resDirectory, "/b_strand_3.txt"]];
1654
+ // Print[ h, OnPoint{2.309e-3,3.86e-4,0}, Format TimeTable, File StrCat[resDirectory, "/h_strand_3.txt"]];
1655
+ // Global solutions
1656
+ Print[ magnetization[OmegaC_and_stranded], OnGlobal, Format TimeTable, File StrCat[resDirectory, "/magn_total.txt"]];
1657
+ Print[ Iz, OnRegion Resistors, File StrCat[resDirectory,"/Iz.txt"], Format SimpleTable];
1658
+ // Print[strand_current[Strand_1], OnRegion Strand_1, File StrCat[resDirectory,"/Strand_current.txt"], Format SimpleTable];
1659
+ Print[coating_current[Coating], OnRegion Coating, File StrCat[resDirectory,"/Coating_current.txt"], Format SimpleTable];
1660
+ For i In {2:N_strands}
1661
+ Print[strand_current[Strand~{i}], OnRegion Strand~{i}, File > StrCat[resDirectory,"/Strand_current.txt"], Format SimpleTable];
1662
+ EndFor
1663
+ Print[Iz, OnRegion R_crossing_1, File StrCat[resDirectory,"/Coupling_current.txt"], Format SimpleTable];
1664
+ For i In {2:N_crossing_resistors}
1665
+ Print[Iz, OnRegion R_crossing~{i}, File > StrCat[resDirectory,"/Coupling_current.txt"], Format SimpleTable];
1666
+ EndFor
1667
+ // Print[Iz, OnRegion R_crossing_oblique_1, File StrCat[resDirectory,"/Coupling_oblique_current.txt"], Format SimpleTable];
1668
+ // For i In {2:N_strands}
1669
+ // Print[Iz, OnRegion R_crossing_oblique~{i}, File > StrCat[resDirectory,"/Coupling_oblique_current.txt"], Format SimpleTable];
1670
+ // EndFor
1671
+ Print[Iz, OnRegion R_adjacent_1, File StrCat[resDirectory,"/Adjacent_current.txt"], Format SimpleTable];
1672
+ For i In {2:N_strands}
1673
+ Print[Iz, OnRegion R_adjacent~{i}, File > StrCat[resDirectory,"/Adjacent_current.txt"], Format SimpleTable];
1674
+ EndFor
1675
+ {% if dm.magnet.solve.frequency_domain_solver.enable %}
1676
+ // Frequency-domain solutions
1677
+ Print[ Iz_magnitude, OnRegion Resistors, File StrCat[resDirectory,"/Iz_magnitude.txt"], Format SimpleTable];
1678
+ Print[ mean_coupling_loss, OnRegion Resistors_crossing, File StrCat[resDirectory,"/Coupling_crossing_loss.txt"], Format SimpleTable];
1679
+ // Print[ mean_coupling_loss, OnRegion Resistors_crossing_oblique, File StrCat[resDirectory,"/Coupling_crossing_oblique_loss.txt"], Format SimpleTable];
1680
+ Print[ mean_coupling_loss, OnRegion Resistors_adjacent, File StrCat[resDirectory,"/Coupling_adjacent_loss.txt"], Format SimpleTable];
1681
+ Print[ mean_strand_loss[Strands], OnGlobal, File StrCat[resDirectory,"/Strand_loss.txt"], Format SimpleTable];
1682
+ {% else %}
1683
+ Print[ power_interstrand_coupling, OnRegion Resistors, File StrCat[resDirectory,"/power_IS_coupling.txt"], Format SimpleTable];
1684
+ {% endif %}
1685
+ {% if dm.magnet.solve.formulation_parameters.stranded_strands %}
1686
+ Print[ Is, OnRegion Strands, File StrCat[resDirectory,"/Is.txt"], Format SimpleTable];
1687
+ Print[ Vs, OnRegion Strands, File StrCat[resDirectory,"/Vs.txt"], Format SimpleTable];
1688
+ Print[ Vs_unitlen, OnRegion Strands, File StrCat[resDirectory,"/Vs_unitlen.txt"], Format SimpleTable];
1689
+ {% endif %}
1690
+ {% if dm.magnet.solve.formulation_parameters.rohf %}
1691
+ Print[ delta_fluxhyst, OnRegion Strands, File StrCat[resDirectory,"/delta_flux_hyst.txt"], Format SimpleTable];
1692
+ {% if dm.magnet.postproc.generate_pos_files%}
1693
+ Print[ delta_flux_local, OnElementsOf Strands , File StrCat["delta_flux_dens.pos"], Name "flux_dens [Wb/m3]" ];
1694
+ Print[ power_hyst_rohf_local, OnElementsOf Strands , File StrCat["p_hyst_ROHF.pos"], Name "p_hyst_ROHF [W/m3]" ];
1695
+ {% endif %}
1696
+ Print[ delta_voltage_rohf, OnRegion Strands, File StrCat[resDirectory,"/delta_voltage_ROHF.txt"], Format SimpleTable];
1697
+ Print[ power_hyst_rohf, OnRegion Strands, File StrCat[resDirectory,"/power_hyst_ROHF.txt"], Format SimpleTable];
1698
+ Print[ power_eddy_rohf, OnRegion Strands, File StrCat[resDirectory,"/power_eddy_ROHF.txt"], Format SimpleTable];
1699
+ Print[ power_joule, OnRegion Strands, File StrCat[resDirectory,"/power_joule.txt"], Format SimpleTable];
1700
+ {% endif %}
1701
+ {% if dm.magnet.solve.formulation_parameters.rohm%}
1702
+ {% if dm.magnet.postproc.generate_pos_files%}
1703
+ Print[ power_hyst_hyst_c_local, OnElementsOf MagnHystDomain , File StrCat["p_hyst_ROHM.pos"], Name "p_hyst_ROHM [W/m3]" ];
1704
+ {% endif %}
1705
+ {% endif %}
1706
+ Print[ I, OnRegion CoatingCut, File StrCat[resDirectory,"/It.txt"], Format SimpleTable];
1707
+ Print[ V, OnRegion CoatingCut, File StrCat[resDirectory,"/Vt.txt"], Format SimpleTable];
1708
+ {% if dm.magnet.solve.source_parameters.parallel_resistor %}
1709
+ Print[ Ip, OnRegion PoweringCircuit, File StrCat[resDirectory,"/Ip.txt"], Format SimpleTable];
1710
+ Print[ Vp, OnRegion PoweringCircuit, File StrCat[resDirectory,"/Vp.txt"], Format SimpleTable];
1711
+ {% endif %}
1712
+ Print[ V_unitlen, OnRegion CoatingCut, File StrCat[resDirectory,"/Vt_unitlen.txt"], Format SimpleTable];
1713
+ {% if dm.magnet.postproc.save_last_magnetic_field != "None" %}
1714
+ // Last magnetic field solution for projection. Note the special format GmshParsed required for proper GmshRead[] operation in the later pre-resolution.
1715
+ Print[ h, OnElementsOf Omega, Format GmshParsed , File StrCat["../", "<<dm.magnet.postproc.save_last_magnetic_field>>", ".pos"], Name "h [A/m]", LastTimeStepOnly ];
1716
+ {% endif %}
1717
+ }
1718
+ }
1719
+ { Name MagDyn_energy; LastTimeStepOnly 1 ;
1720
+ NameOfPostProcessing MagDyn_hphi;
1721
+ Operation {
1722
+ Print[ totalLoss[Omega], OnGlobal, Format Table, StoreInVariable $indicTotalLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1723
+ }
1724
+ }
1725
+ { Name MagDyn_energy_full; LastTimeStepOnly 1 ;
1726
+ NameOfPostProcessing MagDyn_hphi;
1727
+ Operation {
1728
+ Print[ totalLoss[Omega], OnGlobal, Format Table, StoreInVariable $indicTotalLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1729
+ {% if dm.magnet.solve.formulation_parameters.rohm %}
1730
+ Print[ power_hyst[Omega], OnGlobal, Format Table, StoreInVariable $indicHystLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1731
+ Print[ power_hyst_c[Omega], OnGlobal, Format Table, StoreInVariable $indicHystCLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1732
+ Print[ power_coupling[Omega], OnGlobal, Format Table, StoreInVariable $indicCouplingLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1733
+ Print[ power_eddy[Omega], OnGlobal, Format Table, StoreInVariable $indicEddyLoss, File StrCat[resDirectory,"/dummy.txt"] ];
1734
+ {% endif %}
1735
+ {% if dm.magnet.solve.formulation_parameters.rohf %}
1736
+ Print[ power_hyst_rohf, OnRegion Strands, Format Table, StoreInVariable $indicHystLossROHF, File StrCat[resDirectory,"/dummy.txt"] ]; // This only saved the power in a single strand into the Variable
1737
+ Print[ power_eddy_rohf, OnRegion Strands, Format Table, StoreInVariable $indicEddyLossROHF, File StrCat[resDirectory,"/dummy.txt"] ]; // This only saved the power in a single strand into the Variable
1738
+ Print[ power_joule, OnRegion Strands, Format Table, StoreInVariable $indicJouleLossROHF, File StrCat[resDirectory,"/dummy.txt"] ]; // This only saved the power in a single strand into the Variable
1739
+ {% endif %}
1740
+ }
1741
+ }
1742
+ }