fiqus 2024.5.2__py3-none-any.whl → 2024.6.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.
- fiqus/MainFiQuS.py +15 -5
- fiqus/data/DataConductor.py +301 -0
- fiqus/data/DataFiQuS.py +5 -2
- fiqus/data/DataFiQuSConductor.py +84 -0
- fiqus/data/DataFiQuSConductorAC_Strand.py +565 -0
- fiqus/data/DataFiQuSPancake3D.py +149 -39
- fiqus/data/RegionsModelFiQuS.py +4 -2
- fiqus/geom_generators/GeometryCCT.py +19 -17
- fiqus/geom_generators/GeometryConductorAC_Strand.py +1391 -0
- fiqus/getdp_runners/RunGetdpConductorAC_Strand.py +202 -0
- fiqus/getdp_runners/RunGetdpMultipole.py +4 -4
- fiqus/mains/MainConductorAC_Strand.py +133 -0
- fiqus/mesh_generators/MeshCCT.py +8 -8
- fiqus/mesh_generators/MeshConductorAC_Strand.py +657 -0
- fiqus/mesh_generators/MeshMultipole.py +11 -8
- fiqus/mesh_generators/MeshPancake3D.py +20 -18
- fiqus/plotters/PlotPythonConductorAC.py +840 -0
- fiqus/post_processors/PostProcessConductorAC.py +49 -0
- fiqus/pro_assemblers/ProAssembler.py +4 -3
- fiqus/pro_templates/combined/CCT_template.pro +25 -25
- fiqus/pro_templates/combined/ConductorAC_template.pro +1025 -0
- fiqus/pro_templates/combined/Multipole_template.pro +5 -5
- fiqus/pro_templates/combined/Pancake3D_template.pro +131 -46
- fiqus/pro_templates/combined/materials.pro +13 -9
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/METADATA +2 -1
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/RECORD +34 -22
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/WHEEL +1 -1
- tests/test_geometry_generators.py +41 -0
- tests/test_mesh_generators.py +45 -0
- tests/test_solvers.py +52 -0
- tests/utils/fiqus_test_classes.py +42 -6
- tests/utils/generate_reference_files_ConductorAC.py +57 -0
- tests/utils/generate_reference_files_Pancake3D.py +92 -0
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1025 @@
|
|
|
1
|
+
Group {
|
|
2
|
+
// ------- PROBLEM DEFINITION -------
|
|
3
|
+
// Filaments
|
|
4
|
+
Filaments_SC = Region[{<<rm.powered.Filaments.vol.numbers|join(', ')>>}]; // Filament superconducting region
|
|
5
|
+
Filament_holes = Region[{<<rm.powered.Filaments.surf_in.numbers|join(', ')>>}]; // Filament holes
|
|
6
|
+
|
|
7
|
+
Filaments = Region[{Filaments_SC, Filament_holes}]; // Filaments (including holes)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
BndFilaments = Region[{<<rm.powered.Filaments.surf.numbers|join(', ')>>}]; // Filament boundaries
|
|
11
|
+
Cuts = Region[{<<rm.powered.Filaments.cochain.numbers|join(', ')>>}]; // Cuts on filament boundaries
|
|
12
|
+
|
|
13
|
+
// Define the filaments, boundaries and cuts according to their layer and index in the layer
|
|
14
|
+
{% if len(rm.powered.Filaments.vol.numbers) % 6 == 0 %} // There is no inner layer (of length 1)
|
|
15
|
+
{% for layer in range( int(len(rm.powered.Filaments.vol.numbers)/6 )) %}
|
|
16
|
+
{% for filament_index in range(6) %}
|
|
17
|
+
filament_<<layer + 1>>_<<filament_index + 1>> = Region[{<<rm.powered.Filaments.vol.numbers[layer*6 + filament_index]>>}]; // Filament surface
|
|
18
|
+
filamentBnd_<<layer + 1>>_<<filament_index + 1>> = Region[{<<rm.powered.Filaments.surf.numbers[layer*6 + filament_index]>>}]; // Boundary
|
|
19
|
+
Cut_<<layer + 1>>_<<filament_index + 1>> = Region[{<<rm.powered.Filaments.cochain.numbers[layer*6 + filament_index]>>}]; // Cut
|
|
20
|
+
{%endfor%}
|
|
21
|
+
{%endfor%}
|
|
22
|
+
|
|
23
|
+
{% elif len(rm.powered.Filaments.vol.numbers) % 6 == 1 %} // There is an inner layer (of length 1)
|
|
24
|
+
// Define the inner point
|
|
25
|
+
filament_0_0 = Region[{<<rm.powered.Filaments.vol.numbers[0]>>}];
|
|
26
|
+
filamentBnd_0_0 = Region[{<<rm.powered.Filaments.surf.numbers[0]>>}];
|
|
27
|
+
Cut_0_0 = Region[{<<rm.powered.Filaments.cochain.numbers[0]>>}];
|
|
28
|
+
|
|
29
|
+
{% for layer in range(0, int((len(rm.powered.Filaments.vol.numbers)-1) /6 ) ) %}
|
|
30
|
+
{% for filament_index in range(6) %}
|
|
31
|
+
filament_<<layer + 1>>_<<filament_index + 1>> = Region[{<<rm.powered.Filaments.vol.numbers[layer*6 + filament_index + 1]>>}];
|
|
32
|
+
filamentBnd_<<layer + 1>>_<<filament_index + 1>> = Region[{<<rm.powered.Filaments.surf.numbers[layer*6 + filament_index + 1]>>}];
|
|
33
|
+
Cut_<<layer + 1>>_<<filament_index + 1>> = Region[{<<rm.powered.Filaments.cochain.numbers[layer*6 + filament_index + 1]>>}];
|
|
34
|
+
{%endfor%}
|
|
35
|
+
{%endfor%}
|
|
36
|
+
|
|
37
|
+
{% endif %}
|
|
38
|
+
|
|
39
|
+
// To assign different material properties to each filament hole, we need to assign them separately.
|
|
40
|
+
{% for i, hole in enumerate(rm.powered.Filaments.surf_in.numbers) %}
|
|
41
|
+
FilamentHole_<<i>> = Region[{<<hole>>}];
|
|
42
|
+
{%endfor%}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
// Matrix partitions
|
|
47
|
+
{% for i, matrix_partition in enumerate(rm.induced.Matrix.vol.numbers)%}
|
|
48
|
+
Matrix_<<i>> = Region[{<<matrix_partition>>}];
|
|
49
|
+
{%endfor%}
|
|
50
|
+
|
|
51
|
+
// Matrix
|
|
52
|
+
Matrix = Region[{<<rm.induced.Matrix.vol.numbers|join(', ') >>}];
|
|
53
|
+
BndMatrix = Region[ <<rm.induced.Matrix.surf_out.numbers[0]>> ]; // Strand outer boundary
|
|
54
|
+
BndMatrixCut = Region[ <<rm.induced.Matrix.cochain.numbers[0]>> ]; // Strand outer boundary cut
|
|
55
|
+
Cuts += Region[ BndMatrixCut ]; // important to add the matrix cut to the region of the cuts
|
|
56
|
+
|
|
57
|
+
// Air
|
|
58
|
+
Air = Region[ <<rm.air.vol.number>> ]; // Air surface
|
|
59
|
+
BndAir = Region[ <<rm.air.surf.number>> ]; // Air outer boundary
|
|
60
|
+
|
|
61
|
+
// Define a region for the matrix partitions to be included in the TI (in-plane) problem
|
|
62
|
+
TI_adjacent_region = Region[ {Air} ]; // Define the regions adjacent to the region on which the TI problem is solved (used for defining h_perp_space_dynamic)
|
|
63
|
+
{% if dm.magnet.geometry.io_settings.load.load_from_yaml %}
|
|
64
|
+
Matrix_partitions_excluded_from_TI = Region[{<<mp.Surfaces_excluded_from_TI|join(', ')>>}]; // Matrix partitions excluded from the IP problem
|
|
65
|
+
|
|
66
|
+
Matrix_partitions_for_TI = Region[ {Matrix} ];
|
|
67
|
+
Matrix_partitions_for_TI -= Region[ {Matrix_partitions_excluded_from_TI} ]; // Matrix partitions included in the IP problem
|
|
68
|
+
|
|
69
|
+
TI_adjacent_region += Region[ {Matrix_partitions_excluded_from_TI} ]; // Define the regions adjacent to the region on which the TI problem is solved (used for defining h_perp_space_dynamic)
|
|
70
|
+
{% else %}
|
|
71
|
+
Matrix_partitions_for_TI = Region[ {Matrix} ];
|
|
72
|
+
{% endif %}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// Split into conducting and non-conducting domains
|
|
76
|
+
LinOmegaC = Region[ {Matrix, Filament_holes} ];
|
|
77
|
+
NonLinOmegaC = Region[ {Filaments_SC} ];
|
|
78
|
+
OmegaC = Region[ {LinOmegaC, NonLinOmegaC} ];
|
|
79
|
+
BndOmegaC = Region[ {BndMatrix, BndFilaments} ];
|
|
80
|
+
OmegaCC = Region[ {Air} ];
|
|
81
|
+
Omega = Region[ {OmegaC, OmegaCC} ]; // the whole domain (only surfaces in 2D, or volumes in 3D)
|
|
82
|
+
|
|
83
|
+
OmegaC_AndBnd = Region[{OmegaC, BndOmegaC}]; // useful for function space definition
|
|
84
|
+
OmegaCC_AndBnd = Region[{OmegaCC, BndOmegaC, BndAir}]; // useful for function space definition
|
|
85
|
+
|
|
86
|
+
// Here we define points on the boundaries of the filaments and the outer matrix boundary.
|
|
87
|
+
// These points are used to fix the magnetic potential to zero on the boundaries.
|
|
88
|
+
MatrixPointOnBoundary = Region[{<<rm.air.point.numbers[0]>>}];
|
|
89
|
+
FilamentPointsOnBoundaries = Region[{<<rm.powered.Filaments.curve.numbers|join(', ')>>}];
|
|
90
|
+
ArbitraryPoints = Region[{MatrixPointOnBoundary, FilamentPointsOnBoundaries}];
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
Function{
|
|
95
|
+
// ------- GEOMETRY PARAMETERS -------
|
|
96
|
+
{% if len(rm.powered.Filaments.vol.numbers) % 6 == 0 %}
|
|
97
|
+
number_of_layers = <<len(rm.powered.Filaments.vol.numbers)>>/6;
|
|
98
|
+
{% elif len(rm.powered.Filaments.vol.numbers) % 6 == 1 %}
|
|
99
|
+
number_of_layers = (<<len(rm.powered.Filaments.vol.numbers)>>-1) / 6;
|
|
100
|
+
{% endif %}
|
|
101
|
+
// ------- MATERIAL PARAMETERS -------
|
|
102
|
+
temperature = <<dm.magnet.solve.general_parameters.temperature>>;
|
|
103
|
+
T[] = temperature; // this can be made a function of time if needed. Later on, T may also be a field we solve for.
|
|
104
|
+
RRR_matrix = <<dm.conductors[dm.magnet.solve.conductor_name].strand.RRR>>;
|
|
105
|
+
|
|
106
|
+
mu0 = Pi*4e-7; // [H/m]
|
|
107
|
+
nu0 = 1.0/mu0; // [m/H]
|
|
108
|
+
mu[Omega] = mu0;
|
|
109
|
+
nu[Omega] = nu0;
|
|
110
|
+
// Copper
|
|
111
|
+
{% if isinstance(dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer, float) %} // If the matrix has constant resistivity we can assign it directly
|
|
112
|
+
rho[Matrix] = <<dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer>>;
|
|
113
|
+
{% elif dm.magnet.geometry.io_settings.load.load_from_yaml %}
|
|
114
|
+
// If we load the geometry from a YAML file, we also have material properties assigned in a MaterialProperties (mp) data structure.
|
|
115
|
+
{% for i, matrix_partition_material in zip(range(len(rm.induced.Matrix.vol.numbers)), rm.induced.Matrix.vol.names)%}
|
|
116
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer == 'CFUN_rhoCu_T' %}
|
|
117
|
+
rho[Matrix_<<i>>] = CFUN_rhoCu_T[T[]]{0, << mp.Materials[matrix_partition_material].RRR >>};
|
|
118
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer == 'CFUN_rhoCu' %}
|
|
119
|
+
rho[Matrix_<<i>>] = CFUN_rhoCu_T_B[T[], $1]{<< mp.Materials[matrix_partition_material].RRR >>};
|
|
120
|
+
{% endif %}
|
|
121
|
+
{%endfor%}
|
|
122
|
+
{% else %} // If we don't load the geometry from a YAML file, we can assign the material properties directly
|
|
123
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer == 'CFUN_rhoCu_T' %}
|
|
124
|
+
rho[Matrix] = CFUN_rhoCu_T[T[]]{0, RRR_matrix};
|
|
125
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer == 'CFUN_rhoCu' %}
|
|
126
|
+
rho[Matrix] = CFUN_rhoCu_T_B[T[], $1]{RRR_matrix};
|
|
127
|
+
{% endif %}
|
|
128
|
+
{% endif %}
|
|
129
|
+
|
|
130
|
+
// Superconducting filaments (nonlinear now)
|
|
131
|
+
ec = <<dm.conductors[dm.magnet.solve.conductor_name].strand.ec_superconductor>>; // [V/m], the value 1e-4 V/m is a common convention
|
|
132
|
+
|
|
133
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.type == 'Ic_A_NbTi' and dm.conductors[dm.magnet.solve.conductor_name].strand.material_superconductor == 'NbTi' %}
|
|
134
|
+
jc[] = <<dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.Jc_5T_4_2K>> / 1.70732393e9 * CFUN_IcNbTi_T_B_a[T[], $1, 1]; // [A/m2] critical current density as function of temperature and field amplitude
|
|
135
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.type == 'Ic_A_NbTi' and dm.conductors[dm.magnet.solve.conductor_name].strand.material_superconductor == 'Nb3Sn' %}
|
|
136
|
+
jc[] = CFUN_IcNb3Sn_T_B_a[T[], $1, 1]; // [A/m2] critical current density as function of temperature and field amplitude
|
|
137
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.type == 'Bordini' %}
|
|
138
|
+
jc[] = 2.25*CFUN_Jc_Bordini_T_B[T[], $1]{60400/1.056e-6, 16.47, 30.77, 1.025}; // [A/m2], parameters from DOI: 10.1109/TASC.2022.3167655 (see conclusion)
|
|
139
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.type == 'Constant Jc' %}
|
|
140
|
+
jc[] = <<dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.Jc_constant>>; // [A/m2] constant critical current density
|
|
141
|
+
{% endif %}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
n = <<dm.conductors[dm.magnet.solve.conductor_name].strand.n_value_superconductor>>; // [-] power law index, one key parameter for the power law
|
|
145
|
+
|
|
146
|
+
rho_power[] = ec / jc[$2] * (Norm[$1] / jc[$2])^(n - 1); // [Ohm m] power law resistivity
|
|
147
|
+
dedj_power[] = (
|
|
148
|
+
ec / jc[$2] * (Norm[$1]/jc[$2])^(n - 1) * TensorDiag[1, 1, 1] +
|
|
149
|
+
ec / jc[$2]^3 * (n - 1) * (Norm[$1]/jc[$2])^(n - 3) * SquDyadicProduct[$1]);
|
|
150
|
+
|
|
151
|
+
outer_product[] = Tensor[CompX[$1]*CompX[$2], CompX[$1]*CompY[$2], CompX[$1]*CompZ[$2], CompY[$1]*CompX[$2], CompY[$1]*CompY[$2], CompY[$1]*CompZ[$2], CompZ[$1]*CompX[$2], CompZ[$1]*CompY[$2], CompZ[$1]*CompZ[$2]];
|
|
152
|
+
dedb_power[] = -n*ec/jc[Norm[$2]]^2 * (Norm[$1]/jc[Norm[$2]])^(n-1) * ( jc[Norm[$2] + 0.005] - jc[Max[0, Norm[$2] - 0.005]] ) / (0.01) * outer_product[$1, $2]/(Norm[$2]+1e-10);
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
{% if dm.magnet.solve.general_parameters.superconductor_linear %}
|
|
156
|
+
mult_copper_like = 1e-5;
|
|
157
|
+
rho[Filaments_SC] = mult_copper_like * 1.81e-10; // <<dm.magnet.solve.material_properties.matrix.resistivity.constant>>;
|
|
158
|
+
dedj[Filaments_SC] = mult_copper_like * 1.81e-10; //<<dm.magnet.solve.material_properties.matrix.resistivity.constant>>;
|
|
159
|
+
{% else %}
|
|
160
|
+
rho[Filaments_SC] = rho_power[$1, $2];
|
|
161
|
+
dedj[Filaments_SC] = dedj_power[$1, $2];
|
|
162
|
+
{% endif %}
|
|
163
|
+
dedb[Filaments_SC] = dedb_power[$1, $2];
|
|
164
|
+
|
|
165
|
+
{% if dm.magnet.geometry.io_settings.load.load_from_yaml %}
|
|
166
|
+
// We assign material properties to each filament hole. Currently we just assign the same properties as the matrix, but with a different RRR.
|
|
167
|
+
// This must be changed to actually use the correct material property read from the geometry YAML.
|
|
168
|
+
{% for i, hole_material in zip(range(len(rm.powered.Filaments.surf_in.numbers)), rm.powered.Filaments.surf_in.names)%}
|
|
169
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer == 'CFUN_rhoCu_T' %}
|
|
170
|
+
rho[FilamentHole_<<i>>] = CFUN_rhoCu_T[T[]]{0, << mp.Materials[hole_material].RRR >>};
|
|
171
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer == 'CFUN_rhoCu' %}
|
|
172
|
+
rho[FilamentHole_<<i>>] = CFUN_rhoCu_T_B[T[], $1]{<< mp.Materials[hole_material].RRR >>};
|
|
173
|
+
{% elif isinstance(dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer, float) %} // If the matrix has constant resistivity we can assign it directly
|
|
174
|
+
rho[FilamentHole_<<i>>] = <<dm.conductors[dm.magnet.solve.conductor_name].strand.rho_material_stabilizer>>;
|
|
175
|
+
{% endif %}
|
|
176
|
+
{% endfor %}
|
|
177
|
+
{% endif %}
|
|
178
|
+
|
|
179
|
+
sigma[] = 1/rho[$1] ; // Can only be used in the matrix
|
|
180
|
+
|
|
181
|
+
// HEAT APPROXIMATION
|
|
182
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].strand.Cv_material_superconductor == 'CFUN_CvNbTi' %}
|
|
183
|
+
filament_Cv[] = CFUN_CvNbTi_T_B[$1, $2]{0, 1, 0}; // Volumetric heat capacity [J/(m3 K)], as function of temperature and field magnitude.
|
|
184
|
+
{% elif dm.conductors[dm.magnet.solve.conductor_name].strand.Cv_material_superconductor == 'CFUN_CvNb3Sn' %}
|
|
185
|
+
filament_Cv[] = CFUN_CvNb3Sn_T_B[$1, $2]; // Volumetric heat capacity [J/(m3 K)], as function of temperature and field magnitude.
|
|
186
|
+
{% endif %}
|
|
187
|
+
|
|
188
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].strand.Cv_material_stabilizer == 'CFUN_CvCu' %}
|
|
189
|
+
matrix_Cv[] = CFUN_CvCu_T[$1]; // Volumetric heat capacity [J/(m3 K)], as function of temperature
|
|
190
|
+
{% endif %}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
// ------- SOURCE PARAMETERS -------
|
|
194
|
+
bmax = <<dm.magnet.solve.source_parameters.sine.field_amplitude>>; // Maximum applied magnetic induction [T]
|
|
195
|
+
f = <<dm.magnet.solve.source_parameters.sine.frequency>>; // Frequency of applied field [Hz]
|
|
196
|
+
// Direction and value of applied field
|
|
197
|
+
{% if dm.magnet.solve.source_parameters.source_type != 'sine' %}
|
|
198
|
+
directionApplied[] = Vector[0., 1., 0.];
|
|
199
|
+
{% endif %}
|
|
200
|
+
|
|
201
|
+
{% if dm.magnet.solve.source_parameters.source_type == 'sine' %} // Sine wave source (potentially with DC component)
|
|
202
|
+
time_multiplier = 1;
|
|
203
|
+
|
|
204
|
+
I_transport[] = <<dm.magnet.solve.source_parameters.sine.superimposed_DC.current_magnitude>> + <<dm.magnet.solve.source_parameters.sine.current_amplitude>> * Sin[2*Pi*f * $Time];
|
|
205
|
+
|
|
206
|
+
constant_field_direction[] = Vector[0., 1., 0.];
|
|
207
|
+
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.];
|
|
208
|
+
|
|
209
|
+
hsVal[] = nu0 * <<dm.magnet.solve.source_parameters.sine.superimposed_DC.field_magnitude>> * constant_field_direction[] + nu0 * <<dm.magnet.solve.source_parameters.sine.field_amplitude>> * Sin[2*Pi*f * $Time] * directionApplied[];
|
|
210
|
+
hsVal_prev[] = nu0 * <<dm.magnet.solve.source_parameters.sine.superimposed_DC.field_magnitude>> * constant_field_direction[] + nu0 * <<dm.magnet.solve.source_parameters.sine.field_amplitude>> * Sin[2*Pi*f * ($Time-$DTime)] * directionApplied[];
|
|
211
|
+
|
|
212
|
+
{% elif dm.magnet.solve.source_parameters.source_type == 'piecewise' %}
|
|
213
|
+
time_multiplier = <<dm.magnet.solve.source_parameters.piecewise.time_multiplier>>;
|
|
214
|
+
applied_field_multiplier = <<dm.magnet.solve.source_parameters.piecewise.applied_field_multiplier>>;
|
|
215
|
+
transport_current_multiplier = <<dm.magnet.solve.source_parameters.piecewise.transport_current_multiplier>>;
|
|
216
|
+
|
|
217
|
+
{% if dm.magnet.solve.source_parameters.piecewise.source_csv_file %} // Source from CSV file
|
|
218
|
+
timeList() = {<<ed['time']|join(', ')>>};
|
|
219
|
+
valueList() = {<<ed['value']|join(', ')>>};
|
|
220
|
+
timeValuesList() = ListAlt[timeList(), valueList()];
|
|
221
|
+
|
|
222
|
+
hsVal[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{List[timeValuesList()]} * directionApplied[];
|
|
223
|
+
hsVal_prev[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time-$DTime)/time_multiplier]]{List[timeValuesList()]} * directionApplied[];
|
|
224
|
+
I_transport[] = transport_current_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{List[timeValuesList()]};
|
|
225
|
+
|
|
226
|
+
{% else %} // Source from parameters
|
|
227
|
+
times_source_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.times|join(', ')>>};
|
|
228
|
+
transport_currents_relative_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.transport_currents_relative|join(', ')>>};
|
|
229
|
+
applied_fields_relative_piecewise_linear() = {<<dm.magnet.solve.source_parameters.piecewise.applied_fields_relative|join(', ')>>};
|
|
230
|
+
|
|
231
|
+
hsVal[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), applied_fields_relative_piecewise_linear()]} * directionApplied[];
|
|
232
|
+
hsVal_prev[] = nu0 * applied_field_multiplier * InterpolationLinear[Max[0,($Time-$DTime)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), applied_fields_relative_piecewise_linear()]} * directionApplied[];
|
|
233
|
+
I_transport[] = transport_current_multiplier * InterpolationLinear[Max[0,($Time)/time_multiplier]]{ListAlt[times_source_piecewise_linear(), transport_currents_relative_piecewise_linear()]};
|
|
234
|
+
{% endif %}
|
|
235
|
+
{% endif %}
|
|
236
|
+
|
|
237
|
+
// For the natural boundary condition (restricted to fields of constant direction for the moment, should be generalized)
|
|
238
|
+
dbsdt[] = mu0 * (hsVal[] - hsVal_prev[]) / $DTime; // must be a finite difference to avoid error accumulation
|
|
239
|
+
|
|
240
|
+
// ------- NUMERICAL PARAMETERS -------
|
|
241
|
+
timeStart = 0.; // Initial time [s]
|
|
242
|
+
|
|
243
|
+
{% if dm.magnet.solve.source_parameters.source_type == 'sine'%}
|
|
244
|
+
timeFinal = <<dm.magnet.solve.numerical_parameters.sine.number_of_periods_to_simulate>>/f; // Final time for source definition (s)
|
|
245
|
+
dt = 1 / (f*<<dm.magnet.solve.numerical_parameters.sine.timesteps_per_period>>); // Time step (initial if adaptive) (s)
|
|
246
|
+
dt_max = dt; // Fixed maximum time step
|
|
247
|
+
dt_max_var[] = dt_max;
|
|
248
|
+
{% else %}
|
|
249
|
+
timeFinal = <<dm.magnet.solve.numerical_parameters.piecewise.time_to_simulate>>;
|
|
250
|
+
|
|
251
|
+
{% if dm.magnet.solve.numerical_parameters.piecewise.variable_max_timestep %}
|
|
252
|
+
times_max_timestep_piecewise_linear() = {<<dm.magnet.solve.numerical_parameters.piecewise.times_max_timestep_piecewise_linear|join(', ')>>};
|
|
253
|
+
max_timestep_piecewise_linear() = {<<dm.magnet.solve.numerical_parameters.piecewise.max_timestep_piecewise_linear|join(', ')>>};
|
|
254
|
+
dt = max_timestep_piecewise_linear(0);
|
|
255
|
+
dt_max_var[] = InterpolationLinear[Max[0,$Time]]{ListAlt[times_max_timestep_piecewise_linear(), max_timestep_piecewise_linear()]};
|
|
256
|
+
{% else %}
|
|
257
|
+
dt = timeFinal / <<dm.magnet.solve.numerical_parameters.piecewise.timesteps_per_time_to_simulate>>;
|
|
258
|
+
dt_max = dt; // Fixed maximum time step
|
|
259
|
+
dt_max_var[] = dt_max;
|
|
260
|
+
{% endif %}
|
|
261
|
+
|
|
262
|
+
{% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear%}
|
|
263
|
+
control_time_instants_list() = {<<dm.magnet.solve.source_parameters.piecewise.times|join(', ')>>, 1e99}; // last one is just to avoid 'seg. fault' errors
|
|
264
|
+
{% endif %}
|
|
265
|
+
|
|
266
|
+
{% endif %}
|
|
267
|
+
|
|
268
|
+
// Set correction factor based on the periodicity length
|
|
269
|
+
{% if dm.magnet.solve.formulation_parameters.two_ell_periodicity %}
|
|
270
|
+
correctionFactor = 0.827; // to be automatized (equal to sin(x)/x with x = pi*ell/p, with ell = p/6 in the hexagonal lattice case)
|
|
271
|
+
ell = 2*correctionFactor * <<dm.conductors[dm.magnet.solve.conductor_name].strand.fil_twist_pitch>> / 6;
|
|
272
|
+
{% else %}
|
|
273
|
+
correctionFactor = 0.9549;
|
|
274
|
+
ell = correctionFactor * <<dm.conductors[dm.magnet.solve.conductor_name].strand.fil_twist_pitch>> / 6;
|
|
275
|
+
{% endif %}
|
|
276
|
+
|
|
277
|
+
iter_max = 60; // Maximum number of iterations (after which we exit the iterative loop)
|
|
278
|
+
extrapolationOrder = 1; // Extrapolation order for predictor
|
|
279
|
+
tol_energy = 1e-6; // Tolerance on the relative change of the power indicator
|
|
280
|
+
writeInterval = dt; // Time interval to save the solution [s]
|
|
281
|
+
|
|
282
|
+
// ------- SIMULATION NAME -------
|
|
283
|
+
name = "test_temporary";
|
|
284
|
+
resDirectory = StrCat["./",name];
|
|
285
|
+
infoResidualFile = StrCat[resDirectory,"/residual.txt"];
|
|
286
|
+
outputPower = StrCat[resDirectory,"/power.txt"]; // File updated during runtime
|
|
287
|
+
crashReportFile = StrCat[resDirectory,"/crash_report.txt"];
|
|
288
|
+
outputTemperature = StrCat[resDirectory,"/temperature.txt"];
|
|
289
|
+
|
|
290
|
+
{% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
|
|
291
|
+
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[]
|
|
292
|
+
{% endif %}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
Constraint {
|
|
296
|
+
{ Name phi ;
|
|
297
|
+
Case {
|
|
298
|
+
{% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %} // For natural boundary condition (in formulation)
|
|
299
|
+
{Region ArbitraryPoints ; Value 0.0 ;} // Fix the magnetic potential to zero on the boundaries of the filaments and the outer matrix boundary
|
|
300
|
+
{% elif dm.magnet.solve.source_parameters.boundary_condition_type == 'Essential' %}
|
|
301
|
+
{Region BndAir ; Type Assign ; Value XYZ[]*directionApplied[] ; TimeFunction hsVal[] * directionApplied[] ;} // Essential boundary condition (not compatible with transport current)
|
|
302
|
+
{% endif %}
|
|
303
|
+
{% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
|
|
304
|
+
{Region Omega ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
|
|
305
|
+
{% endif %}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
{ Name Current ;
|
|
309
|
+
Case {
|
|
310
|
+
{Region BndMatrixCut ; Type Assign ; Value 1.0 ; TimeFunction I_transport[] ;} // Contraint for the total transport current
|
|
311
|
+
{% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
|
|
312
|
+
{Region Cuts ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
|
|
313
|
+
{% endif %}
|
|
314
|
+
// {Region Cuts ; Type Assign ; Value 0. ;} // for debugging (or to model fully uncoupled filaments without transport current)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
{ Name Voltage ; Case {} } // Empty to avoid warnings
|
|
318
|
+
{ Name Current_plane ; Case {} } // Empty to avoid warnings
|
|
319
|
+
{ Name Voltage_plane ;
|
|
320
|
+
Case {
|
|
321
|
+
// The constraint below can be useful for debugging (together with the Current one on Cuts, they uncouple the OOP and IP problems in the linked-flux formulation)
|
|
322
|
+
//{Region filamentBnd_1_1 ; Type Assign ; Value 1. ;} // Put just one to non-zero voltage to see a non-trivial solution
|
|
323
|
+
//{Region BndFilaments ; Type Assign ; Value 0. ;} // All the other ones are forced to be zero
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
{ Name v_plane ;
|
|
327
|
+
Case {
|
|
328
|
+
// {Region filamentBnd_1_1 ; Type Assign ; Value 1. ;}
|
|
329
|
+
// {Region BndFilaments ; Type Assign ; Value 0. ;}
|
|
330
|
+
{Region MatrixPointOnBoundary ; Type Assign ; Value 0. ;}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
335
|
+
// As only the curl of the field is projected, the absolute value is unknown. We need to symmetrize the field
|
|
336
|
+
{ Name hp_static ;
|
|
337
|
+
Case {
|
|
338
|
+
// {Region CenterPoint ; Value 0.0 ;} // replaced by a Lagrange multiplier in the formulation (more general, as there might be a filament at the center!)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
{% endif %}
|
|
342
|
+
|
|
343
|
+
// This is the key constraint for coupling global quantities: it contains the links between the filaments
|
|
344
|
+
{Name ElectricalCircuit ; Type Network ;
|
|
345
|
+
Case circuit {
|
|
346
|
+
// A filament in the center is treated separately.
|
|
347
|
+
{% if len(rm.powered.Filaments.vol.numbers) % 6 == 1 %}
|
|
348
|
+
{ Region Cut_0_0 ; Branch { 0, 0 } ; }
|
|
349
|
+
{ Region filamentBnd_0_0 ; Branch {1000, 0} ; }
|
|
350
|
+
{% endif %}
|
|
351
|
+
|
|
352
|
+
{% if dm.magnet.solve.formulation_parameters.two_ell_periodicity %}
|
|
353
|
+
{% for layer in range(1, int( len(rm.powered.Filaments.vol.numbers)/6 ) + 1) %}
|
|
354
|
+
{% for filament in range(1, 4) %}
|
|
355
|
+
{ Region Cut_<<layer>>_<<2*filament>> ; Branch { <<100*layer + 2*filament-1>>, <<100*layer + (2*filament+1)%6>> } ; }
|
|
356
|
+
{ Region filamentBnd_<<layer>>_<<2*filament-1>> ; Branch {1000, <<100*layer + 2*filament-1>>} ; }
|
|
357
|
+
{ Region Cut_<<layer>>_<<(2*filament+1)%6>> ; Branch { <<100*layer + 2*filament>>, <<100*layer + (2*filament+1)%6+1>> } ; }
|
|
358
|
+
{ Region filamentBnd_<<layer>>_<<2*filament>> ; Branch {1000, <<100*layer + 2*filament>>} ; }
|
|
359
|
+
{%endfor%}
|
|
360
|
+
{%endfor%}
|
|
361
|
+
|
|
362
|
+
{% else %}
|
|
363
|
+
{% for layer in range(1, int( len(rm.powered.Filaments.vol.numbers)/6 ) + 1) %}
|
|
364
|
+
{% for filament in range(1, 7) %}
|
|
365
|
+
{ Region Cut_<<layer>>_<<filament>> ; Branch { <<100*layer + filament>>, <<100*layer + filament%6+1>> } ; }
|
|
366
|
+
{ Region filamentBnd_<<layer>>_<<filament>> ; Branch {1000, <<100*layer + filament>>} ; }
|
|
367
|
+
{%endfor%}
|
|
368
|
+
{%endfor%}
|
|
369
|
+
{% endif %}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
{ Name h ; Type Assign ;
|
|
373
|
+
Case {
|
|
374
|
+
{% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
|
|
375
|
+
{Region OmegaC ; Type InitFromResolution ; NameOfResolution Projection_h_to_h ;}
|
|
376
|
+
{% endif %}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
FunctionSpace {
|
|
383
|
+
// Function space for magnetic field h in h-conform formulation. Main field for the magnetodynamic problem.
|
|
384
|
+
// h = sum phi_n * grad(psi_n) (nodes in Omega_CC with boundary)
|
|
385
|
+
// + sum h_e * psi_e (edges in Omega_C)
|
|
386
|
+
// + sum I_i * c_i (cuts, global basis functions for net current intensity) not yet here
|
|
387
|
+
{ Name h_space; Type Form1;
|
|
388
|
+
BasisFunction {
|
|
389
|
+
{ Name gradpsin; NameOfCoef phin; Function BF_GradNode;
|
|
390
|
+
Support OmegaCC_AndBnd; Entity NodesOf[OmegaCC]; } // Extend support to boundary for surface integration (e.g. useful for weak B.C.)
|
|
391
|
+
{ Name gradpsin; NameOfCoef phin2; Function BF_GroupOfEdges;
|
|
392
|
+
Support OmegaC; Entity GroupsOfEdgesOnNodesOf[BndOmegaC]; } // To treat properly the Omega_CC-Omega_C boundary
|
|
393
|
+
{ Name psie; NameOfCoef he; Function BF_Edge;
|
|
394
|
+
Support OmegaC_AndBnd; Entity EdgesOf[All, Not BndOmegaC]; }
|
|
395
|
+
{ Name sc; NameOfCoef Ii; Function BF_GroupOfEdges;
|
|
396
|
+
Support Omega; Entity GroupsOfEdgesOf[Cuts]; } // The region Cuts contains the union of all the relevant cuts (cohomology basis function support)
|
|
397
|
+
}
|
|
398
|
+
GlobalQuantity {
|
|
399
|
+
{ Name I ; Type AliasOf ; NameOfCoef Ii ; }
|
|
400
|
+
{ Name V ; Type AssociatedWith ; NameOfCoef Ii ; }
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
Constraint {
|
|
404
|
+
{ NameOfCoef he; EntityType EdgesOf; NameOfConstraint h; }
|
|
405
|
+
{ NameOfCoef phin; EntityType NodesOf; NameOfConstraint phi; }
|
|
406
|
+
{ NameOfCoef phin2; EntityType NodesOf; NameOfConstraint phi; }
|
|
407
|
+
{ NameOfCoef Ii ;
|
|
408
|
+
EntityType GroupsOfEdgesOf ; NameOfConstraint Current ; }
|
|
409
|
+
{ NameOfCoef V ;
|
|
410
|
+
EntityType GroupsOfNodesOf ; NameOfConstraint Voltage ; }
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Function space for the in-plane voltage field. Main field for the electrokinetics problem.
|
|
414
|
+
// The (in-plane) coupling current derive from this voltage j_coupling = - sigma * grad(v).
|
|
415
|
+
{ Name v_space_elKin ; Type Form0 ;
|
|
416
|
+
BasisFunction {
|
|
417
|
+
{ Name vn ; NameOfCoef vn ; Function BF_Node ;
|
|
418
|
+
Support Matrix_partitions_for_TI ; Entity NodesOf[All, Not BndFilaments] ; }
|
|
419
|
+
{ Name vi; NameOfCoef vi; Function BF_GroupOfNodes;
|
|
420
|
+
Support Matrix_partitions_for_TI; Entity GroupsOfNodesOf[BndFilaments]; }
|
|
421
|
+
}
|
|
422
|
+
GlobalQuantity {
|
|
423
|
+
{ Name V ; Type AliasOf ; NameOfCoef vi ; }
|
|
424
|
+
{ Name I ; Type AssociatedWith ; NameOfCoef vi ; }
|
|
425
|
+
}
|
|
426
|
+
Constraint {
|
|
427
|
+
{ NameOfCoef vn ; EntityType NodesOf ; NameOfConstraint v_plane ; }
|
|
428
|
+
{ NameOfCoef V ;
|
|
429
|
+
EntityType Region ; NameOfConstraint Voltage_plane ; }
|
|
430
|
+
{ NameOfCoef I ;
|
|
431
|
+
EntityType Region ; NameOfConstraint Current_plane ; }
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
435
|
+
// The curl of this space is the projection of the coupling current on this subspace (no net current from fil.)
|
|
436
|
+
{ Name h_perp_space_static; Type Form1P;
|
|
437
|
+
BasisFunction {
|
|
438
|
+
{ Name sn; NameOfCoef hn; Function BF_PerpendicularEdge;
|
|
439
|
+
Support Matrix_partitions_for_TI; Entity NodesOf[All]; }
|
|
440
|
+
}
|
|
441
|
+
Constraint {
|
|
442
|
+
{ NameOfCoef hn; EntityType NodesOf; NameOfConstraint hp_static; }
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// This is a Lagrange multplier for forcing the integral of hp_static to be zero in the matrix (avg field = 0)
|
|
446
|
+
{ Name h_perp_space_static_lagrange; Type Vector;
|
|
447
|
+
BasisFunction {
|
|
448
|
+
{ Name sn_lag; NameOfCoef hn_lag; Function BF_RegionZ;
|
|
449
|
+
Support Matrix_partitions_for_TI; Entity Matrix_partitions_for_TI; } // Ideally, should be only one function (not one per matrix part). To be double-checked!
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// This space will correct the static space above with dynamic effects
|
|
453
|
+
{ Name h_perp_space_dynamic; Type Form1P;
|
|
454
|
+
BasisFunction {
|
|
455
|
+
{ Name sn; NameOfCoef hn; Function BF_PerpendicularEdge;
|
|
456
|
+
Support Matrix_partitions_for_TI; Entity NodesOf[All, Not TI_adjacent_region ]; }
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
{% endif %}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
Jacobian {
|
|
463
|
+
{ Name Vol ;
|
|
464
|
+
Case {
|
|
465
|
+
{Region All ; Jacobian Vol ;}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
{ Name Sur ;
|
|
469
|
+
Case {
|
|
470
|
+
{ Region All ; Jacobian Sur ; }
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
Integration {
|
|
476
|
+
{ Name Int ;
|
|
477
|
+
Case {
|
|
478
|
+
{ Type Gauss ;
|
|
479
|
+
Case {
|
|
480
|
+
{ GeoElement Point ; NumberOfPoints 1 ; }
|
|
481
|
+
{ GeoElement Line ; NumberOfPoints 3 ; }
|
|
482
|
+
{ GeoElement Triangle ; NumberOfPoints 3 ; }
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
Formulation{
|
|
490
|
+
// h-formulation
|
|
491
|
+
{ Name MagDyn_hphi; Type FemEquation;
|
|
492
|
+
Quantity {
|
|
493
|
+
// Functions for the out-of-plane (OOP) problem
|
|
494
|
+
{ Name h; Type Local; NameOfSpace h_space; }
|
|
495
|
+
{ Name hp; Type Local; NameOfSpace h_space; }
|
|
496
|
+
{ Name I; Type Global; NameOfSpace h_space[I]; }
|
|
497
|
+
{ Name V; Type Global; NameOfSpace h_space[V]; }
|
|
498
|
+
// Functions for the in-plane (IP) problem
|
|
499
|
+
{ Name v; Type Local; NameOfSpace v_space_elKin; }
|
|
500
|
+
{ Name Vp; Type Global; NameOfSpace v_space_elKin[V]; }
|
|
501
|
+
{ Name Ip; Type Global; NameOfSpace v_space_elKin[I]; }
|
|
502
|
+
}
|
|
503
|
+
Equation {
|
|
504
|
+
// --- OOP problem ---
|
|
505
|
+
// Time derivative of b (NonMagnDomain)
|
|
506
|
+
Galerkin { [ ell* mu[] * Dof{h} / $DTime , {h} ];
|
|
507
|
+
In Omega; Integration Int; Jacobian Vol; }
|
|
508
|
+
Galerkin { [ - ell*mu[] * {h}[1] / $DTime , {h} ];
|
|
509
|
+
In Omega; Integration Int; Jacobian Vol; }
|
|
510
|
+
// Induced current (linear OmegaC)
|
|
511
|
+
Galerkin { [ ell*rho[mu0*Norm[{h}]] * Dof{d h} , {d h} ];
|
|
512
|
+
In LinOmegaC; Integration Int; Jacobian Vol; }
|
|
513
|
+
// Induced current (non-linear OmegaC)
|
|
514
|
+
Galerkin { [ ell*rho[{d h}, mu0*Norm[{h}]] * {d h} , {d h} ];
|
|
515
|
+
In NonLinOmegaC; Integration Int; Jacobian Vol; }
|
|
516
|
+
|
|
517
|
+
Galerkin { [ ell*dedj[{d h}, mu0*Norm[{h}]] * Dof{d h} , {d h} ];
|
|
518
|
+
In NonLinOmegaC; Integration Int; Jacobian Vol; } // For Newton-Raphson method
|
|
519
|
+
Galerkin { [ - ell*dedj[{d h}, mu0*Norm[{h}]] * {d h} , {d h} ];
|
|
520
|
+
In NonLinOmegaC; Integration Int; Jacobian Vol; } // For Newton-Raphson method
|
|
521
|
+
|
|
522
|
+
{% if dm.conductors[dm.magnet.solve.conductor_name].Jc_fit.type != 'Constant Jc' and dm.magnet.solve.general_parameters.superconductor_linear == False%}
|
|
523
|
+
Galerkin { [ ell*dedb[{d h}, mu0*{h}] * mu0*Dof{h} , {d hp} ];
|
|
524
|
+
In NonLinOmegaC; Integration Int; Jacobian Vol; } // For Newton-Raphson method
|
|
525
|
+
Galerkin { [ -ell*dedb[{d h}, mu0*{h}] * mu0*{h} , {d hp} ];
|
|
526
|
+
In NonLinOmegaC; Integration Int; Jacobian Vol; } // For Newton-Raphson method
|
|
527
|
+
{% endif %}
|
|
528
|
+
|
|
529
|
+
// Natural boundary condition for normal flux density (useful when transport current is an essential condition)
|
|
530
|
+
{% if dm.magnet.solve.source_parameters.boundary_condition_type == 'Natural' %}
|
|
531
|
+
Galerkin { [ - ell*dbsdt[] * Normal[] , {dInv h} ];
|
|
532
|
+
In BndAir; Integration Int; Jacobian Sur; }
|
|
533
|
+
{% endif %}
|
|
534
|
+
// Global term
|
|
535
|
+
GlobalTerm { [ Dof{V} , {I} ] ; In Cuts ; }
|
|
536
|
+
|
|
537
|
+
// --- IP problem ---
|
|
538
|
+
Galerkin { [ ell * sigma[mu0*Norm[{h}]] * Dof{d v} , {d v} ];
|
|
539
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; } // Matrix
|
|
540
|
+
GlobalTerm { [ Dof{Ip} , {Vp} ] ; In BndFilaments ; }
|
|
541
|
+
|
|
542
|
+
// --- Coupling between OOP and IP problems via circuit equations ---
|
|
543
|
+
GlobalEquation {
|
|
544
|
+
Type Network ; NameOfConstraint ElectricalCircuit ;
|
|
545
|
+
{ Node {I}; Loop {V}; Equation {V}; In Cuts ; }
|
|
546
|
+
{ Node {Ip}; Loop {Vp}; Equation {Ip}; In BndFilaments ; }
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
551
|
+
// h-formulation
|
|
552
|
+
{ Name MagDyn_hphi_dynCorr; Type FemEquation;
|
|
553
|
+
Quantity {
|
|
554
|
+
// Functions for the OOP and IP problems, that are just used here (and not solved for)
|
|
555
|
+
{ Name h; Type Local; NameOfSpace h_space; }
|
|
556
|
+
{ Name v; Type Local; NameOfSpace v_space_elKin; }
|
|
557
|
+
// Functions for the dynamic correction of the IP problem
|
|
558
|
+
{ Name hp_static; Type Local; NameOfSpace h_perp_space_static; }
|
|
559
|
+
{ Name hp_static_lagrange; Type Local; NameOfSpace h_perp_space_static_lagrange; }
|
|
560
|
+
{ Name hp_dynamic; Type Local; NameOfSpace h_perp_space_dynamic; }
|
|
561
|
+
}
|
|
562
|
+
Equation {
|
|
563
|
+
// --- Dynamic correction of the IP problem ---
|
|
564
|
+
// Projection of the static current flow on the curl of a "static" magnetic field
|
|
565
|
+
Galerkin { [ sigma[mu0*Norm[{h}]] * {d v} , {d hp_static} ]; // No DOF! Just take the solution of the previously solved v-based formulation
|
|
566
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
567
|
+
Galerkin { [ Dof{d hp_static} , {d hp_static} ];
|
|
568
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
569
|
+
Galerkin { [ Dof{hp_static_lagrange} , {hp_static} ];
|
|
570
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
571
|
+
Galerkin { [ Dof{hp_static} , {hp_static_lagrange} ];
|
|
572
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; } // ensure the magnetic field is averaged to zero over the matrix
|
|
573
|
+
// Introduce a dynamic component to the magnetic field
|
|
574
|
+
Galerkin { [ mu[] * Dof{hp_static} / $DTime , {hp_dynamic} ];
|
|
575
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
576
|
+
Galerkin { [ mu[] * Dof{hp_dynamic} / $DTime , {hp_dynamic} ];
|
|
577
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
578
|
+
Galerkin { [ - mu[] * {hp_static}[1] / $DTime , {hp_dynamic} ];
|
|
579
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
580
|
+
Galerkin { [ - mu[] * {hp_dynamic}[1] / $DTime , {hp_dynamic} ];
|
|
581
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; }
|
|
582
|
+
//Galerkin { [ - Dof{d v} , {d hp_dynamic} ];
|
|
583
|
+
// In Matrix; Integration Int; Jacobian Vol; } // Static field is curl-free so this contribution is unnecessary!
|
|
584
|
+
Galerkin { [ rho[mu0*Norm[{h}]] * Dof{d hp_dynamic} , {d hp_dynamic} ];
|
|
585
|
+
In Matrix_partitions_for_TI; Integration Int; Jacobian Vol; } // Only the dynamic correction is an eddy current
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
{% endif %}
|
|
589
|
+
{% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
|
|
590
|
+
// Projection formulation for initial condition
|
|
591
|
+
{ Name Projection_h_to_h; Type FemEquation;
|
|
592
|
+
Quantity {
|
|
593
|
+
{ Name h; Type Local; NameOfSpace h_space; }
|
|
594
|
+
}
|
|
595
|
+
Equation{
|
|
596
|
+
// 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).
|
|
597
|
+
// Validity of this to be checked again if we go to different meshes between the initial condition and the following simulation
|
|
598
|
+
Galerkin { [ Dof{h}, {h} ] ;
|
|
599
|
+
In Omega ; Jacobian Vol ; Integration Int ; }
|
|
600
|
+
Galerkin { [ - h_from_file[], {h} ] ;
|
|
601
|
+
In Omega ; Jacobian Vol ; Integration Int ; }
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
{% endif %}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
Macro CustomIterativeLoop
|
|
608
|
+
// Compute first solution guess and residual at step $TimeStep
|
|
609
|
+
Generate[A];
|
|
610
|
+
Solve[A]; Evaluate[ $syscount = $syscount + 1 ];
|
|
611
|
+
Generate[A]; GetResidual[A, $res0];
|
|
612
|
+
Evaluate[ $res = $res0 ];
|
|
613
|
+
Evaluate[ $iter = 0 ];
|
|
614
|
+
Evaluate[ $convCrit = 1e99 ];
|
|
615
|
+
PostOperation[MagDyn_energy];
|
|
616
|
+
Print[{$iter, $res, $res / $res0, $indicFilamentLoss},
|
|
617
|
+
Format "%g %14.12e %14.12e %14.12e", File infoResidualFile];
|
|
618
|
+
// ----- Enter the iterative loop (hand-made) -----
|
|
619
|
+
While[$convCrit > 1 && $res / $res0 <= 1e10 && $iter < iter_max]{
|
|
620
|
+
Solve[A]; Evaluate[ $syscount = $syscount + 1 ];
|
|
621
|
+
Generate[A]; GetResidual[A, $res];
|
|
622
|
+
Evaluate[ $iter = $iter + 1 ];
|
|
623
|
+
Evaluate[ $indicFilamentLossOld = $indicFilamentLoss];
|
|
624
|
+
PostOperation[MagDyn_energy];
|
|
625
|
+
Print[{$iter, $res, $res / $res0, $indicFilamentLoss},
|
|
626
|
+
Format "%g %14.12e %14.12e %14.12e", File infoResidualFile];
|
|
627
|
+
// Evaluate the convergence indicator
|
|
628
|
+
Evaluate[ $relChangeACLoss = Abs[($indicFilamentLossOld - $indicFilamentLoss)/((Abs[$indicFilamentLossOld]>1e-7 || $iter < 10) ? $indicFilamentLossOld:1e-7)] ];
|
|
629
|
+
Evaluate[ $convCrit = $relChangeACLoss/tol_energy];
|
|
630
|
+
}
|
|
631
|
+
Return
|
|
632
|
+
|
|
633
|
+
Resolution {
|
|
634
|
+
{ Name MagDyn;
|
|
635
|
+
System {
|
|
636
|
+
{Name A; NameOfFormulation MagDyn_hphi;}
|
|
637
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
638
|
+
{Name A_dynCorr; NameOfFormulation MagDyn_hphi_dynCorr;}
|
|
639
|
+
{% endif %}
|
|
640
|
+
}
|
|
641
|
+
Operation {
|
|
642
|
+
// Initialize directories
|
|
643
|
+
CreateDirectory[resDirectory];
|
|
644
|
+
DeleteFile[outputPower];
|
|
645
|
+
DeleteFile[infoResidualFile];
|
|
646
|
+
// Initialize the solution (initial condition)
|
|
647
|
+
SetTime[ timeStart ];
|
|
648
|
+
SetDTime[ dt ];
|
|
649
|
+
SetTimeStep[ 0 ];
|
|
650
|
+
InitSolution[A];
|
|
651
|
+
SaveSolution[A]; // Saves the solution x (from Ax = B) to .res file
|
|
652
|
+
Evaluate[ $syscount = 0 ];
|
|
653
|
+
Evaluate[ $saved = 1 ];
|
|
654
|
+
Evaluate[ $elapsedCTI = 1 ]; // Number of control time instants already treated
|
|
655
|
+
Evaluate[ $isCTI = 0 ];
|
|
656
|
+
|
|
657
|
+
{% if dm.magnet.solve.formulation_parameters.compute_temperature %}
|
|
658
|
+
Evaluate[ $cumulative_temperature = 0 ];
|
|
659
|
+
Evaluate[ $dT_old = 0 ];
|
|
660
|
+
{% endif %}
|
|
661
|
+
|
|
662
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
663
|
+
InitSolution[A_dynCorr];
|
|
664
|
+
SaveSolution[A_dynCorr];
|
|
665
|
+
{% else %}
|
|
666
|
+
Evaluate[ $indicTotalLoss_dyn = 0 ]; // Put it to zero to avoid warnings
|
|
667
|
+
Evaluate[ $indicCouplingLoss_dyn = 0 ]; // Put it to zero to avoid warnings
|
|
668
|
+
{% endif %}
|
|
669
|
+
// ----- Enter implicit Euler time integration loop (hand-made) -----
|
|
670
|
+
// Avoid too close steps at the end. Stop the simulation if the step becomes ridiculously small
|
|
671
|
+
SetExtrapolationOrder[ extrapolationOrder ];
|
|
672
|
+
While[$Time < timeFinal] {
|
|
673
|
+
SetTime[ $Time + $DTime ]; // Time instant at which we are looking for the solution
|
|
674
|
+
SetTimeStep[ $TimeStep + 1 ];
|
|
675
|
+
{% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear and dm.magnet.solve.numerical_parameters.source_type == 'piecewise'%}
|
|
676
|
+
// Make sure all CTI are exactly chosen
|
|
677
|
+
Evaluate[ $isCTI = 0 ];
|
|
678
|
+
Test[$Time >= time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} - 1e-7 ]{
|
|
679
|
+
Evaluate[ $isCTI = 1, $prevDTime = $DTime ]; // Also save the previous time step to restart from it after the CTI
|
|
680
|
+
SetDTime[ time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} - $Time + $DTime ];
|
|
681
|
+
SetTime[ time_multiplier*AtIndex[$elapsedCTI]{List[control_time_instants_list]} ]; // To compute exactly at the asked time instant
|
|
682
|
+
Print[{$Time}, Format "*** Control time instant: %g s."];
|
|
683
|
+
}
|
|
684
|
+
{% endif %}
|
|
685
|
+
// Iterative loop defined as a macro above
|
|
686
|
+
Print[{$Time, $DTime, $TimeStep}, Format "Start new time step. Time: %g s. Time step: %g s. Step: %g."];
|
|
687
|
+
Call CustomIterativeLoop;
|
|
688
|
+
// Has it converged? If yes, save solution and possibly increase the time step...
|
|
689
|
+
Test[ $iter < iter_max && ($res / $res0 <= 1e10 || $res0 == 0)]{
|
|
690
|
+
Print[{$Time, $DTime, $iter}, Format "Converged time %g s with time step %g s in %g iterations."];
|
|
691
|
+
// Save the solution of few time steps (small correction to avoid bad rounding)
|
|
692
|
+
// Test[ $Time >= $saved * writeInterval - 1e-7 || $Time + $DTime >= timeFinal]{
|
|
693
|
+
Test[ 1 ]{
|
|
694
|
+
// Test[ $Time >= $saved * $DTime - 1e-7 || $Time + $DTime >= timeFinal]{
|
|
695
|
+
SaveSolution[A];
|
|
696
|
+
// post
|
|
697
|
+
PostOperation[test_Losses];
|
|
698
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
699
|
+
Generate[A_dynCorr]; Solve[A_dynCorr]; SaveSolution[A_dynCorr];
|
|
700
|
+
PostOperation[test_Losses_dynCorr];
|
|
701
|
+
{% endif %}
|
|
702
|
+
Print[{$Time, $saved}, Format "Saved time %g s (saved solution number %g). Output power infos:"];
|
|
703
|
+
Print[{$Time, $indicFilamentLoss, $indicCouplingLoss, $indicEddyLoss, $indicTotalLoss, $indicCouplingLoss_dyn, $indicTotalLoss_dyn},
|
|
704
|
+
Format "%g %14.12e %14.12e %14.12e %14.12e %14.12e %14.12e", File outputPower];
|
|
705
|
+
|
|
706
|
+
// Compute the temperature
|
|
707
|
+
{% if dm.magnet.solve.formulation_parameters.compute_temperature == True %}
|
|
708
|
+
PostOperation[heat_capacity];
|
|
709
|
+
Evaluate[$dT = $DTime * $indicTotalLoss/$heat_capacity_per_unit_length];
|
|
710
|
+
Evaluate[ $cumulative_temperature = $cumulative_temperature + ($dT_old + $dT)/2 ];
|
|
711
|
+
Print[{$Time, $dT, $cumulative_temperature}, Format "%g %14.12e %14.12e", File outputTemperature];
|
|
712
|
+
Evaluate[ $dT_old = $dT ];
|
|
713
|
+
{% endif %}
|
|
714
|
+
|
|
715
|
+
Evaluate[$saved = $saved + 1];
|
|
716
|
+
}
|
|
717
|
+
{% if dm.magnet.solve.numerical_parameters.piecewise.force_stepping_at_times_piecewise_linear and dm.magnet.solve.numerical_parameters.source_type == 'piecewise' %}
|
|
718
|
+
// Consider the time step before the control time instant (if relevant) and increment $elapsedCTI
|
|
719
|
+
Test[ $isCTI == 1 ]{
|
|
720
|
+
Evaluate[ $elapsedCTI = $elapsedCTI + 1 ];
|
|
721
|
+
SetDTime[ $prevDTime ];
|
|
722
|
+
}
|
|
723
|
+
{% endif %}
|
|
724
|
+
// Increase the step if we converged sufficiently "fast" (and not a control time instant)
|
|
725
|
+
Test[ $iter < iter_max / 4 && $DTime < dt_max_var[] && $isCTI == 0 ]{
|
|
726
|
+
Evaluate[ $dt_new = Min[$DTime * 2, dt_max_var[]] ];
|
|
727
|
+
Print[{$dt_new}, Format "*** Fast convergence: increasing time step to %g"];
|
|
728
|
+
SetDTime[$dt_new];
|
|
729
|
+
}
|
|
730
|
+
Test[ $DTime > dt_max_var[]]{
|
|
731
|
+
Evaluate[ $dt_new = dt_max_var[] ];
|
|
732
|
+
Print[{$dt_new}, Format "*** Variable maximum time-stepping: reducing time step to %g"];
|
|
733
|
+
SetDTime[$dt_new];
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
// ...otherwise, reduce the time step and try again
|
|
737
|
+
{
|
|
738
|
+
Evaluate[ $dt_new = $DTime / 2 ];
|
|
739
|
+
Print[{$iter, $dt_new},
|
|
740
|
+
Format "*** Non convergence (iter %g): recomputing with reduced step %g"];
|
|
741
|
+
RemoveLastSolution[A];
|
|
742
|
+
SetTime[$Time - $DTime];
|
|
743
|
+
SetTimeStep[$TimeStep - 1];
|
|
744
|
+
SetDTime[$dt_new];
|
|
745
|
+
// If it gets ridicoulously small, end the simulation, and report the information in crash file.
|
|
746
|
+
Test[ $dt_new < dt_max/10000 ]{
|
|
747
|
+
Print[{$iter, $dt_new, $Time},
|
|
748
|
+
Format "*** Non convergence (iter %g): time step %g too small, stopping the simulation at time %g s.", File crashReportFile];
|
|
749
|
+
// Print[A];
|
|
750
|
+
Exit;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
} // ----- End time loop -----
|
|
754
|
+
// Print information about the resolution and the nonlinear iterations
|
|
755
|
+
Print[{$syscount}, Format "Total number of linear systems solved: %g"];
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
{% if dm.magnet.solve.initial_conditions.init_from_pos_file %}
|
|
759
|
+
{ Name Projection_h_to_h;
|
|
760
|
+
System {
|
|
761
|
+
{Name Projection_h_to_h; NameOfFormulation Projection_h_to_h; DestinationSystem A ;}
|
|
762
|
+
}
|
|
763
|
+
Operation {
|
|
764
|
+
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)
|
|
765
|
+
Generate[Projection_h_to_h]; Solve[Projection_h_to_h];
|
|
766
|
+
TransferSolution[Projection_h_to_h];
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
{% endif %}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
PostProcessing {
|
|
773
|
+
{ Name MagDyn_hphi; NameOfFormulation MagDyn_hphi;
|
|
774
|
+
Quantity {
|
|
775
|
+
{ Name phi; Value{ Local{ [ {dInv h} ] ;
|
|
776
|
+
In OmegaCC; Jacobian Vol; } } }
|
|
777
|
+
{ Name h; Value{ Local{ [ {h} ] ;
|
|
778
|
+
In Omega; Jacobian Vol; } } }
|
|
779
|
+
{ Name b; Value{ Local{ [ mu[] * {h} ] ;
|
|
780
|
+
In Omega; Jacobian Vol; } } }
|
|
781
|
+
{ Name b_reaction; Value{ Local{ [ mu[] * ({h} - hsVal[]) ] ;
|
|
782
|
+
In Omega; Jacobian Vol; } } }
|
|
783
|
+
{ Name j; Value{ Local{ [ {d h} ] ;
|
|
784
|
+
In OmegaC; Jacobian Vol; } } }
|
|
785
|
+
{ Name jc; Value{ Local{ [ jc[mu0*Norm[{h}]] ] ;
|
|
786
|
+
In NonLinOmegaC; Jacobian Vol; } } }
|
|
787
|
+
{ Name power_filaments; Value{ Local{ [ rho[{d h}, mu0*Norm[{h}]] * {d h} * {d h} ] ; // j*e : Power (only for filaments)
|
|
788
|
+
In NonLinOmegaC; Jacobian Vol; } } }
|
|
789
|
+
{ Name sigma_matrix; Value{ Local{ [ sigma[mu0*Norm[{h}]]] ;
|
|
790
|
+
In Matrix; Jacobian Vol; } } }
|
|
791
|
+
{ Name j_plane; Value{ Local{ [ -1/rho[mu0*Norm[{h}]] * {d v} ] ;
|
|
792
|
+
In Matrix; Jacobian Vol; } } }
|
|
793
|
+
{ Name v_plane; Value{ Local{ [ {v} ] ;
|
|
794
|
+
In Matrix; Jacobian Vol; } } }
|
|
795
|
+
{ Name power_matrix;
|
|
796
|
+
Value{
|
|
797
|
+
Local{ [rho[mu0*Norm[{h}]] * {d h} * {d h}] ; // j*e = rho*j^2 in matrix (eddy)
|
|
798
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
799
|
+
Local{ [ (sigma[mu0*Norm[{h}]] * {d v}) * {d v}] ; // j*e = sigma*e^2 in matrix (coupling)
|
|
800
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
{ Name couplingLoss;
|
|
804
|
+
Value{
|
|
805
|
+
Integral{ [ (sigma[mu0*Norm[{h}]] * {d v}) * {d v}] ; // j*e = sigma*e^2 in matrix
|
|
806
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
{ Name eddyLoss; // NEW. Eddyloss was computed as totalLoss[matrix], which combines eddy and couplingLoss
|
|
810
|
+
Value{
|
|
811
|
+
Integral{ [rho[mu0*Norm[{h}]] * {d h} * {d h}] ; // EddyLoss = rho*j^2 in matrix
|
|
812
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
{ Name totalLoss;
|
|
816
|
+
Value{
|
|
817
|
+
// Separate OmegaC into Matrix and nonlinear (resistivities take different argument types)
|
|
818
|
+
Integral{ [rho[{d h}, mu0*Norm[{h}]] * {d h} * {d h}] ; // j*e = rho*j^2 (filaments)
|
|
819
|
+
In NonLinOmegaC ; Integration Int ; Jacobian Vol; }
|
|
820
|
+
Integral{ [rho[mu0*Norm[{h}]] * {d h} * {d h}] ; // j*e = rho*j^2 (eddy)
|
|
821
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
822
|
+
Integral{ [ (sigma[mu0*Norm[{h}]]*{d v}) * {d v}] ; // j*e = sigma*e^2 in matrix (coupling)
|
|
823
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
{ Name heat_capacity;
|
|
828
|
+
Value{
|
|
829
|
+
Integral{ [(filament_Cv[T[] + $cumulative_temperature, mu0*Norm[{h}]] )] ; // j*e = rho*j^2 in filaments (?)
|
|
830
|
+
In NonLinOmegaC ; Integration Int ; Jacobian Vol; }
|
|
831
|
+
Integral{ [(matrix_Cv[T[] + $cumulative_temperature]) ] ; // j*e = rho*j^2 in filaments (?)
|
|
832
|
+
In NonLinOmegaC ; Integration Int ; Jacobian Vol; }
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
{ Name I; Value { Term{ [ {I} ] ; In Cuts; } } }
|
|
837
|
+
{ Name V; Value { Term{ [ {V} ] ; In Cuts; } } }
|
|
838
|
+
{ Name Ip; Value { Term{ [ {Ip} ] ; In BndFilaments; } } }
|
|
839
|
+
{ Name Vp; Value { Term{ [ {Vp} ] ; In BndFilaments; } } }
|
|
840
|
+
{ Name I_integral;
|
|
841
|
+
Value{
|
|
842
|
+
Integral{ [ {d h} * Vector[0,0,1]] ;
|
|
843
|
+
In OmegaC ; Integration Int ; Jacobian Vol; }
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
{ Name I_abs_integral;
|
|
847
|
+
Value{
|
|
848
|
+
Integral{ [ Fabs[{d h} * Vector[0,0,1]]] ;
|
|
849
|
+
In OmegaC ; Integration Int ; Jacobian Vol; }
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
// Applied field (useful for magnetization plots)
|
|
853
|
+
{ Name hsVal; Value{ Term { [ hsVal[] ]; In Omega; } } }
|
|
854
|
+
// Magnetization: integral of 1/2 * (r /\ j) in a conducting (sub-)domain
|
|
855
|
+
{ Name m_avg; Value{ Integral{ [ 0.5 * XYZ[] /\ {d h} ] ;
|
|
856
|
+
In OmegaC; Integration Int; Jacobian Vol; } } }
|
|
857
|
+
// Magnetic energy
|
|
858
|
+
{ Name magnetic_energy; Value{ Integral{ [ 0.5 * mu[] * {h} * {h} ] ;
|
|
859
|
+
In Omega; Integration Int; Jacobian Vol; } } }
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
863
|
+
{ Name MagDyn_hphi_dynCorr; NameOfFormulation MagDyn_hphi_dynCorr;
|
|
864
|
+
Quantity {
|
|
865
|
+
{ Name hp_static; Value{ Local{ [ {hp_static} ] ;
|
|
866
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
867
|
+
{ Name hp_static_lagrange; Value{ Local{ [ {hp_static_lagrange} ] ;
|
|
868
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
869
|
+
{ Name j_static; Value{ Local{ [ {d hp_static} ] ;
|
|
870
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
871
|
+
{ Name hp_dynamic; Value{ Local{ [ {hp_dynamic} ] ;
|
|
872
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
873
|
+
{ Name j_dynamic; Value{ Local{ [ {d hp_dynamic} ] ;
|
|
874
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
875
|
+
{ Name j_stadyn; Value{ Local{ [ {d hp_static} + {d hp_dynamic} ] ;
|
|
876
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
877
|
+
{ Name j_stadyn_mixed; Value{ Local{ [ - sigma[mu0*Norm[{h}]] * {d v} + {d hp_dynamic} ] ;
|
|
878
|
+
In Matrix_partitions_for_TI; Jacobian Vol; } } }
|
|
879
|
+
{ Name totalLoss_dyn;
|
|
880
|
+
Value{
|
|
881
|
+
// Integral{ [rho[{d h}, mu0*Norm[{h}]] * {d h} * {d h}] ;
|
|
882
|
+
// In OmegaC ; Integration Int ; Jacobian Vol; }
|
|
883
|
+
// NEW separate OmegaC into Matrix and nonlinear
|
|
884
|
+
Integral{ [rho[{d h}, mu0*Norm[{h}]] * {d h} * {d h}] ; // j*e = rho*j^2 in filaments
|
|
885
|
+
In NonLinOmegaC ; Integration Int ; Jacobian Vol; }
|
|
886
|
+
Integral{ [rho[mu0*Norm[{h}]] * {d h} * {d h}] ; // Eddy
|
|
887
|
+
In Matrix ; Integration Int ; Jacobian Vol; }
|
|
888
|
+
Integral{ [ (- sigma[mu0*Norm[{h}]]*{d v} + {d hp_dynamic}) * (- {d v} + rho[mu0*Norm[{h}]] * {d hp_dynamic})] ;
|
|
889
|
+
In Matrix_partitions_for_TI ; Integration Int ; Jacobian Vol; } // Attention to signs!
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
{ Name couplingLoss_dyn;
|
|
893
|
+
Value{
|
|
894
|
+
Integral{ [(- sigma[mu0*Norm[{h}]]*{d v} + {d hp_dynamic}) * (- {d v} + rho[mu0*Norm[{h}]] * {d hp_dynamic})] ;
|
|
895
|
+
In Matrix_partitions_for_TI ; Integration Int ; Jacobian Vol; } // Attention to signs!
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
{% endif %}
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
PostOperation {
|
|
904
|
+
{ Name MagDyn;
|
|
905
|
+
NameOfPostProcessing MagDyn_hphi;
|
|
906
|
+
Operation {
|
|
907
|
+
// Local field solutions
|
|
908
|
+
{% if dm.magnet.postproc.generate_pos_files%}
|
|
909
|
+
Print[ b, OnElementsOf Omega , File StrCat["b.pos"], Name "b [T]" ];
|
|
910
|
+
Print[ b_reaction, OnElementsOf Omega , File StrCat["br.pos"], Name "br [T]" ];
|
|
911
|
+
Print[ j, OnElementsOf OmegaC , File StrCat["j.pos"], Name "j [A/m2]" ];
|
|
912
|
+
// Print[ jc, OnElementsOf NonLinOmegaC , File StrCat["jc.pos"], Name "jc [A/m2]" ];
|
|
913
|
+
Print[ j_plane, OnElementsOf Matrix , File StrCat["jPlane.pos"], Name "j_plane [A/m2]" ];
|
|
914
|
+
Print[ v_plane, OnElementsOf Matrix , File StrCat["vPlane.pos"], Name "v_plane [V/m]" ];
|
|
915
|
+
// Print[ power_filaments, OnElementsOf NonLinOmegaC , File StrCat["powFil_f.pos"], Name "powerFilaments [W]" ];
|
|
916
|
+
// Print[ power_matrix, OnElementsOf Matrix , File StrCat["powMat_f.pos"], Name "powerMatrix [W]" ];
|
|
917
|
+
// Print[ sigma_matrix, OnElementsOf Matrix , File StrCat["sigmaMat_f.pos"], Name "sigmaMatrix [S/m]" ];
|
|
918
|
+
Print[ phi, OnElementsOf OmegaCC , File StrCat["phi_f.pos"], Name "phi [A]" ];
|
|
919
|
+
{% endif %}
|
|
920
|
+
// Global solutions
|
|
921
|
+
Print[ I, OnRegion BndMatrixCut, File StrCat[resDirectory,"/I_transport.txt"], Format SimpleTable];
|
|
922
|
+
Print[ V, OnRegion BndMatrixCut, File StrCat[resDirectory,"/V_transport.txt"], Format SimpleTable];
|
|
923
|
+
Print[ hsVal[Omega], OnRegion Matrix, Format TimeTable, File StrCat[resDirectory, "/hs_val.txt"]];
|
|
924
|
+
Print[ m_avg[Filaments], OnGlobal, Format TimeTable, File StrCat[resDirectory, "/magn_fil.txt"]];
|
|
925
|
+
Print[ m_avg[Matrix], OnGlobal, Format TimeTable, File StrCat[resDirectory, "/magn_matrix.txt"]];
|
|
926
|
+
Print[ magnetic_energy[OmegaC], OnGlobal, Format TimeTable, File StrCat[resDirectory, "/magnetic_energy_internal.txt"]];
|
|
927
|
+
{% if dm.magnet.postproc.compute_current_per_filament == True %}
|
|
928
|
+
// Integrals of local quantities
|
|
929
|
+
Print[I_integral[filament_1_1], OnGlobal, File StrCat[resDirectory,"/I_integral.txt"], Format SimpleTable];
|
|
930
|
+
For i In {1:number_of_layers}
|
|
931
|
+
For j In {((i==1)?2:1):6}
|
|
932
|
+
Print[I_integral[filament~{i}~{j}], OnGlobal, File > StrCat[resDirectory,"/I_integral.txt"], Format SimpleTable];
|
|
933
|
+
EndFor
|
|
934
|
+
EndFor
|
|
935
|
+
Print[I_abs_integral[filament_1_1], OnGlobal, File StrCat[resDirectory,"/I_abs_integral.txt"], Format SimpleTable];
|
|
936
|
+
For i In {1:number_of_layers}
|
|
937
|
+
For j In {((i==1)?2:1):6}
|
|
938
|
+
Print[I_abs_integral[filament~{i}~{j}], OnGlobal, File > StrCat[resDirectory,"/I_abs_integral.txt"], Format SimpleTable];
|
|
939
|
+
EndFor
|
|
940
|
+
EndFor
|
|
941
|
+
// Global quantities (out-of-plane)
|
|
942
|
+
Print[I, OnRegion Cut_1_1, File StrCat[resDirectory,"/I.txt"], Format SimpleTable];
|
|
943
|
+
For i In {1:number_of_layers}
|
|
944
|
+
For j In {((i==1)?2:1):6}
|
|
945
|
+
Print[I, OnRegion Cut~{i}~{j}, File > StrCat[resDirectory,"/I.txt"], Format SimpleTable];
|
|
946
|
+
EndFor
|
|
947
|
+
EndFor
|
|
948
|
+
Print[V, OnRegion Cut_1_1, File StrCat[resDirectory,"/V.txt"], Format SimpleTable];
|
|
949
|
+
For i In {1:number_of_layers}
|
|
950
|
+
For j In {((i==1)?2:1):6}
|
|
951
|
+
Print[V, OnRegion Cut~{i}~{j}, File > StrCat[resDirectory,"/V.txt"], Format SimpleTable];
|
|
952
|
+
EndFor
|
|
953
|
+
EndFor
|
|
954
|
+
// Global quantities (in-plane)
|
|
955
|
+
Print[Ip, OnRegion filamentBnd_1_1, File StrCat[resDirectory,"/Ip.txt"], Format SimpleTable];
|
|
956
|
+
For i In {1:number_of_layers}
|
|
957
|
+
For j In {((i==1)?2:1):6}
|
|
958
|
+
Print[Ip, OnRegion filamentBnd~{i}~{j}, File > StrCat[resDirectory,"/Ip.txt"], Format SimpleTable];
|
|
959
|
+
EndFor
|
|
960
|
+
EndFor
|
|
961
|
+
Print[Vp, OnRegion filamentBnd_1_1, File StrCat[resDirectory,"/Vp.txt"], Format SimpleTable];
|
|
962
|
+
For i In {1:number_of_layers}
|
|
963
|
+
For j In {((i==1)?2:1):6}
|
|
964
|
+
Print[Vp, OnRegion filamentBnd~{i}~{j}, File > StrCat[resDirectory,"/Vp.txt"], Format SimpleTable];
|
|
965
|
+
EndFor
|
|
966
|
+
EndFor
|
|
967
|
+
{% endif %}
|
|
968
|
+
{% if dm.magnet.postproc.save_last_current_density is not none %}
|
|
969
|
+
// Last current density distribution for projection (not ready yet)
|
|
970
|
+
Print[ j, OnElementsOf OmegaC, Format GmshParsed , File StrCat["../", "<<dm.magnet.postproc.save_last_current_density>>", ".pos"], Name "j [A/m2]", LastTimeStepOnly ];
|
|
971
|
+
{% endif %}
|
|
972
|
+
{% if dm.magnet.postproc.save_last_magnetic_field != "None" %}
|
|
973
|
+
// Last magnetic field solution for projection. Note the special format GmshParsed required for proper GmshRead[] operation in the later pre-resolution.
|
|
974
|
+
Print[ h, OnElementsOf Omega, Format GmshParsed , File StrCat["../", "<<dm.magnet.postproc.save_last_magnetic_field>>", ".pos"], Name "h [A/m]", LastTimeStepOnly ];
|
|
975
|
+
{% endif %}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
979
|
+
{ Name MagDyn_dynCorr;
|
|
980
|
+
NameOfPostProcessing MagDyn_hphi_dynCorr;
|
|
981
|
+
Operation {
|
|
982
|
+
{% if dm.magnet.postproc.generate_pos_files%}
|
|
983
|
+
Print[ j_dynamic, OnElementsOf Matrix_partitions_for_TI , File StrCat["j_dynamic.pos"], Name "j_dynamic [A/m2]" ];
|
|
984
|
+
Print[ j_stadyn_mixed, OnElementsOf Matrix_partitions_for_TI , File StrCat["j_stadyn_mixed.pos"], Name "j_stadyn_mixed [A/m2]" ];
|
|
985
|
+
Print[ hp_dynamic, OnElementsOf Matrix_partitions_for_TI , File StrCat["hp_dynamic.pos"], Name "hp_dynamic [A/m]" ];
|
|
986
|
+
// Print[ hp_static, OnElementsOf Matrix , File StrCat["hp_static.pos"], Name "hp_static [A/m]" ];
|
|
987
|
+
// Print[ hp_static_lagrange, OnElementsOf Matrix , File StrCat["hp_static_lagrange.pos"], Name "hp_static_lagrange [A/m]" ];
|
|
988
|
+
{% endif %}
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
{% endif %}
|
|
992
|
+
{ Name MagDyn_energy; LastTimeStepOnly 1 ;
|
|
993
|
+
NameOfPostProcessing MagDyn_hphi;
|
|
994
|
+
Operation {
|
|
995
|
+
Print[ totalLoss[NonLinOmegaC], OnGlobal, Format Table, StoreInVariable $indicFilamentLoss, File StrCat[resDirectory,"/dummy.txt"] ];
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
{ Name test_Losses; LastTimeStepOnly 1 ;
|
|
999
|
+
NameOfPostProcessing MagDyn_hphi;
|
|
1000
|
+
Operation {
|
|
1001
|
+
Print[ totalLoss[NonLinOmegaC], OnGlobal, Format Table, StoreInVariable $indicFilamentLoss, File StrCat[resDirectory,"/dummy.txt"] ];
|
|
1002
|
+
// Print[ totalLoss[Matrix], OnGlobal, Format Table, StoreInVariable $indicEddyLoss, File > StrCat[resDirectory,"/dummy.txt"] ];
|
|
1003
|
+
Print[ eddyLoss[Matrix], OnGlobal, Format Table, StoreInVariable $indicEddyLoss, File > StrCat[resDirectory,"/dummy.txt"] ];
|
|
1004
|
+
Print[ couplingLoss[Matrix], OnGlobal, Format Table, StoreInVariable $indicCouplingLoss, File > StrCat[resDirectory,"/dummy.txt"] ];
|
|
1005
|
+
Print[ totalLoss[OmegaC], OnGlobal, Format Table, StoreInVariable $indicTotalLoss, File > StrCat[resDirectory,"/dummy.txt"] ];
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
{ Name heat_capacity; LastTimeStepOnly 1 ;
|
|
1010
|
+
NameOfPostProcessing MagDyn_hphi;
|
|
1011
|
+
Operation {
|
|
1012
|
+
Print[ heat_capacity[OmegaC], OnGlobal, Format Table, StoreInVariable $heat_capacity_per_unit_length, File StrCat[resDirectory,"/dummy.txt"] ];
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
{% if dm.magnet.solve.formulation_parameters.dynamic_correction == True %}
|
|
1017
|
+
{ Name test_Losses_dynCorr; LastTimeStepOnly 1 ;
|
|
1018
|
+
NameOfPostProcessing MagDyn_hphi_dynCorr;
|
|
1019
|
+
Operation {
|
|
1020
|
+
Print[ totalLoss_dyn[OmegaC], OnGlobal, Format Table, StoreInVariable $indicTotalLoss_dyn, File > StrCat[resDirectory,"/dummy.txt"] ];
|
|
1021
|
+
Print[ couplingLoss_dyn[Matrix_partitions_for_TI], OnGlobal, Format Table, StoreInVariable $indicCouplingLoss_dyn, File > StrCat[resDirectory,"/dummy.txt"] ];
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
{% endif %}
|
|
1025
|
+
}
|