fiqus 2024.7.0__py3-none-any.whl → 2024.12.1__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 (69) hide show
  1. fiqus/MainFiQuS.py +290 -134
  2. fiqus/data/DataConductor.py +301 -301
  3. fiqus/data/DataFiQuS.py +128 -84
  4. fiqus/data/DataFiQuSCCT.py +150 -150
  5. fiqus/data/DataFiQuSConductor.py +84 -84
  6. fiqus/data/DataFiQuSConductorAC_Strand.py +565 -565
  7. fiqus/data/DataFiQuSMultipole.py +716 -42
  8. fiqus/data/DataFiQuSPancake3D.py +737 -278
  9. fiqus/data/DataMultipole.py +180 -15
  10. fiqus/data/DataRoxieParser.py +90 -51
  11. fiqus/data/DataSettings.py +121 -0
  12. fiqus/data/DataWindingsCCT.py +37 -37
  13. fiqus/data/RegionsModelFiQuS.py +18 -6
  14. fiqus/geom_generators/GeometryCCT.py +905 -905
  15. fiqus/geom_generators/GeometryConductorAC_Strand.py +1391 -1391
  16. fiqus/geom_generators/GeometryMultipole.py +1827 -227
  17. fiqus/geom_generators/GeometryPancake3D.py +316 -117
  18. fiqus/geom_generators/GeometryPancake3DUtils.py +549 -0
  19. fiqus/getdp_runners/RunGetdpCCT.py +4 -4
  20. fiqus/getdp_runners/RunGetdpConductorAC_Strand.py +201 -201
  21. fiqus/getdp_runners/RunGetdpMultipole.py +115 -42
  22. fiqus/getdp_runners/RunGetdpPancake3D.py +28 -6
  23. fiqus/mains/MainCCT.py +2 -2
  24. fiqus/mains/MainConductorAC_Strand.py +132 -132
  25. fiqus/mains/MainMultipole.py +113 -62
  26. fiqus/mains/MainPancake3D.py +63 -23
  27. fiqus/mesh_generators/MeshCCT.py +209 -209
  28. fiqus/mesh_generators/MeshConductorAC_Strand.py +656 -656
  29. fiqus/mesh_generators/MeshMultipole.py +1243 -181
  30. fiqus/mesh_generators/MeshPancake3D.py +275 -192
  31. fiqus/parsers/ParserCOND.py +825 -0
  32. fiqus/parsers/ParserDAT.py +16 -16
  33. fiqus/parsers/ParserGetDPOnSection.py +212 -212
  34. fiqus/parsers/ParserGetDPTimeTable.py +134 -134
  35. fiqus/parsers/ParserMSH.py +53 -53
  36. fiqus/parsers/ParserPOS.py +214 -214
  37. fiqus/parsers/ParserRES.py +142 -142
  38. fiqus/plotters/PlotPythonCCT.py +133 -133
  39. fiqus/plotters/PlotPythonConductorAC.py +855 -855
  40. fiqus/plotters/PlotPythonMultipole.py +18 -18
  41. fiqus/post_processors/PostProcessCCT.py +440 -440
  42. fiqus/post_processors/PostProcessConductorAC.py +49 -49
  43. fiqus/post_processors/PostProcessMultipole.py +353 -229
  44. fiqus/post_processors/PostProcessPancake3D.py +8 -13
  45. fiqus/pre_processors/PreProcessCCT.py +175 -175
  46. fiqus/pro_assemblers/ProAssembler.py +14 -6
  47. fiqus/pro_material_functions/ironBHcurves.pro +246 -246
  48. fiqus/pro_templates/combined/CCT_template.pro +274 -274
  49. fiqus/pro_templates/combined/ConductorAC_template.pro +1025 -1025
  50. fiqus/pro_templates/combined/Multipole_template.pro +1694 -126
  51. fiqus/pro_templates/combined/Pancake3D_template.pro +2294 -1103
  52. fiqus/pro_templates/combined/TSA_materials.pro +162 -0
  53. fiqus/pro_templates/combined/materials.pro +36 -18
  54. fiqus/utils/Utils.py +508 -110
  55. fiqus/utils/update_data_settings.py +33 -0
  56. fiqus-2024.12.1.dist-info/METADATA +132 -0
  57. fiqus-2024.12.1.dist-info/RECORD +84 -0
  58. {fiqus-2024.7.0.dist-info → fiqus-2024.12.1.dist-info}/WHEEL +1 -1
  59. tests/test_FiQuS.py +1 -1
  60. tests/test_geometry_generators.py +101 -2
  61. tests/test_mesh_generators.py +154 -1
  62. tests/test_solvers.py +115 -21
  63. tests/utils/fiqus_test_classes.py +85 -21
  64. tests/utils/generate_reference_files_ConductorAC.py +57 -57
  65. tests/utils/generate_reference_files_Pancake3D.py +4 -5
  66. tests/utils/helpers.py +97 -97
  67. fiqus-2024.7.0.dist-info/METADATA +0 -103
  68. fiqus-2024.7.0.dist-info/RECORD +0 -79
  69. {fiqus-2024.7.0.dist-info → fiqus-2024.12.1.dist-info}/top_level.txt +0 -0
@@ -1,67 +1,973 @@
1
- // BH curve for iron yoke
2
1
  Include "<<BHcurves>>";
2
+ {% import "materials.pro" as materials %}
3
+ {% import "TSA_materials.pro" as TSA_materials %}
4
+
5
+ {% macro criticalCurrentDensity(region_name, cond, time_trigger, cond_name) %}
6
+ {% if cond.Jc_fit.type == 'CUDI1' %}
7
+ {% if cond.strand.type == 'Round' %}
8
+ {% set wire_diameter = (cond.cable.n_strands)**(1/2) * cond.strand.diameter %}
9
+ {% elif cond.strand.type == 'Rectangular' %}
10
+ {% set n_strands = cond.cable.n_strands if cond.cable.type == 'Rutherford' else 1 %}
11
+ {% set wire_diameter = (4 * n_strands * cond.strand.bare_width * cond.strand.bare_height / Pi) ** (1 / 2) %}
12
+ {% endif %}
13
+ criticalCurrentDensity[<<region_name>>] = $Time > <<time_trigger>>? 0: <<materials[criticalCurrentDensityMacroName[cond.strand.material_superconductor + '_' + cond.Jc_fit.type]](C1=cond.Jc_fit.C1_CUDI1, C2=cond.Jc_fit.C2_CUDI1, Tc0=cond.Jc_fit.Tc0_CUDI1, Bc20=cond.Jc_fit.Bc20_CUDI1, wireDiameter=wire_diameter, Cu_noCu=cond.strand.Cu_noCu_in_strand)>> * f_sc_<<cond_name>>;
14
+ {% elif cond.Jc_fit.type == 'Summers' %}
15
+ criticalCurrentDensity[<<region_name>>] = $Time > <<time_trigger>>? 0: <<materials[criticalCurrentDensityMacroName[cond.strand.material_superconductor + '_' + cond.Jc_fit.type]](Jc0=cond.Jc_fit.Jc0_Summers, Tc0=cond.Jc_fit.Tc0_Summers, Bc20=cond.Jc_fit.Bc20_Summers)>> * f_sc_<<cond_name>>;
16
+ {% elif cond.Jc_fit.type == 'Bordini' %}
17
+ criticalCurrentDensity[<<region_name>>] = $Time > <<time_trigger>>? 0: <<materials[criticalCurrentDensityMacroName[cond.strand.material_superconductor + '_' + cond.Jc_fit.type]](Tc0=cond.Jc_fit.Tc0_Bordini, Bc20=cond.Jc_fit.Bc20_Bordini, C0=cond.Jc_fit.C0_Bordini, alpha=cond.Jc_fit.alpha_Bordini)>> * f_sc_<<cond_name>>;
18
+ {% elif cond.Jc_fit.type == 'BSCCO_2212_LBNL' %}
19
+ criticalCurrentDensity[<<region_name>>] = $Time > <<time_trigger>>? 0: <<materials[criticalCurrentDensityMacroName[cond.strand.material_superconductor + '_' + cond.Jc_fit.type]](f_scaling=cond.Jc_fit.f_scaling_Jc_BSCCO2212)>> * f_sc_<<cond_name>>;
20
+ {% endif %}
21
+ {% endmacro %}
22
+
23
+ {% if dm.magnet.solve.thermal.solve_type %}
24
+
25
+ stop_temperature = <<dm.magnet.solve.thermal.time_stepping.stop_temperature>>;
26
+ /* -------------------------------------------------------------------------- */
27
+ {% if dm.magnet.geometry.thermal.use_TSA %}
28
+ // Checkered support indexing for bare part
29
+ // first index: neighboring information in azimuthal direction
30
+ // second index: neighboring information in radial direction
31
+ {% if dm.magnet.geometry.thermal.with_wedges %}
32
+ {% set bare_1_1 = rm_TH.powered['r1_a1'].vol.numbers + rm_TH.induced['r1_a1'].vol.numbers %}
33
+ {% set bare_2_1 = rm_TH.powered['r2_a1'].vol.numbers + rm_TH.induced['r2_a1'].vol.numbers %}
34
+ {% set bare_1_2 = rm_TH.powered['r1_a2'].vol.numbers + rm_TH.induced['r1_a2'].vol.numbers %}
35
+ {% set bare_2_2 = rm_TH.powered['r2_a2'].vol.numbers + rm_TH.induced['r2_a2'].vol.numbers %}
36
+ {% else %}
37
+ {% set bare_1_1 = rm_TH.powered['r1_a1'].vol.numbers %}
38
+ {% set bare_2_1 = rm_TH.powered['r2_a1'].vol.numbers %}
39
+ {% set bare_1_2 = rm_TH.powered['r1_a2'].vol.numbers %}
40
+ {% set bare_2_2 = rm_TH.powered['r2_a2'].vol.numbers %}
41
+ {% endif %}
42
+
43
+ bare_1_1 = {<<bare_1_1|join(', ')>>};
44
+ bare_2_1 = {<<bare_2_1|join(', ')>>};
45
+ bare_1_2 = {<<bare_1_2|join(', ')>>};
46
+ bare_2_2 = {<<bare_2_2|join(', ')>>};
47
+
48
+ // Shell lines belonging to the bare parts as indexed above
49
+ {% if dm.magnet.geometry.thermal.with_wedges %}
50
+ {% set bare_layers_1_1 = rm_TH.powered['r1_a1'].surf_in.numbers + rm_TH.induced['r1_a1'].surf_in.numbers %}
51
+ {% set bare_layers_2_1 = rm_TH.powered['r2_a1'].surf_in.numbers + rm_TH.induced['r2_a1'].surf_in.numbers %}
52
+ {% set bare_layers_1_2 = rm_TH.powered['r1_a2'].surf_in.numbers + rm_TH.induced['r1_a2'].surf_in.numbers %}
53
+ {% set bare_layers_2_2 = rm_TH.powered['r2_a2'].surf_in.numbers + rm_TH.induced['r2_a2'].surf_in.numbers %}
54
+ {% else %}
55
+ {% set bare_layers_1_1 = rm_TH.powered['r1_a1'].surf_in.numbers %}
56
+ {% set bare_layers_2_1 = rm_TH.powered['r2_a1'].surf_in.numbers %}
57
+ {% set bare_layers_1_2 = rm_TH.powered['r1_a2'].surf_in.numbers %}
58
+ {% set bare_layers_2_2 = rm_TH.powered['r2_a2'].surf_in.numbers %}
59
+ {% endif %}
60
+
61
+ bare_layers_1_1() = {<<bare_layers_1_1|join(', ')>>};
62
+ bare_layers_2_1() = {<<bare_layers_2_1|join(', ')>>};
63
+ bare_layers_1_2() = {<<bare_layers_1_2|join(', ')>>};
64
+ bare_layers_2_2() = {<<bare_layers_2_2|join(', ')>>};
65
+
66
+ // ------------ BOUNDARY CONDITIONS --------------------------------------------
67
+ // boundary shells where Dirichlet BC applied, there we need two Tdisc
68
+ // indexing follows the one with the bares BUT we have to think of these lines
69
+ // as neighbors belonging to the non-existing exterior bare part, i.e.,
70
+ // the line touching bare_2_1 will then be bare_1_1
71
+ bndDir_1_1() = {<<rm_TH.boundaries.thermal.temperature.groups['r1_a1']|join(', ')>>};
72
+ bndDir_2_1() = {<<rm_TH.boundaries.thermal.temperature.groups['r2_a1']|join(', ')>>};
73
+ bndDir_1_2() = {<<rm_TH.boundaries.thermal.temperature.groups['r1_a2']|join(', ')>>};
74
+ bndDir_2_2() = {<<rm_TH.boundaries.thermal.temperature.groups['r2_a2']|join(', ')>>};
75
+
76
+ // boundary shells where Neumann BC applied, there we need two Tdisc
77
+ // indexing follows the one with the bares BUT we have to think of these lines
78
+ // as neighbors belonging to the non-existing exterior bare part, i.e.,
79
+ // the line touching bare_2_1 will then be bare_1_1
80
+ bndNeu_1_1() = {<<rm_TH.boundaries.thermal.heat_flux.groups['r1_a1']|join(', ')>>};
81
+ bndNeu_2_1() = {<<rm_TH.boundaries.thermal.heat_flux.groups['r2_a1']|join(', ')>>};
82
+ bndNeu_1_2() = {<<rm_TH.boundaries.thermal.heat_flux.groups['r1_a2']|join(', ')>>};
83
+ bndNeu_2_2() = {<<rm_TH.boundaries.thermal.heat_flux.groups['r2_a2']|join(', ')>>};
84
+
85
+ // boundary shells where Robin BC applied, follows the same indexing scheme as
86
+ // Dirichlet, i.e.,
87
+ // indexing follows the one with the bares BUT we have to think of these lines
88
+ // as neighbors belonging to the non-existing exterior bare part, i.e.,
89
+ // the line touching bare_2_1 will then be bare_1_1
90
+ bndRobin_1_1() = { <<rm_TH.boundaries.thermal.cooling.groups['r1_a1']|join(', ')>>};
91
+ bndRobin_2_1() = { <<rm_TH.boundaries.thermal.cooling.groups['r2_a1']|join(', ')>>};
92
+ bndRobin_1_2() = { <<rm_TH.boundaries.thermal.cooling.groups['r1_a2']|join(', ')>>};
93
+ bndRobin_2_2() = { <<rm_TH.boundaries.thermal.cooling.groups['r2_a2']|join(', ')>>};
94
+
95
+ // for Robin and Neumann, we also need to store some information for GetDP to know the
96
+ // outer virtual shell element
97
+ // first index: same as first index of horVer_layers of Robin (simplified) or midLayers (non-simplified)
98
+ // second index: same as first index of bndRobin or bndNeumann
99
+ // third index: same as second index of bndRobin or bndNeumann
100
+ {% set bndRobinInt_1_1_1 = list(set(rm_TH.boundaries.thermal.cooling.groups['r1_a1']).intersection(bare_layers_2_1)) %}
101
+ {% set bndRobinInt_2_1_1 = list(set(rm_TH.boundaries.thermal.cooling.groups['r1_a1']).intersection(bare_layers_1_2)) %}
102
+
103
+ {% set bndRobinInt_1_2_1 = list(set(rm_TH.boundaries.thermal.cooling.groups['r2_a1']).intersection(bare_layers_1_1)) %}
104
+ {% set bndRobinInt_2_2_1 = list(set(rm_TH.boundaries.thermal.cooling.groups['r2_a1']).intersection(bare_layers_2_2)) %}
105
+
106
+ {% set bndRobinInt_1_1_2 = list(set(rm_TH.boundaries.thermal.cooling.groups['r1_a2']).intersection(bare_layers_2_2)) %}
107
+ {% set bndRobinInt_2_1_2 = list(set(rm_TH.boundaries.thermal.cooling.groups['r1_a2']).intersection(bare_layers_1_1)) %}
108
+
109
+ {% set bndRobinInt_1_2_2 = list(set(rm_TH.boundaries.thermal.cooling.groups['r2_a2']).intersection(bare_layers_1_2)) %}
110
+ {% set bndRobinInt_2_2_2 = list(set(rm_TH.boundaries.thermal.cooling.groups['r2_a2']).intersection(bare_layers_2_1)) %}
111
+
112
+ // Neumann
113
+ {% set bndNeuInt_1_1_1 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r1_a1']).intersection(bare_layers_2_1)) %}
114
+ {% set bndNeuInt_2_1_1 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r1_a1']).intersection(bare_layers_1_2)) %}
115
+
116
+ {% set bndNeuInt_1_2_1 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r2_a1']).intersection(bare_layers_1_1)) %}
117
+ {% set bndNeuInt_2_2_1 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r2_a1']).intersection(bare_layers_2_2)) %}
118
+
119
+ {% set bndNeuInt_1_1_2 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r1_a2']).intersection(bare_layers_2_2)) %}
120
+ {% set bndNeuInt_2_1_2 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r1_a2']).intersection(bare_layers_1_1)) %}
121
+
122
+ {% set bndNeuInt_1_2_2 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r2_a2']).intersection(bare_layers_1_2)) %}
123
+ {% set bndNeuInt_2_2_2 = list(set(rm_TH.boundaries.thermal.heat_flux.groups['r2_a2']).intersection(bare_layers_2_1)) %}
124
+
125
+ // QH
126
+ {% set ns = namespace(all_QH=[]) %}
127
+
128
+ {% for taglist in rm_TH.thin_shells.quench_heaters.thin_shells %}
129
+ {% set ns.all_QH = ns.all_QH + taglist %}
130
+ {% endfor %}
131
+
132
+ {% set QH_1_1 = set(ns.all_QH).intersection(set(bare_layers_2_1).intersection(rm_TH.thin_shells.normals_directed['azimuthally']).union(set(bare_layers_1_2).intersection(rm_TH.thin_shells.normals_directed['radially']))) %}
133
+ {% set QH_2_1 = set(ns.all_QH).intersection(set(bare_layers_1_1).intersection(rm_TH.thin_shells.normals_directed['azimuthally']).union(set(bare_layers_2_2).intersection(rm_TH.thin_shells.normals_directed['radially']))) %}
134
+ {% set QH_1_2 = set(ns.all_QH).intersection(set(bare_layers_2_2).intersection(rm_TH.thin_shells.normals_directed['azimuthally']).union(set(bare_layers_1_1).intersection(rm_TH.thin_shells.normals_directed['radially']))) %}
135
+ {% set QH_2_2 = set(ns.all_QH).intersection(set(bare_layers_1_2).intersection(rm_TH.thin_shells.normals_directed['azimuthally']).union(set(bare_layers_2_1).intersection(rm_TH.thin_shells.normals_directed['radially']))) %}
136
+ QH_1_1() = {<<QH_1_1|join(', ')>>};
137
+ QH_2_1() = {<<QH_2_1|join(', ')>>};
138
+
139
+ QH_1_2() = {<<QH_1_2|join(', ')>>};
140
+ QH_2_2() = {<<QH_2_2|join(', ')>>};
141
+
142
+ // midLayers
143
+ {% if dm.magnet.geometry.thermal.with_wedges %}
144
+ {% set midLayers_1_1 = rm_TH.powered['r1_a1'].surf_out.numbers + rm_TH.induced['r1_a1'].surf_out.numbers %}
145
+ {% set midLayers_2_1 = rm_TH.powered['r2_a1'].surf_out.numbers + rm_TH.induced['r2_a1'].surf_out.numbers %}
146
+ {% set midLayers_1_2 = rm_TH.powered['r1_a2'].surf_out.numbers + rm_TH.induced['r1_a2'].surf_out.numbers %}
147
+ {% set midLayers_2_2 = rm_TH.powered['r2_a2'].surf_out.numbers + rm_TH.induced['r2_a2'].surf_out.numbers %}
148
+ {% else %}
149
+ {% set midLayers_1_1 = rm_TH.powered['r1_a1'].surf_out.numbers %}
150
+ {% set midLayers_2_1 = rm_TH.powered['r2_a1'].surf_out.numbers %}
151
+ {% set midLayers_1_2 = rm_TH.powered['r1_a2'].surf_out.numbers %}
152
+ {% set midLayers_2_2 = rm_TH.powered['r2_a2'].surf_out.numbers %}
153
+ {% endif %}
154
+ midLayers_1_1() = {<<midLayers_1_1|join(', ')>>};
155
+ midLayers_2_1() = {<<midLayers_2_1|join(', ')>>};
156
+ midLayers_1_2() = {<<midLayers_1_2|join(', ')>>};
157
+ midLayers_2_2() = {<<midLayers_2_2|join(', ')>>};
158
+ midLayers() = {<<rm_TH.thin_shells.mid_turns_layers_poles|join(', ')>>};
159
+
160
+ {# midLayers_1: oriented along radial direction, connecting half-turns and poles #}
161
+ {# part of the vertical and horizontal splitting #}
162
+ {# it needs to match the definition of the function spaces for identifying plus and minus side correctly #}
163
+ {% set midLayers_1 = list(set(rm_TH.thin_shells.normals_directed['azimuthally']).intersection(rm_TH.thin_shells.mid_turns_layers_poles)) %}
164
+ {# midLayers_2: oriented along azimuth direction, connecting layer # }
165
+ {# part of the vertical and horizontal splitting #}
166
+ {% set midLayers_2 = list(set(rm_TH.thin_shells.normals_directed['radially']).intersection(rm_TH.thin_shells.mid_turns_layers_poles)) %}
167
+
168
+ // AUX GROUPS ------------------------------------------------------------------
169
+ allLayers = {{% if rm_TH.powered['r1_a1'].surf_in.numbers %}<<rm_TH.powered['r1_a1'].surf_in.numbers|join(', ')>>{% endif %}
170
+ {% if rm_TH.powered['r2_a1'].surf_in.numbers %}, <<rm_TH.powered['r2_a1'].surf_in.numbers|join(', ')>>{% endif %}
171
+ {% if rm_TH.powered['r1_a2'].surf_in.numbers %}, <<rm_TH.powered['r1_a2'].surf_in.numbers|join(', ')>>{% endif %}
172
+ {% if rm_TH.powered['r2_a2'].surf_in.numbers %}, <<rm_TH.powered['r2_a2'].surf_in.numbers|join(', ')>>{% endif %}
173
+ {% if dm.magnet.geometry.thermal.with_wedges %}
174
+ {% if rm_TH.induced['r1_a1'].surf_in.numbers %}, <<rm_TH.induced['r1_a1'].surf_in.numbers|join(', ')>>{% endif %}
175
+ {% if rm_TH.induced['r2_a1'].surf_in.numbers %}, <<rm_TH.induced['r2_a1'].surf_in.numbers|join(', ')>>{% endif %}
176
+ {% if rm_TH.induced['r1_a2'].surf_in.numbers %}, <<rm_TH.induced['r1_a2'].surf_in.numbers|join(', ')>>{% endif %}
177
+ {% if rm_TH.induced['r2_a2'].surf_in.numbers %}, <<rm_TH.induced['r2_a2'].surf_in.numbers|join(', ')>>{% endif %}
178
+ {% endif %}};
179
+ {% endif %}
180
+
181
+ {% endif %}
3
182
 
4
183
  Group {
5
- // Physical regions:
6
- <<rm.air.vol.name>> = Region[ <<rm.air.vol.number>> ]; // Air
7
- <<rm.air_far_field.vol.names[0]>> = Region[ <<rm.air_far_field.vol.numbers[0]>> ]; // AirInf
8
- {% for name, number in zip(rm.powered['Multipole'].vol.names, rm.powered['Multipole'].vol.numbers) %}
9
- <<name>> = Region[ <<number>> ];
10
- {% endfor %}
11
-
12
- {% for name, number in zip(rm.induced['Multipole'].vol.names, rm.induced['Multipole'].vol.numbers) %}
13
- <<name>> = Region[ <<number>> ];
14
- {% endfor %}
15
-
16
- {% for name, number in zip(rm.iron.vol.names, rm.iron.vol.numbers) %}
17
- <<name>> = Region[ <<number>> ];
18
- {% endfor %}
19
-
20
- // Surface_ht0 = Region[ 1100 ];
21
- // Surface_bn0 = Region[ 1101 ];
22
- <<rm.air_far_field.surf.name>> = Region[ <<rm.air_far_field.surf.number>> ];
23
-
24
- <<nc.omega>><<nc.powered>> = Region[ {<<rm.powered['Multipole'].vol.names|join(', ')>>} ];
25
- <<nc.omega>><<nc.iron>> = Region[ {<<rm.iron.vol.names|join(', ')>>} ];
26
- <<nc.omega>><<nc.induced>> = Region[ {<<rm.induced['Multipole'].vol.names|join(', ')>>} ];
27
- <<nc.omega>><<nc.air_far_field>> = Region[ <<rm.air_far_field.vol.names[0]>> ];
28
- <<nc.omega>><<nc.conducting>> = Region[ {<<nc.omega>><<nc.powered>>, <<nc.omega>><<nc.iron>>, <<nc.omega>><<nc.induced>>} ];
29
- <<nc.omega>> = Region[ {<<rm.air.vol.name>>, <<rm.air_far_field.vol.names[0]>>, <<nc.omega>><<nc.powered>>, <<nc.omega>><<nc.iron>>, <<nc.omega>><<nc.induced>>} ];
30
- <<nc.boundary>><<nc.omega>> = Region[ <<rm.air_far_field.surf.name>> ];
31
- //Sur_Neu_Mag = Region[ {} ]; // empty
32
- //Dom_Hcurl_a_Mag_2D = Region[ {<<nc.omega>>, Sur_Neu_Mag} ];
184
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
185
+
186
+ <<rm_EM.air.vol.name>> = Region[ <<rm_EM.air.vol.number>> ]; // Air
187
+ <<rm_EM.air_far_field.vol.names[0]>> = Region[ <<rm_EM.air_far_field.vol.numbers[0]>> ]; // AirInf
188
+ {% for name, number in zip(rm_EM.powered['r1_a1'].vol.names, rm_EM.powered['r1_a1'].vol.numbers) %}
189
+ <<name>> = Region[ <<number>> ];
190
+ {% endfor %}
191
+ {% for name, number in zip(rm_EM.powered['r2_a1'].vol.names, rm_EM.powered['r2_a1'].vol.numbers) %}
192
+ <<name>> = Region[ <<number>> ];
193
+ {% endfor %}
194
+ {% for name, number in zip(rm_EM.powered['r1_a2'].vol.names, rm_EM.powered['r1_a2'].vol.numbers) %}
195
+ <<name>> = Region[ <<number>> ];
196
+ {% endfor %}
197
+ {% for name, number in zip(rm_EM.powered['r2_a2'].vol.names, rm_EM.powered['r2_a2'].vol.numbers) %}
198
+ <<name>> = Region[ <<number>> ];
199
+ {% endfor %}
200
+
201
+ {% if dm.magnet.geometry.electromagnetics.with_wedges %}
202
+ {% for name, number in zip(rm_EM.induced['r1_a1'].vol.names, rm_EM.induced['r1_a1'].vol.numbers) %}
203
+ <<name>> = Region[ <<number>> ];
204
+ {% endfor %}
205
+ {% for name, number in zip(rm_EM.induced['r2_a1'].vol.names, rm_EM.induced['r2_a1'].vol.numbers) %}
206
+ <<name>> = Region[ <<number>> ];
207
+ {% endfor %}
208
+ {% for name, number in zip(rm_EM.induced['r1_a2'].vol.names, rm_EM.induced['r1_a2'].vol.numbers) %}
209
+ <<name>> = Region[ <<number>> ];
210
+ {% endfor %}
211
+ {% for name, number in zip(rm_EM.induced['r2_a2'].vol.names, rm_EM.induced['r2_a2'].vol.numbers) %}
212
+ <<name>> = Region[ <<number>> ];
213
+ {% endfor %}
214
+ {% endif %}
215
+
216
+ {% if dm.magnet.geometry.electromagnetics.with_iron_yoke %}
217
+ {% for name, number in zip(rm_EM.iron.vol.names, rm_EM.iron.vol.numbers) %}
218
+ <<name>> = Region[ <<number>> ];
219
+ {% endfor %}
220
+ {% endif %}
221
+
222
+ <<rm_EM.air_far_field.surf.name>> = Region[ <<rm_EM.air_far_field.surf.number>> ];
223
+ {% if rm_EM.boundaries.symmetry.normal_free.number %}
224
+ <<rm_EM.boundaries.symmetry.normal_free.name>> = Region[ <<rm_EM.boundaries.symmetry.normal_free.number>> ];
225
+ {% endif %}
226
+
227
+ <<nc.omega>><<nc.powered>>_EM = Region[ {
228
+ {% if rm_EM.powered['r1_a1'].vol.names %}<<rm_EM.powered['r1_a1'].vol.names|join(', ')>>{% endif %}
229
+ {% if rm_EM.powered['r1_a2'].vol.names %}, <<rm_EM.powered['r1_a2'].vol.names|join(', ')>>{% endif %}
230
+ {% if rm_EM.powered['r2_a1'].vol.names %}, <<rm_EM.powered['r2_a1'].vol.names|join(', ')>>{% endif %}
231
+ {% if rm_EM.powered['r2_a2'].vol.names %}, <<rm_EM.powered['r2_a2'].vol.names|join(', ')>>{% endif %}} ];
232
+
233
+ {% if dm.magnet.geometry.electromagnetics.with_iron_yoke %}
234
+ <<nc.omega>><<nc.iron>>_EM = Region[ {<<rm_EM.iron.vol.names|join(', ')>>} ];
235
+ {% endif %}
236
+
237
+ {% if dm.magnet.geometry.electromagnetics.with_wedges %}
238
+ <<nc.omega>><<nc.induced>>_EM = Region[ {
239
+ {% if rm_EM.induced['r1_a1'].vol.names %}<<rm_EM.induced['r1_a1'].vol.names|join(', ')>>{% endif %}
240
+ {% if rm_EM.induced['r1_a2'].vol.names %}, <<rm_EM.induced['r1_a2'].vol.names|join(', ')>>{% endif %}
241
+ {% if rm_EM.induced['r2_a1'].vol.names %}, <<rm_EM.induced['r2_a1'].vol.names|join(', ')>>{% endif %}
242
+ {% if rm_EM.induced['r2_a2'].vol.names %}, <<rm_EM.induced['r2_a2'].vol.names|join(', ')>>{% endif %}} ];
243
+ {% endif %}
244
+
245
+ <<nc.omega>><<nc.air_far_field>>_EM = Region[ <<rm_EM.air_far_field.vol.names[0]>> ];
246
+ <<nc.omega>><<nc.air>>_EM = Region[ <<rm_EM.air.vol.name>> ];
247
+ <<nc.omega>><<nc.conducting>>_EM = Region[ {<<nc.omega>><<nc.powered>>_EM{% if dm.magnet.geometry.electromagnetics.with_iron_yoke %}, <<nc.omega>><<nc.iron>>_EM{% endif %}
248
+ {% if dm.magnet.geometry.electromagnetics.with_wedges %}, <<nc.omega>><<nc.induced>>_EM{% endif %}} ];
249
+ <<nc.omega>>_EM = Region[ {<<rm_EM.air.vol.name>>, <<rm_EM.air_far_field.vol.names[0]>>, <<nc.omega>><<nc.powered>>_EM{% if dm.magnet.geometry.electromagnetics.with_iron_yoke %}, <<nc.omega>><<nc.iron>>_EM{% endif %}
250
+ {% if dm.magnet.geometry.electromagnetics.with_wedges %}, <<nc.omega>><<nc.induced>>_EM{% endif %}} ];
251
+ <<nc.boundary>><<nc.omega>> = Region[ {<<rm_EM.air_far_field.surf.name>>{% if rm_EM.boundaries.symmetry.normal_free.number %}, <<rm_EM.boundaries.symmetry.normal_free.name>>{% endif %}}];
252
+
253
+ {% endif %}
254
+
255
+ {% if dm.magnet.solve.thermal.solve_type %}
256
+
257
+ {% if dm.magnet.geometry.thermal.use_TSA %}
258
+ // --------------------- BARE ------------------------------------------------
259
+
260
+ // physical regions of the bare blocks
261
+ For i In {1:2}
262
+ For j In {1:2}
263
+ Bare~{i}~{j} = Region[ bare~{i}~{j} ];
264
+ <<nc.omega>>_TH += Region[ bare~{i}~{j} ];
265
+ EndFor
266
+ EndFor
267
+
268
+ // ------------------- SHELLS ------------------------------------------------
269
+ For i In {1:2}
270
+ For j In {1:2}
271
+ // integration domains
272
+ Bare_Layers~{i}~{j} = Region[ bare_layers~{i}~{j} ];
273
+ Bare_Layers~{i}~{j} += Region[ bndDir~{i}~{j} ];
274
+ Bare_Layers~{i}~{j} += Region[ bndNeu~{i}~{j} ];
275
+ Bare_Layers~{i}~{j} += Region[ bndRobin~{i}~{j} ];
276
+
277
+ Bare_Layers~{i}~{j} += Region[ QH~{i}~{j} ];
278
+
279
+ Domain_Insulated_Str~{i}~{j} = Region[ { Bare~{i}~{j},
280
+ Bare_Layers~{i}~{j} } ];
281
+
282
+ midLayers~{i}~{j} = Region[midLayers~{i}~{j}];
283
+
284
+ EndFor
285
+ EndFor
286
+
287
+ midLayers = Region[midLayers];
288
+
289
+ {% endif %}
290
+
291
+ {% for name, number in zip(rm_TH.powered['r1_a1'].vol.names, rm_TH.powered['r1_a1'].vol.numbers) %}
292
+ <<name>> = Region[ <<number>> ];
293
+ {% endfor %}
294
+ {% for name, number in zip(rm_TH.powered['r2_a1'].vol.names, rm_TH.powered['r2_a1'].vol.numbers) %}
295
+ <<name>> = Region[ <<number>> ];
296
+ {% endfor %}
297
+ {% for name, number in zip(rm_TH.powered['r1_a2'].vol.names, rm_TH.powered['r1_a2'].vol.numbers) %}
298
+ <<name>> = Region[ <<number>> ];
299
+ {% endfor %}
300
+ {% for name, number in zip(rm_TH.powered['r2_a2'].vol.names, rm_TH.powered['r2_a2'].vol.numbers) %}
301
+ <<name>> = Region[ <<number>> ];
302
+ {% endfor %}
303
+
304
+ {% if dm.magnet.geometry.thermal.with_wedges %}
305
+ {% for name, number in zip(rm_TH.induced['r1_a1'].vol.names, rm_TH.induced['r1_a1'].vol.numbers) %}
306
+ <<name>> = Region[ <<number>> ];
307
+ {% endfor %}
308
+ {% for name, number in zip(rm_TH.induced['r2_a1'].vol.names, rm_TH.induced['r2_a1'].vol.numbers) %}
309
+ <<name>> = Region[ <<number>> ];
310
+ {% endfor %}
311
+ {% for name, number in zip(rm_TH.induced['r1_a2'].vol.names, rm_TH.induced['r1_a2'].vol.numbers) %}
312
+ <<name>> = Region[ <<number>> ];
313
+ {% endfor %}
314
+ {% for name, number in zip(rm_TH.induced['r2_a2'].vol.names, rm_TH.induced['r2_a2'].vol.numbers) %}
315
+ <<name>> = Region[ <<number>> ];
316
+ {% endfor %}
317
+ {% endif %}
318
+
319
+ {% if dm.magnet.geometry.thermal.with_iron_yoke %}
320
+ {% for name, number in zip(rm_TH.iron.vol.names, rm_TH.iron.vol.numbers) %}
321
+ <<name>> = Region[ <<number>> ];
322
+ {% endfor %}
323
+ {% endif %}
324
+
325
+ {% if not dm.magnet.geometry.thermal.use_TSA %}
326
+ {% for name, number in zip(rm_TH.insulator.vol.names, rm_TH.insulator.vol.numbers) %}
327
+ <<name>> = Region[ <<number>> ];
328
+ {% endfor %}
329
+ {% for name, number in zip(rm_TH.insulator.surf.names, rm_TH.insulator.surf.numbers) %}
330
+ <<name>> = Region[ <<number>> ];
331
+ {% endfor %}
332
+ {% endif %}
333
+
334
+ {% for cond_name in dm.conductors.keys() %}
335
+ <<nc.omega>><<nc.powered>>_<<cond_name>>_TH = Region[ {
336
+ {% if rm_TH.powered['r1_a1'].conductors[cond_name] %}<<rm_TH.powered['r1_a1'].conductors[cond_name]|join(', ')>>{% endif %}
337
+ {% if rm_TH.powered['r1_a2'].conductors[cond_name] %}, <<rm_TH.powered['r1_a2'].conductors[cond_name]|join(', ')>>{% endif %}
338
+ {% if rm_TH.powered['r2_a1'].conductors[cond_name] %}, <<rm_TH.powered['r2_a1'].conductors[cond_name]|join(', ')>>{% endif %}
339
+ {% if rm_TH.powered['r2_a2'].conductors[cond_name] %}, <<rm_TH.powered['r2_a2'].conductors[cond_name]|join(', ')>>{% endif %}} ];
340
+ {% endfor %}
341
+ <<nc.omega>><<nc.powered>>_TH = Region[ {<<nc.omega>><<nc.powered>>_<<dm.conductors.keys()|join('_TH, ' + nc.omega + nc.powered + '_')>>_TH} ];
342
+ {% if dm.magnet.geometry.thermal.with_iron_yoke %}
343
+ <<nc.omega>><<nc.iron>>_TH = Region[ {<<rm_TH.iron.vol.names|join(', ')>>} ];
344
+ {% endif %}
345
+ {% if dm.magnet.geometry.thermal.with_wedges %}
346
+ <<nc.omega>><<nc.induced>>_TH = Region[ {
347
+ {% if rm_TH.induced['r1_a1'].vol.names %}<<rm_TH.induced['r1_a1'].vol.names|join(', ')>>{% endif %}
348
+ {% if rm_TH.induced['r1_a2'].vol.names %}, <<rm_TH.induced['r1_a2'].vol.names|join(', ')>>{% endif %}
349
+ {% if rm_TH.induced['r2_a1'].vol.names %}, <<rm_TH.induced['r2_a1'].vol.names|join(', ')>>{% endif %}
350
+ {% if rm_TH.induced['r2_a2'].vol.names %}, <<rm_TH.induced['r2_a2'].vol.names|join(', ')>>{% endif %}} ];
351
+ {% endif %}
352
+ <<nc.omega>><<nc.conducting>>_TH = Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>_TH{% endif %}
353
+ {% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %}} ];
354
+ {% if not dm.magnet.geometry.thermal.use_TSA %}
355
+ <<nc.omega>><<nc.insulator>>_TH = Region[ {<<rm_TH.insulator.vol.names|join(', ')>>} ];
356
+ {% endif %}
357
+ <<nc.omega>>_TH = Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>_TH{% endif %}
358
+ {% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %}{% if not dm.magnet.geometry.thermal.use_TSA %}, <<nc.omega>><<nc.insulator>>_TH{% endif %}} ];
359
+
360
+ {# the jinja 'do' extension allows to perform actions without variable assignments, practically enabling jinja dicts since '{% dict[new_key] = new_value %}' is not allowed #}
361
+ {% set jcZero_ht = {} %}
362
+ {% for cond_name in dm.conductors.keys() %}
363
+ {% do jcZero_ht.update({cond_name: []}) %}
364
+ {% endfor %}
365
+ {% for turn in dm.magnet.solve.thermal.jc_degradation_to_zero.turns %}
366
+ jcZero_ht<<turn>> = Region[{ht<<turn>>_TH}];
367
+ {% for cond_name in dm.conductors.keys() %}
368
+ {% if 'ht' + str(turn) + '_TH' in rm_TH.powered['r1_a1'].conductors[cond_name] + rm_TH.powered['r1_a2'].conductors[cond_name] + rm_TH.powered['r2_a1'].conductors[cond_name] + rm_TH.powered['r2_a2'].conductors[cond_name] %}
369
+ {% do jcZero_ht.update({cond_name: jcZero_ht[cond_name] + ['ht' + str(turn) + '_TH']}) %}
370
+ {% endif %}
371
+ {% endfor %}
372
+ {% endfor %}
373
+ {% for cond_name in dm.conductors.keys() %}
374
+ jcZero_<<cond_name>> = Region[{<<jcZero_ht[cond_name]|join(', ')>>}];
375
+ jcNonZero_<<cond_name>> = Region[<<nc.omega>><<nc.powered>>_<<cond_name>>_TH];
376
+ jcNonZero_<<cond_name>> -= Region[jcZero_<<cond_name>>];
377
+ {% endfor %}
378
+
379
+ {% if dm.magnet.geometry.thermal.use_TSA %}
380
+ // {% set more_elems = [3348, 3349] %}
381
+ // {% set bare_layers = bare_layers_1_1 + bare_layers_1_2 + bare_layers_2_1 + bare_layers_2_2 %}
382
+ // {% set not_more_elems = list(set(rm_TH.thin_shells.mid_turns_layers_poles + bare_layers) - set(more_elems)) %}
383
+
384
+ //{% set tags_with_same_tsa_structure = [more_elems, not_more_elems] %}
385
+ //{% set thicknesses_tsa_layers = [[2 * 8.4E-5/4, 2 * 8.4E-5 / 4, 2 * 8.4E-5 / 4, 2 * 8.4E-5 /4], [2 * 8.4E-5/2, 2 * 8.4E-5/2]] %}
386
+ {% set materials_tsa_layers = [[], []] %}
387
+
388
+ //{% set n_tsa_layers = [4, 2] %} // sum of all
389
+
390
+ {% set bndDir_1 = list(set(rm_TH.boundaries.thermal.temperature.groups['r1_a1']).intersection(bare_layers_2_1)) +
391
+ list(set(rm_TH.boundaries.thermal.temperature.groups['r2_a1']).intersection(bare_layers_1_1)) +
392
+ list(set(rm_TH.boundaries.thermal.temperature.groups['r1_a2']).intersection(bare_layers_2_2)) +
393
+ list(set(rm_TH.boundaries.thermal.temperature.groups['r2_a2']).intersection(bare_layers_1_2)) %}
394
+
395
+ {% set bndDir_2 = list(set(rm_TH.boundaries.thermal.temperature.groups['r1_a1']).intersection(bare_layers_1_2)) +
396
+ list(set(rm_TH.boundaries.thermal.temperature.groups['r2_a1']).intersection(bare_layers_2_2)) +
397
+ list(set(rm_TH.boundaries.thermal.temperature.groups['r1_a2']).intersection(bare_layers_1_1)) +
398
+ list(set(rm_TH.boundaries.thermal.temperature.groups['r2_a2']).intersection(bare_layers_2_1)) %}
399
+
400
+ {% for nr, tags in enumerate(rm_TH.thin_shells.insulation_types.thin_shells + rm_TH.thin_shells.quench_heaters.thin_shells) %}
401
+ intDomain_1_<<nr + 1>> = Region[{<<set(midLayers_1).intersection(tags)|join(', ')>>}];
402
+ intDomain_2_<<nr + 1>> = Region[{<<set(midLayers_2).intersection(tags)|join(', ')>>}];
403
+
404
+ // add Robin boundary conditions
405
+ intDomain_1_<<nr + 1>> += Region[{<<set(bndRobinInt_1_1_1 + bndRobinInt_1_1_2 + bndRobinInt_1_2_1 + bndRobinInt_1_2_2).intersection(tags)|join(', ')>>}];
406
+ intDomain_2_<<nr + 1>> += Region[{<<set(bndRobinInt_2_1_1 + bndRobinInt_2_1_2 + bndRobinInt_2_2_1 + bndRobinInt_2_2_2).intersection(tags)|join(', ')>>}];
407
+
408
+ // add Dirichlet boundary conditions
409
+ intDomain_1_<<nr + 1>> += Region[{<<set(bndDir_1).intersection(tags)|join(', ')>>}];
410
+ intDomain_2_<<nr + 1>> += Region[{<<set(bndDir_2).intersection(tags)|join(', ')>>}];
411
+
412
+ // add Neumann boundary conditions
413
+ intDomain_1_<<nr + 1>> += Region[{<<set(bndNeuInt_1_1_1 + bndNeuInt_1_1_2 + bndNeuInt_1_2_1 + bndNeuInt_1_2_2).intersection(tags)|join(', ')>>}];
414
+ intDomain_2_<<nr + 1>> += Region[{<<set(bndNeuInt_2_1_1 + bndNeuInt_2_1_2 + bndNeuInt_2_2_1 + bndNeuInt_2_2_2).intersection(tags)|join(', ')>>}];
415
+
416
+ // Robin domains
417
+ bndRobinInt_1_1_1_<<nr + 1>> = Region[{<<set(bndRobinInt_1_1_1).intersection(tags)|join(', ')>>}];
418
+ bndRobinInt_1_1_2_<<nr + 1>> = Region[{<<set(bndRobinInt_1_1_2).intersection(tags)|join(', ')>>}];
419
+ bndRobinInt_1_2_1_<<nr + 1>> = Region[{<<set(bndRobinInt_1_2_1).intersection(tags)|join(', ')>>}];
420
+ bndRobinInt_1_2_2_<<nr + 1>> = Region[{<<set(bndRobinInt_1_2_2).intersection(tags)|join(', ')>>}];
421
+ bndRobinInt_2_1_1_<<nr + 1>> = Region[{<<set(bndRobinInt_2_1_1).intersection(tags)|join(', ')>>}];
422
+ bndRobinInt_2_1_2_<<nr + 1>> = Region[{<<set(bndRobinInt_2_1_2).intersection(tags)|join(', ')>>}];
423
+ bndRobinInt_2_2_1_<<nr + 1>> = Region[{<<set(bndRobinInt_2_2_1).intersection(tags)|join(', ')>>}];
424
+ bndRobinInt_2_2_2_<<nr + 1>> = Region[{<<set(bndRobinInt_2_2_2).intersection(tags)|join(', ')>>}];
425
+
426
+ // Neumann domains
427
+ bndNeuInt_1_1_1_<<nr + 1>> = Region[{<<set(bndNeuInt_1_1_1).intersection(tags)|join(', ')>>}];
428
+ bndNeuInt_1_1_2_<<nr + 1>> = Region[{<<set(bndNeuInt_1_1_2).intersection(tags)|join(', ')>>}];
429
+ bndNeuInt_1_2_1_<<nr + 1>> = Region[{<<set(bndNeuInt_1_2_1).intersection(tags)|join(', ')>>}];
430
+ bndNeuInt_1_2_2_<<nr + 1>> = Region[{<<set(bndNeuInt_1_2_2).intersection(tags)|join(', ')>>}];
431
+ bndNeuInt_2_1_1_<<nr + 1>> = Region[{<<set(bndNeuInt_2_1_1).intersection(tags)|join(', ')>>}];
432
+ bndNeuInt_2_1_2_<<nr + 1>> = Region[{<<set(bndNeuInt_2_1_2).intersection(tags)|join(', ')>>}];
433
+ bndNeuInt_2_2_1_<<nr + 1>> = Region[{<<set(bndNeuInt_2_2_1).intersection(tags)|join(', ')>>}];
434
+ bndNeuInt_2_2_2_<<nr + 1>> = Region[{<<set(bndNeuInt_2_2_2).intersection(tags)|join(', ')>>}];
435
+ {% endfor %}
436
+
437
+ {% else %} {# not TSA #}
438
+
439
+ {% for nr, names in enumerate(rm_TH.boundaries.thermal.temperature.bc.names) %}
440
+ <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.temperature)[nr]>> = Region[ {<<names|join(', ')>>} ];
441
+ {% endfor %}
442
+
443
+ {% for nr, names in enumerate(rm_TH.boundaries.thermal.heat_flux.bc.names) %}
444
+ {% if dm.magnet.solve.thermal.He_cooling.sides != 'external' and nr == 0 %}
445
+ general_adiabatic = Region[ {<<names|join(', ')>>} ];
446
+ {% else %}
447
+ <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.heat_flux)[nr - 1 if dm.magnet.solve.thermal.He_cooling.sides != 'external' else nr]>> = Region[ {<<names|join(', ')>>} ];
448
+ {% endif %}
449
+ {% endfor %}
450
+
451
+ {% for nr, names in enumerate(rm_TH.boundaries.thermal.cooling.bc.names) %}
452
+ {% if dm.magnet.solve.thermal.He_cooling.enabled and nr == 0 %}
453
+ general_cooling = Region[ {<<names|join(', ')>>} ];
454
+ {% else %}
455
+ <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling)[nr - 1 if dm.magnet.solve.thermal.He_cooling.enabled else nr]>> = Region[ {<<names|join(', ')>>} ];
456
+ {% endif %}
457
+ {% endfor %}
458
+
459
+ Bnds_dirichlet = Region[ {<<dm.magnet.solve.thermal.overwrite_boundary_conditions.temperature|join(', ')>>} ];
460
+ Bnds_neumann = Region[ {} ];
461
+ {% if dm.magnet.solve.thermal.He_cooling.sides != 'external' %}
462
+ Bnds_neumann += Region[ general_adiabatic ];
463
+ {% endif %}
464
+ {% if dm.magnet.solve.thermal.overwrite_boundary_conditions.heat_flux %}
465
+ Bnds_neumann += Region[ {<<dm.magnet.solve.thermal.overwrite_boundary_conditions.heat_flux|join(', ')>>} ];
466
+ {% endif %}
467
+
468
+ Bnds_robin = Region[ {} ];
469
+ {% if dm.magnet.solve.thermal.He_cooling.enabled %}
470
+ Bnds_robin += Region[ general_cooling ];
471
+ {% endif %}
472
+ {% if dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling %}
473
+ Bnds_robin += Region[ {<<dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling|join(', ')>>} ];
474
+ {% endif %}
475
+
476
+ Bnds_support = Region[ {Bnds_neumann, Bnds_robin} ];
477
+
478
+ {% endif %}
479
+
480
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
481
+ <<rm_TH.projection_points.name>> = Region[ <<rm_TH.projection_points.number>> ];
482
+ {% endif %}
483
+
484
+ {% endif %}
33
485
  }
34
486
 
35
487
  Function {
36
- mu0 = 4.e-7 * Pi;
37
-
38
- /* New ONELAB variables can then be defined using DefineNumber, e.g.: */
39
- //murCore = DefineNumber[100, Name "Model parameters/Mur core",
40
- //Help "Magnetic relative permeability of Core"];
41
-
42
- nu [ Region[{<<rm.air.vol.name>>, <<nc.omega>><<nc.powered>>, <<rm.air_far_field.vol.names[0]>>, <<nc.omega>><<nc.induced>>}] ] = 1. / mu0;
43
-
44
- {% for name in rm.iron.vol.names %}
45
- nu [ <<name>> ] = nu<<name>>[$1];
46
- dnuIronYoke [ <<name>> ] = dnu<<name>>[$1];
47
- {% endfor %}
48
- /*nu [ BHiron2 ] = nuBHiron2[$1]; //1. / (murCore * mu0);
49
- dnuIronYoke [ BHiron2 ] = dnuBHiron2[$1];*/
50
-
51
- //Current = DefineNumber[7180, Name "Model parameters/Current",
52
- // Help "Current injected in coil [A]"];
53
-
54
- // NbTurns = 1 ; // number of turns in the coil
55
- {% for name, current in zip(rm.powered['Multipole'].vol.names, rm.powered['Multipole'].vol.currents) %}
56
- js_fct[ <<name>> ] = <<current>>/SurfaceArea[];
57
- {% endfor %}
58
- //js_fct[ PowPos ] = Current/SurfaceArea[];
59
- //js_fct[ PowNeg ] = -Current/SurfaceArea[];
60
- /* The minus sign is to have the current in -e_z direction,
61
- so that the magnetic induction field is in +e_y direction */
488
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
489
+
490
+ mu0 = 4.e-7 * Pi;
491
+ nu [ Region[{<<rm_EM.air.vol.name>>, <<nc.omega>><<nc.powered>>_EM, <<rm_EM.air_far_field.vol.names[0]>>{% if dm.magnet.geometry.electromagnetics.with_wedges %}, <<nc.omega>><<nc.induced>>_EM{% endif %}}] ] = 1. / mu0;
492
+
493
+ {% if dm.magnet.geometry.electromagnetics.with_iron_yoke %}
494
+ {% for name in rm_EM.iron.vol.names %}
495
+ nu [ <<name>> ] = nu<<name>>[$1];
496
+ dnuIronYoke [ <<name>> ] = dnu<<name>>[$1];
497
+ {% endfor %}
498
+ {% endif %}
499
+
500
+ {% for name, current in zip(rm_EM.powered['r1_a1'].vol.names + rm_EM.powered['r1_a2'].vol.names + rm_EM.powered['r2_a1'].vol.names + rm_EM.powered['r2_a2'].vol.names,
501
+ rm_EM.powered['r1_a1'].vol.currents + rm_EM.powered['r1_a2'].vol.currents + rm_EM.powered['r2_a1'].vol.currents + rm_EM.powered['r2_a2'].vol.currents) %}
502
+ js_fct[ <<name>> ] = <<current>>/SurfaceArea[];
503
+ {% endfor %}
504
+
505
+ {% endif %}
506
+
507
+ {% if dm.magnet.solve.thermal.solve_type %}
508
+
509
+ {% if dm.magnet.geometry.thermal.use_TSA %}
510
+ {% for nr, tags in enumerate(rm_TH.boundaries.thermal.temperature.bc.numbers) %}
511
+ bnd_dirichlet_<<nr + 1>>() = {<<tags|join(', ')>>};
512
+ val_temperature_<<nr + 1>> = <<rm_TH.boundaries.thermal.temperature.bc.value[nr]>>;
513
+ {% endfor %}
514
+ num_dirichlet = <<len(rm_TH.boundaries.thermal.temperature.bc.numbers)>>; // number of different dirichlet boundary cond.
515
+
516
+ {% for nr, tags in enumerate(rm_TH.boundaries.thermal.heat_flux.bc.numbers) %}
517
+ bnd_neumann_<<nr + 1>>() = {<<tags|join(', ')>>};
518
+ val_heatFlux_<<nr + 1>> = <<rm_TH.boundaries.thermal.heat_flux.bc.value[nr]>>;
519
+ {% endfor %}
520
+ num_neumann = <<len(rm_TH.boundaries.thermal.heat_flux.bc.numbers)>>; // number of different neumann boundary cond.
521
+
522
+ {% for nr, tags in enumerate(rm_TH.boundaries.thermal.cooling.bc.numbers) %}
523
+ bnd_robin_<<nr + 1>>() = {<<tags|join(', ')>>};
524
+ {% if isinstance(rm_TH.boundaries.thermal.cooling.bc.values[nr][0], str) %}
525
+ val_heatExchCoeff_<<nr + 1>>[] = <<rm_TH.boundaries.thermal.cooling.bc.values[nr][0]>>[$1, $2];
526
+ {% else %}
527
+ val_heatExchCoeff_<<nr + 1>>[] = <<rm_TH.boundaries.thermal.cooling.bc.values[nr][0]>>;
528
+ {% endif %}
529
+ val_Tinf_<<nr + 1>> = <<rm_TH.boundaries.thermal.cooling.bc.values[nr][1]>>;
530
+ {% endfor %}
531
+ num_robin = <<len(rm_TH.boundaries.thermal.cooling.bc.numbers)>>; // number of different robin boundary cond.
532
+ {% endif %}
533
+
534
+ // time steps adaptive time stepping must hit
535
+ Breakpoints = {<<dm.magnet.solve.thermal.time_stepping.breakpoints|join(', ')>>};
536
+
537
+ {% if dm.magnet.geometry.thermal.use_TSA %}
538
+ // first idx: 1 layers parallel to radial direction (== normal to phi unit vector)
539
+ // 2 layers parallel to azimuthal direction (== normal to r unit vector)
540
+ // second and third idx: same as bare layers
541
+ // this gives the relation between radius/angle and index 0 to n_ele
542
+ {% for nr, n_ele in enumerate(rm_TH.thin_shells.insulation_types.layers_number + rm_TH.thin_shells.quench_heaters.layers_number) %}
543
+ outerElem_1_1_1_<<nr + 1>> = 0;
544
+ outerElem_2_1_1_<<nr + 1>> = 0;
545
+
546
+ outerElem_1_2_1_<<nr + 1>> = <<n_ele>>;
547
+ outerElem_2_2_1_<<nr + 1>> = 0;
548
+
549
+ outerElem_1_1_2_<<nr + 1>> = 0;
550
+ outerElem_2_1_2_<<nr + 1>> = <<n_ele>>;
551
+
552
+ outerElem_1_2_2_<<nr + 1>> = <<n_ele>>;
553
+ outerElem_2_2_2_<<nr + 1>> = <<n_ele>>;
554
+ {% endfor %}
555
+
556
+ {% set no_flip_tags = rm_TH.thin_shells.second_group_is_next['azimuthally'] + rm_TH.thin_shells.second_group_is_next['radially'] %}
557
+ {% set all_dir = bndDir_1 + bndDir_2 %}
558
+ {% set all_neu = bndNeuInt_1_1_1 + bndNeuInt_1_1_2 + bndNeuInt_1_2_1 + bndNeuInt_1_2_2 + bndNeuInt_2_1_1 + bndNeuInt_2_1_2 + bndNeuInt_2_2_1 + bndNeuInt_2_2_2 %}
559
+ {% set all_robin = bndRobinInt_1_1_1 + bndRobinInt_1_1_2 + bndRobinInt_1_2_1 + bndRobinInt_1_2_2 + bndRobinInt_2_1_1 + bndRobinInt_2_1_2 + bndRobinInt_2_2_1 + bndRobinInt_2_2_2 %}
560
+
561
+ {% set flip_tags = list(set(rm_TH.thin_shells.mid_turns_layers_poles + all_neu + all_dir + all_robin + ns.all_QH) - set(no_flip_tags)) %}
562
+ {% endif %}
563
+
564
+ // --------------- MATERIAL FUNCTIONS ----------------------------------------
565
+ {% set criticalCurrentDensityMacroName = {'Nb-Ti_CUDI1': 'MATERIAL_CriticalCurrentDensity_NiobiumTitanium_CUDI1_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
566
+ 'Nb3Sn_Summers': 'MATERIAL_CriticalCurrentDensity_Niobium3Tin_Summers_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
567
+ 'Nb3Sn_Bordini': 'MATERIAL_CriticalCurrentDensity_Niobium3Tin_Bordini_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
568
+ 'BSCCO2212': 'MATERIAL_CriticalCurrentDensity_BSCCO2212_BSCCO_2212_LBNL_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else '')} %}
569
+ {% set resistivityMacroName = {'Cu': 'MATERIAL_Resistivity_Copper_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
570
+ 'Ag': 'MATERIAL_Resistivity_Silver_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
571
+ 'SS': 'MATERIAL_Resistivity_SSteel_T'} %}
572
+ {% set thermalConductivityMacroName = {'Cu': 'MATERIAL_ThermalConductivity_Copper_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
573
+ 'Ag': 'MATERIAL_ThermalConductivity_Silver_T', 'SS': 'MATERIAL_ThermalConductivity_SSteel_T',
574
+ 'kapton': 'MATERIAL_ThermalConductivity_Kapton_T', 'G10': 'MATERIAL_ThermalConductivity_G10_T'} %}
575
+ {% set specificHeatCapacityMacroName = {'Cu': 'MATERIAL_SpecificHeatCapacity_Copper_T', 'Ag': 'MATERIAL_SpecificHeatCapacity_Silver_T', 'SS': 'MATERIAL_SpecificHeatCapacity_SSteel_T',
576
+ 'Nb-Ti': 'MATERIAL_SpecificHeatCapacity_NiobiumTitanium_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
577
+ 'Nb3Sn': 'MATERIAL_SpecificHeatCapacity_Niobium3Tin_T' + ('_B' if dm.magnet.solve.electromagnetics.solve_type else ''),
578
+ 'BSCCO2212': 'MATERIAL_SpecificHeatCapacity_BSCCO2212_T',
579
+ 'kapton': 'MATERIAL_SpecificHeatCapacity_Kapton_T', 'G10': 'MATERIAL_SpecificHeatCapacity_G10_T',
580
+ 'helium': 'MATERIAL_SpecificHeatCapacity_Helium_T'} %}
581
+
582
+ {% set thermalConductivityTSAStiffnessMacroName = {'Cu': 'MATERIAL_ThermalConductivity_Copper_TSAStiffness_T', 'SS': 'MATERIAL_ThermalConductivity_SSteel_TSAStiffness_T',
583
+ 'kapton': 'MATERIAL_ThermalConductivity_Kapton_TSAStiffness_T', 'G10': 'MATERIAL_ThermalConductivity_G10_TSAStiffness_T'} %}
584
+
585
+ {% set thermalConductivityTSAMassMacroName = {'Cu': 'MATERIAL_ThermalConductivity_Copper_TSAMass_T', 'SS': 'MATERIAL_ThermalConductivity_SSteel_TSAMass_T',
586
+ 'kapton': 'MATERIAL_ThermalConductivity_Kapton_TSAMass_T', 'G10': 'MATERIAL_ThermalConductivity_G10_TSAMass_T'} %}
587
+
588
+ {% set specificHeatCapacityTSAMacroName = {'Cu': 'MATERIAL_SpecificHeatCapacity_Copper_TSAMass_T', 'SS': 'MATERIAL_SpecificHeatCapacity_SSteel_TSAMass_T',
589
+ 'kapton': 'MATERIAL_SpecificHeatCapacity_Kapton_TSAMass_T', 'G10': 'MATERIAL_SpecificHeatCapacity_G10_TSAMass_T'} %}
590
+
591
+ {% for name, cond in dm.conductors.items() %}
592
+ {% if cond.cable.f_inner_voids and cond.cable.f_outer_voids %}
593
+ f_inner_voids_<<name>> = <<cond.cable.f_inner_voids>>;
594
+ f_outer_voids_<<name>> = <<cond.cable.f_outer_voids>>;
595
+ f_strand_<<name>> = 1.0 - (<<cond.cable.f_inner_voids>> + <<cond.cable.f_outer_voids>>);
596
+ {% else %}
597
+ {% if cond.strand.type == 'Round' %}
598
+ {% set n_strands = cond.cable.n_strands %}
599
+ {% set A_Strand = cond.cable.n_strands * Pi/4.0 * cond.strand.diameter**2 %}
600
+ {% elif cond.strand.type == 'Rectangular' %}
601
+ {% set n_strands = cond.cable.n_strands if cond.cable.type == 'Rutherford' else 1 %}
602
+ {% set A_Strand = n_strands * cond.strand.bare_width * cond.strand.bare_height %}
603
+ {% endif %}
604
+ {% set A_cable = cond.cable.bare_cable_width * cond.cable.bare_cable_height_mean %}
605
+
606
+ {% set f_both_voids = 1.0 - A_Strand / A_cable %}
607
+ {% set f_inner_voids = f_both_voids * (0.5 - 1.0/n_strands) %}
608
+ {% set f_outer_voids = f_both_voids * (0.5 + 1.0/n_strands) %}
609
+
610
+ f_inner_voids_<<name>> = <<f_inner_voids>>;
611
+ f_outer_voids_<<name>> = <<f_outer_voids>>;
612
+ f_strand_<<name>> = 1.0 - <<f_both_voids>>;
613
+ {% endif %}
614
+
615
+ f_stabilizer_<<name>> = f_strand_<<name>> * <<cond.strand.Cu_noCu_in_strand>> / (1. + <<cond.strand.Cu_noCu_in_strand>>);
616
+ f_sc_<<name>> = f_strand_<<name>> * (1.0 - <<cond.strand.Cu_noCu_in_strand>> / (1. + <<cond.strand.Cu_noCu_in_strand>>));
617
+ {% endfor %}
618
+
619
+ source_current = <<dm.power_supply.I_initial>>;
620
+
621
+ {# the namespace object with attribute 'conductor' is necessary to store a Pydantic class object like 'cond' #}
622
+ {% set current_cond = namespace(conductor={}) %}
623
+ {% for name, cond in dm.conductors.items() %}
624
+ <<criticalCurrentDensity("jcNonZero_" + name, cond, time_trigger=1e6, cond_name=name)>>
625
+ {% endfor %}
626
+ {% for turn, t_trigger in zip(dm.magnet.solve.thermal.jc_degradation_to_zero.turns, dm.magnet.solve.thermal.jc_degradation_to_zero.t_trigger) %}
627
+ {% for name, cond in dm.conductors.items() %}
628
+ {% if 'ht' + str(turn) + '_TH' in jcZero_ht[name] %}
629
+ {% set current_cond.conductor = cond %}
630
+ {% set current_cond.name = name %}
631
+
632
+ {% endif %}
633
+ {% endfor %}
634
+ <<criticalCurrentDensity("jcZero_ht" + str(turn), cond=current_cond.conductor, time_trigger=t_trigger, cond_name=current_cond.name)>>
635
+ {% endfor %}
636
+
637
+ {% for name, cond in dm.conductors.items() %}
638
+ rho[<<nc.omega>><<nc.powered>>_<<name>>_TH] = EffectiveResistivity[<<materials[resistivityMacroName[cond.strand.material_stabilizer]](RRR=cond.strand.RRR)>>]{f_stabilizer_<<name>>};
639
+ {% endfor %}
640
+
641
+ // effective thermal conductivity of the bare part
642
+ {% for name, cond in dm.conductors.items() %}
643
+ kappa[<<nc.omega>><<nc.powered>>_<<name>>_TH] = RuleOfMixtures[
644
+ <<materials[thermalConductivityMacroName[cond.strand.material_stabilizer]
645
+ ](RRR=cond.strand.RRR)>>
646
+ {% if cond.cable.material_inner_voids != 'helium' %}
647
+ , <<materials[thermalConductivityMacroName[cond.cable.material_inner_voids]]()>>
648
+ {% endif %}
649
+ {% if cond.cable.material_outer_voids != 'helium' %}
650
+ , <<materials[thermalConductivityMacroName[cond.cable.material_outer_voids]]()>>
651
+ {% endif %}
652
+ ]
653
+ {f_stabilizer_<<name>>
654
+ {% if cond.cable.material_inner_voids != 'helium' %}
655
+ , f_inner_voids_<<name>>
656
+ {% endif %}
657
+ {% if cond.cable.material_outer_voids != 'helium' %}
658
+ , f_outer_voids_<<name>>
659
+ {% endif %}
660
+ };
661
+ {% endfor %}
662
+
663
+ // heat capacity of bare part
664
+ {% for name, cond in dm.conductors.items() %}
665
+ {% if cond.strand.material_superconductor == 'Nb-Ti' %}
666
+ heatCap[<<nc.omega>><<nc.powered>>_<<name>>_TH] = RuleOfMixtures[
667
+ <<materials[specificHeatCapacityMacroName[cond.strand.material_stabilizer]]()>>,
668
+ <<materials[specificHeatCapacityMacroName[cond.strand.material_superconductor]](C1=cond.Jc_fit.C1_CUDI1, C2=cond.Jc_fit.C2_CUDI1, current=dm.power_supply.I_initial)>>,
669
+ <<materials[specificHeatCapacityMacroName[cond.cable.material_inner_voids]]()>>,
670
+ <<materials[specificHeatCapacityMacroName[cond.cable.material_outer_voids]]()>>
671
+ ]
672
+ {
673
+ f_stabilizer_<<name>>,
674
+ f_sc_<<name>>,
675
+ f_inner_voids_<<name>>,
676
+ f_outer_voids_<<name>>
677
+ };
678
+ {% else %}
679
+ heatCap[<<nc.omega>><<nc.powered>>_<<name>>_TH] = RuleOfMixtures[
680
+ <<materials[specificHeatCapacityMacroName[cond.strand.material_stabilizer]]()>>,
681
+ <<materials[specificHeatCapacityMacroName[cond.strand.material_superconductor]]()>>,
682
+ <<materials[specificHeatCapacityMacroName[cond.cable.material_inner_voids]]()>>,
683
+ <<materials[specificHeatCapacityMacroName[cond.cable.material_outer_voids]]()>>
684
+ ]
685
+ {
686
+ f_stabilizer_<<name>>,
687
+ f_sc_<<name>>,
688
+ f_inner_voids_<<name>>,
689
+ f_outer_voids_<<name>>
690
+ };
691
+ {% endif %}
692
+ {% endfor %}
693
+
694
+ // joule losses of bare part
695
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
696
+ jouleLosses[] = CFUN_quenchState_Ic[criticalCurrentDensity[$1, $2] * SurfaceArea[]]{source_current} * rho[$1, $2] * SquNorm[source_current/SurfaceArea[]];
697
+ {% else %}
698
+ jouleLosses[] = CFUN_quenchState_Ic[criticalCurrentDensity[$1] * SurfaceArea[]]{source_current} * rho[$1] * SquNorm[source_current/SurfaceArea[]];
699
+ {% endif %}
700
+
701
+ {% if dm.magnet.geometry.thermal.with_wedges %}
702
+ // thermal conductivity of the wedges
703
+ kappa[<<nc.omega>><<nc.induced>>_TH] = <<materials[thermalConductivityMacroName[dm.magnet.solve.wedges.material]](RRR=dm.magnet.solve.wedges.RRR)>>;
704
+
705
+ // heat capacity of wedges
706
+ heatCap[<<nc.omega>><<nc.induced>>_TH] = <<materials[specificHeatCapacityMacroName[dm.magnet.solve.wedges.material]]()>>;
707
+ {% endif %}
708
+
709
+ {% if dm.magnet.geometry.thermal.with_iron_yoke %}
710
+ // thermal conductivity of the iron yoke
711
+ kappa[<<nc.omega>><<nc.iron>>_TH] = 300;
712
+
713
+ // heat capacity of iron yoke
714
+ heatCap[ <<nc.omega>><<nc.iron>>_TH ] = 50;
715
+ {% endif %}
716
+
717
+ {% if dm.magnet.geometry.thermal.use_TSA %}
718
+ For i In {1:num_dirichlet}
719
+ // piece-wise defined const_temp
720
+ const_temp[Region[bnd_dirichlet~{i}]] = val_temperature~{i};
721
+ EndFor
722
+
723
+ For n In {1:num_neumann}
724
+ // piece-wise defined heatFlux
725
+ heatFlux[Region[bnd_neumann~{n}]] = val_heatFlux~{n};
726
+ EndFor
727
+
728
+ For r In {1:num_robin}
729
+ // piece-wise defined heatExchCoeff
730
+ heatExchCoeff[Region[bnd_robin~{r}]] = val_heatExchCoeff~{r}[$1, $2];
731
+ Tinf[Region[bnd_robin~{r}]] = val_Tinf~{r};
732
+ EndFor
733
+ {% else %}
734
+ // thermal conductivity of the insulation
735
+ kappa[<<nc.omega>><<nc.insulator>>_TH] = <<materials[thermalConductivityMacroName[list(dm.conductors.values())[0].cable.material_insulation]]()>>;
736
+
737
+ // heat capacity of insulation
738
+ heatCap[ <<nc.omega>><<nc.insulator>>_TH ] = <<materials[specificHeatCapacityMacroName[list(dm.conductors.values())[0].cable.material_insulation]]()>>;
739
+ {% endif %}
740
+
741
+ {% if dm.magnet.geometry.thermal.use_TSA %}
742
+ // --------------- Thickness function ----------------------------------------
743
+ // check if we need to flip the order of the layers
744
+ // TODO: this is not very elegant, but it works
745
+ // TODO: check if delta[i] instead of delta~{i} works
746
+ {% set TSAinsulationAndQH_layers_number = rm_TH.thin_shells.insulation_types.layers_number + rm_TH.thin_shells.quench_heaters.layers_number %}
747
+ {% set TSAinsulationAndQH_thicknesses = rm_TH.thin_shells.insulation_types.thicknesses + rm_TH.thin_shells.quench_heaters.thicknesses %}
748
+ {% set TSAinsulationAndQH_thin_shells = rm_TH.thin_shells.insulation_types.thin_shells + rm_TH.thin_shells.quench_heaters.thin_shells %}
749
+ {% set TSAinsulationAndQH_material = rm_TH.thin_shells.insulation_types.layers_material + rm_TH.thin_shells.quench_heaters.layers_material %}
750
+
751
+ {% for nr, n_ele in enumerate(TSAinsulationAndQH_layers_number) %}
752
+ {% for nr_thickness, thickness in enumerate(TSAinsulationAndQH_thicknesses[nr]) %}
753
+ {% for tag in TSAinsulationAndQH_thin_shells[nr] %}
754
+ {% if tag in flip_tags %}
755
+ delta_<<n_ele - nr_thickness - 1>>[Region[<<tag>>]] = <<thickness>>;
756
+ {% for k in range(1,3) %}
757
+ {% for l in range(1,3) %}
758
+ thermalConductivityMass_<<k>>_<<l>>_<<n_ele - nr_thickness - 1>>[Region[<<tag>>]] = <<TSA_materials[thermalConductivityTSAMassMacroName[TSAinsulationAndQH_material[nr][nr_thickness]]](T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, l=l, GaussianPoints=2)>>;
759
+
760
+ thermalConductivityStiffness_<<k>>_<<l>>_<<n_ele - nr_thickness - 1>>[Region[<<tag>>]] = <<TSA_materials[thermalConductivityTSAStiffnessMacroName[TSAinsulationAndQH_material[nr][nr_thickness]]](T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, l=l, GaussianPoints=2)>>;
761
+
762
+ specificHeatCapacity_<<k>>_<<l>>_<<n_ele - nr_thickness - 1>>[Region[<<tag>>]] = <<TSA_materials[specificHeatCapacityTSAMacroName[TSAinsulationAndQH_material[nr][nr_thickness]]](T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, l=l, GaussianPoints=2)>>;
763
+ {% endfor %}
764
+ {% endfor %}
765
+ {% else %}
766
+ delta_<<nr_thickness>>[Region[<<tag>>]] = <<thickness>>;
767
+ {% for k in range(1,3) %}
768
+ {% for l in range(1,3) %}
769
+ thermalConductivityMass_<<k>>_<<l>>_<<nr_thickness>>[Region[<<tag>>]] = <<TSA_materials[thermalConductivityTSAMassMacroName[TSAinsulationAndQH_material[nr][nr_thickness]]](T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, l=l, GaussianPoints=2)>>;
770
+
771
+ thermalConductivityStiffness_<<k>>_<<l>>_<<nr_thickness>>[Region[<<tag>>]] = <<TSA_materials[thermalConductivityTSAStiffnessMacroName[TSAinsulationAndQH_material[nr][nr_thickness]]](T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, l=l, GaussianPoints=2)>>;
772
+
773
+ specificHeatCapacity_<<k>>_<<l>>_<<nr_thickness>>[Region[<<tag>>]] = <<TSA_materials[specificHeatCapacityTSAMacroName[TSAinsulationAndQH_material[nr][nr_thickness]]](T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, l=l, GaussianPoints=2)>>;
774
+ {% endfor %}
775
+ {% endfor %}
776
+ {% endif %}
777
+ {% endfor %}
778
+ {% endfor %}
779
+ {% endfor %}
780
+
781
+ {% for nr, n_ele in enumerate(rm_TH.thin_shells.quench_heaters.layers_number) %}
782
+ {% for nr_thickness, thickness in enumerate(rm_TH.thin_shells.quench_heaters.thicknesses[nr]) %}
783
+ {% for tag in rm_TH.thin_shells.quench_heaters.thin_shells[nr] %}
784
+ {% set qh_indexPlusOne = rm_TH.thin_shells.quench_heaters.label[nr][nr_thickness] %}
785
+ {% if qh_indexPlusOne %}
786
+ {% set qh_dict = dm.quench_protection.quench_heaters %}
787
+ {% set qh_index = int(qh_indexPlusOne or 1E20) - 1 %}
788
+ {% set l_SS = qh_dict.l_stainless_steel[qh_index] / (qh_dict.l_copper[qh_index] + qh_dict.l_stainless_steel[qh_index]) * qh_dict.l[qh_index] %}
789
+ {% endif %}
790
+
791
+ {% if tag in flip_tags %}
792
+ {% for k in range(1,3) %}
793
+ {% if qh_indexPlusOne %}
794
+ powerDensity_<<k>>_<<n_ele - nr_thickness - 1>>[Region[<<tag>>]] = <<TSA_materials['MATERIAL_QuenchHeater_SSteel_t_T'](t_on=qh_dict.t_trigger[qh_index], U_0=qh_dict.U0[qh_index], C=qh_dict.C[qh_index], R_warm=qh_dict.R_warm[qh_index], w_SS=qh_dict.w[qh_index], h_SS=qh_dict.h[qh_index], l_SS=l_SS, mode=1, time="$Time", T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, GaussianPoints=2)>>;
795
+ {% else %}
796
+ powerDensity_<<k>>_<<n_ele - nr_thickness - 1>>[Region[<<tag>>]] = 0;
797
+ {% endif %}
798
+ {% endfor %}
799
+ {% else %}
800
+ {% for k in range(1,3) %}
801
+ {% if qh_indexPlusOne %}
802
+ powerDensity_<<k>>_<<nr_thickness>>[Region[<<tag>>]] = <<TSA_materials['MATERIAL_QuenchHeater_SSteel_t_T'](t_on=qh_dict.t_trigger[qh_index], U_0=qh_dict.U0[qh_index], C=qh_dict.C[qh_index], R_warm=qh_dict.R_warm[qh_index], w_SS=qh_dict.w[qh_index], h_SS=qh_dict.h[qh_index], l_SS=l_SS, mode=1, time="$Time",T_i="$1", T_iPlusOne="$2", thickness_TSA="$3", k=k, GaussianPoints=2)>>;
803
+ {% else %}
804
+ powerDensity_<<k>>_<<nr_thickness>>[Region[<<tag>>]] = 0;
805
+ {% endif %}
806
+ {% endfor %}
807
+ {% endif %}
808
+ {% endfor %}
809
+ {% endfor %}
810
+ {% endfor %}
811
+
812
+ {% endif %}
813
+
814
+ {% endif %}
62
815
  }
63
816
 
817
+ {% if dm.magnet.solve.thermal.solve_type %}
818
+
819
+ {% if dm.magnet.geometry.thermal.use_TSA %}
820
+ {% set lines_tags = rm_TH.boundaries.thermal.temperature.groups['r1_a1'] +
821
+ rm_TH.boundaries.thermal.temperature.groups['r1_a2'] +
822
+ rm_TH.boundaries.thermal.temperature.groups['r2_a1'] +
823
+ rm_TH.boundaries.thermal.temperature.groups['r2_a2'] +
824
+ rm_TH.boundaries.thermal.cooling.groups['r1_a1'] +
825
+ rm_TH.boundaries.thermal.cooling.groups['r1_a2'] +
826
+ rm_TH.boundaries.thermal.cooling.groups['r2_a1'] +
827
+ rm_TH.boundaries.thermal.cooling.groups['r2_a2'] +
828
+ rm_TH.thin_shells.mid_turns_layers_poles %}
829
+
830
+ // split to avoid error for two touching lines in different intDomains
831
+ {% set lines_tags_1 = set(lines_tags).intersection(midLayers_1 + bndDir_1 + bndNeuInt_1_1_1 + bndNeuInt_1_2_1 + bndNeuInt_1_1_2 + bndNeuInt_1_2_2 + bndRobinInt_1_1_1 + bndRobinInt_1_2_1 + bndRobinInt_1_1_2 + bndRobinInt_1_2_2) %}
832
+ {% set lines_tags_2 = set(lines_tags).intersection(midLayers_2 + bndDir_2 + bndNeuInt_2_1_1 + bndNeuInt_2_2_1 + bndNeuInt_2_1_2 + bndNeuInt_2_2_2 + bndRobinInt_2_1_1 + bndRobinInt_2_2_1 + bndRobinInt_2_1_2 + bndRobinInt_2_2_2) %}
833
+
834
+ Constraint {
835
+ coordList_Python_1_1() = {<<rc.neighbouring_nodes.groups['1_1']|join(', ')>>};
836
+ coordList_Python_2_1() = {<<rc.neighbouring_nodes.groups['2_1']|join(', ')>>};
837
+ coordList_Python_1_2() = {<<rc.neighbouring_nodes.groups['1_2']|join(', ')>>};
838
+ coordList_Python_2_2() = {<<rc.neighbouring_nodes.groups['2_2']|join(', ')>>};
839
+ For i In {1:2}
840
+ For j In {1:2}
841
+ { Name Temperature~{i}~{j} ;
842
+ Case {
843
+ // Link DoF of auxiliary shells to actual temperature
844
+ { Region midLayers~{i}~{j} ; Type Link;
845
+ RegionRef Bare_Layers~{i}~{j} ; Coefficient 1;
846
+ // coordList or coordList_Python
847
+ Function shiftCoordinate[X[], Y[], Z[]]{coordList_Python~{i}~{j}()};
848
+ }
849
+ If (num_dirichlet > 0)
850
+ // TODO: proper time dependent boundary conditions
851
+ { Region Region[bndDir~{i}~{j}]; Type Assign;
852
+ Value const_temp[]; }
853
+ EndIf
854
+ }
855
+ }
856
+ EndFor
857
+ EndFor
858
+
859
+ {% if dm.magnet.mesh.thermal.isothermal_conductors or dm.magnet.mesh.thermal.isothermal_wedges %}
860
+ { Name isothermal_surs~{1}~{1} ;
861
+ Case {
862
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
863
+ {% for tag in rm_TH.powered['r1_a1'].vol.numbers %}
864
+ { Region Region[<<tag>>] ; Type Link;
865
+ RegionRef Region[<<tag>>] ; Coefficient 1;
866
+ Function Vector[<<rc.isothermal_nodes.conductors['1_1'][tag]|join(', ')>>];
867
+ }
868
+ {% endfor %}
869
+ {% endif %}
870
+ {% if dm.magnet.mesh.thermal.isothermal_wedges %}
871
+ {% for tag in rm_TH.induced['r1_a1'].vol.numbers %}
872
+ { Region Region[<<tag>>] ; Type Link;
873
+ RegionRef Region[<<tag>>] ; Coefficient 1;
874
+ Function Vector[<<rc.isothermal_nodes.wedges['1_1'][tag]|join(', ')>>];
875
+ }
876
+ {% endfor %}
877
+ {% endif %}
878
+ }
879
+ }
880
+ { Name isothermal_surs~{2}~{1} ;
881
+ Case {
882
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
883
+ {% for tag in rm_TH.powered['r2_a1'].vol.numbers %}
884
+ { Region Region[<<tag>>] ; Type Link;
885
+ RegionRef Region[<<tag>>] ; Coefficient 1;
886
+ Function Vector[<<rc.isothermal_nodes.conductors['2_1'][tag]|join(', ')>>];
887
+ }
888
+ {% endfor %}
889
+ {% endif %}
890
+ {% if dm.magnet.mesh.thermal.isothermal_wedges %}
891
+ {% for tag in rm_TH.induced['r2_a1'].vol.numbers %}
892
+ { Region Region[<<tag>>] ; Type Link;
893
+ RegionRef Region[<<tag>>] ; Coefficient 1;
894
+ Function Vector[<<rc.isothermal_nodes.wedges['2_1'][tag]|join(', ')>>];
895
+ }
896
+ {% endfor %}
897
+ {% endif %}
898
+ }
899
+ }
900
+ { Name isothermal_surs~{1}~{2} ;
901
+ Case {
902
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
903
+ {% for tag in rm_TH.powered['r1_a2'].vol.numbers %}
904
+ { Region Region[<<tag>>] ; Type Link;
905
+ RegionRef Region[<<tag>>] ; Coefficient 1;
906
+ Function Vector[<<rc.isothermal_nodes.conductors['1_2'][tag]|join(', ')>>];
907
+ }
908
+ {% endfor %}
909
+ {% endif %}
910
+ {% if dm.magnet.mesh.thermal.isothermal_wedges %}
911
+ {% for tag in rm_TH.induced['r1_a2'].vol.numbers %}
912
+ { Region Region[<<tag>>] ; Type Link;
913
+ RegionRef Region[<<tag>>] ; Coefficient 1;
914
+ Function Vector[<<rc.isothermal_nodes.wedges['1_2'][tag]|join(', ')>>];
915
+ }
916
+ {% endfor %}
917
+ {% endif %}
918
+ }
919
+ }
920
+ { Name isothermal_surs~{2}~{2} ;
921
+ Case {
922
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
923
+ {% for tag in rm_TH.powered['r2_a2'].vol.numbers %}
924
+ { Region Region[<<tag>>] ; Type Link;
925
+ RegionRef Region[<<tag>>] ; Coefficient 1;
926
+ Function Vector[<<rc.isothermal_nodes.conductors['2_2'][tag]|join(', ')>>];
927
+ }
928
+ {% endfor %}
929
+ {% endif %}
930
+ {% if dm.magnet.mesh.thermal.isothermal_wedges %}
931
+ {% for tag in rm_TH.induced['r2_a2'].vol.numbers %}
932
+ { Region Region[<<tag>>] ; Type Link;
933
+ RegionRef Region[<<tag>>] ; Coefficient 1;
934
+ Function Vector[<<rc.isothermal_nodes.wedges['2_2'][tag]|join(', ')>>];
935
+ }
936
+ {% endfor %}
937
+ {% endif %}
938
+ }
939
+ }
940
+
941
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
942
+ { Name isothermal_lines_1 ;
943
+ Case {
944
+ {% for tag in lines_tags_1 %}
945
+ { Region Region[<<tag>>] ; Type Link;
946
+ RegionRef Region[<<tag>>] ; Coefficient 1;
947
+ Function Vector[<<rc.isothermal_nodes.thin_shells[tag]|join(', ')>>];
948
+ }
949
+ {% endfor %}
950
+ }
951
+ }
952
+ { Name isothermal_lines_2 ;
953
+ Case {
954
+ {% for tag in lines_tags_2 %}
955
+ { Region Region[<<tag>>] ; Type Link;
956
+ RegionRef Region[<<tag>>] ; Coefficient 1;
957
+ Function Vector[<<rc.isothermal_nodes.thin_shells[tag]|join(', ')>>];
958
+ }
959
+ {% endfor %}
960
+ }
961
+ }
962
+ {% endif %}
963
+ {% endif %}
964
+ }
965
+ {% endif %}
966
+
967
+ {% endif %}
968
+
64
969
  Constraint {
970
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
65
971
  { Name Dirichlet_a_Mag;
66
972
  Case {
67
973
  { Region <<nc.boundary>><<nc.omega>> ; Value 0.; }
@@ -69,16 +975,41 @@ Constraint {
69
975
  }
70
976
  { Name SourceCurrentDensityZ;
71
977
  Case {
72
- { Region <<nc.omega>><<nc.powered>> ; Value js_fct[]; }
978
+ { Region <<nc.omega>><<nc.powered>>_EM ; Value js_fct[]; }
73
979
  }
74
980
  }
981
+ {% endif %}
982
+
983
+ {% if dm.magnet.solve.thermal.solve_type %}
984
+ { Name initTemp ;
985
+ Case {
986
+ {% if not dm.magnet.geometry.thermal.use_TSA %}
987
+ {% for nr, names in enumerate(rm_TH.boundaries.thermal.temperature.bc.names) %}
988
+ { Region <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.temperature)[nr]>>; Value <<rm_TH.boundaries.thermal.temperature.bc.value[nr]>>; Type Assign; } // boundary condition
989
+ {% endfor %}
990
+ {% endif %}
991
+ {% if dm.magnet.solve.thermal.solve_type == 'transient' %}
992
+ {% if dm.magnet.geometry.thermal.use_TSA %}{ Region Region[{allLayers, midLayers}] ; Value <<dm.magnet.solve.thermal.init_temperature>> ; Type Init; }{% endif %}
993
+ { Region <<nc.omega>>_TH ; Value <<dm.magnet.solve.thermal.init_temperature>> ; Type Init; } // init. condition
994
+ {% endif %}
995
+ }
996
+ }
997
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
998
+ { Name Dirichlet_a_projection;
999
+ Case {
1000
+ { Region <<rm_TH.projection_points.name>> ; Value 0; Type Assign; }
1001
+ }
1002
+ }
1003
+ {% endif %}
1004
+ {% endif %}
75
1005
  }
76
1006
 
77
1007
  FunctionSpace {
1008
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
78
1009
  { Name Hcurl_a_Mag_2D; Type Form1P; // Magnetic vector potential a
79
1010
  BasisFunction {
80
1011
  { Name se; NameOfCoef ae; Function BF_PerpendicularEdge;
81
- Support <<nc.omega>> ; Entity NodesOf[ All ]; }
1012
+ Support <<nc.omega>>_EM ; Entity NodesOf[ All ]; }
82
1013
  }
83
1014
  Constraint {
84
1015
  { NameOfCoef ae; EntityType NodesOf;
@@ -89,7 +1020,7 @@ FunctionSpace {
89
1020
  { Name Hregion_j_Mag_2D; Type Vector; // Electric current density js
90
1021
  BasisFunction {
91
1022
  { Name sr; NameOfCoef jsr; Function BF_RegionZ;
92
- Support <<nc.omega>><<nc.powered>>; Entity <<nc.omega>><<nc.powered>>; }
1023
+ Support <<nc.omega>><<nc.powered>>_EM; Entity <<nc.omega>><<nc.powered>>_EM; }
93
1024
  }
94
1025
  Constraint {
95
1026
  { NameOfCoef jsr; EntityType Region;
@@ -97,141 +1028,778 @@ FunctionSpace {
97
1028
  }
98
1029
  }
99
1030
 
1031
+ {% if dm.magnet.solve.thermal.solve_type %}
1032
+ { Name H_curl_a_artificial_dof; Type Form1P;
1033
+ BasisFunction {
1034
+ { Name se_after_projection; NameOfCoef ae_after_projection; Function BF_PerpendicularEdge;
1035
+ Support <<nc.omega>>_TH ; Entity NodesOf[ All ]; }
1036
+ }
1037
+ // not needed since boundary is not part of <<nc.omega>>_TH
1038
+ Constraint {
1039
+ { NameOfCoef ae_after_projection; EntityType NodesOf;
1040
+ NameOfConstraint Dirichlet_a_projection; }
1041
+ }
1042
+ }
1043
+ {% endif %}
1044
+ {% endif %}
1045
+
1046
+ {% if dm.magnet.solve.thermal.solve_type %}
1047
+ { Name Hgrad_T; Type Form0;
1048
+ BasisFunction {
1049
+ { Name un; NameOfCoef ui; Function BF_Node;
1050
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1051
+ Support Region[ <<nc.omega>>_TH ]; Entity NodesOf[All, Not allLayers];
1052
+ {% else %}
1053
+ Support Region[{<<nc.omega>>_TH, Bnds_support}] ; Entity NodesOf[All];
1054
+ {% endif %}
1055
+ }
1056
+
1057
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1058
+ // temperature on shells following checkered support idea as indicated
1059
+ // by two indices
1060
+ // FYI: another possibility would be to treat the extremity points of
1061
+ // the shells separately
1062
+ For i In {1:2}
1063
+ For j In {1:2}
1064
+ { Name udn~{i}~{j}; NameOfCoef udi~{i}~{j}; Function BF_Node;
1065
+ Support Region[{midLayers~{i}~{j}, Domain_Insulated_Str~{i}~{j}}];
1066
+ Entity NodesOf[{midLayers~{i}~{j}, Bare_Layers~{i}~{j}}]; }
1067
+ EndFor
1068
+ EndFor
1069
+ {% endif %}
1070
+ }
1071
+
1072
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1073
+ SubSpace {
1074
+ // "vertical" subspaces, up and down are connected via thin shell
1075
+ // vertical thin shells
1076
+ { Name Shell_Up_1; NameOfBasisFunction {udn_1_1, udn_1_2};}
1077
+ { Name Shell_Down_1; NameOfBasisFunction {udn_2_2, udn_2_1};}
1078
+
1079
+ // "horizontal" subspaces, up and down are connected via thin shell
1080
+ { Name Shell_Up_2; NameOfBasisFunction {udn_1_1, udn_2_1}; }
1081
+ { Name Shell_Down_2; NameOfBasisFunction {udn_2_2, udn_1_2}; }
1082
+ }
1083
+ {% endif %}
1084
+
1085
+ Constraint {
1086
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1087
+ For i In {1:2}
1088
+ For j In {1:2}
1089
+ { NameOfCoef udi~{i}~{j}; EntityType NodesOf;
1090
+ NameOfConstraint Temperature~{i}~{j}; }
1091
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
1092
+ {NameOfCoef udi~{i}~{j}; EntityType NodesOf;
1093
+ NameOfConstraint isothermal_surs~{i}~{j}; }
1094
+ {% endif %}
1095
+ { NameOfCoef udi~{i}~{j}; EntityType NodesOf;
1096
+ NameOfConstraint initTemp; }
1097
+ EndFor
1098
+ EndFor
1099
+ {% endif %}
1100
+ { NameOfCoef ui; EntityType NodesOf; NameOfConstraint initTemp; }
1101
+ // do not constraint second order basis function as it's already covered by ui
1102
+ }
1103
+ }
1104
+
1105
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1106
+ {% for nr, n_ele in enumerate(TSAinsulationAndQH_layers_number) %}
1107
+ For i In {1:<<n_ele>>-1}
1108
+ For j In {1:2}
1109
+ { Name Hgrad_T~{i}~{j}~{<<nr + 1>>}; Type Form0 ;
1110
+ BasisFunction {
1111
+ { Name sn~{i}~{j}~{<<nr + 1>>}; NameOfCoef Tn~{i}~{j}~{<<nr + 1>>} ; Function BF_Node ;
1112
+ Support intDomain~{j}~{<<nr + 1>>} ; Entity NodesOf[ All ] ; }
1113
+ }
1114
+ Constraint {
1115
+ {% if dm.magnet.mesh.thermal.isothermal_conductors %}
1116
+ { NameOfCoef Tn~{i}~{j}~{<<nr + 1>>}; EntityType NodesOf;
1117
+ NameOfConstraint isothermal_lines~{j}; }
1118
+ {% endif %}
1119
+ { NameOfCoef Tn~{i}~{j}~{<<nr + 1>>}; EntityType NodesOf;
1120
+ NameOfConstraint initTemp; }
1121
+ }
1122
+ }
1123
+ EndFor
1124
+ EndFor
1125
+ {% endfor %}
1126
+ {% endif %}
1127
+ {% endif %}
100
1128
  }
101
1129
 
102
1130
  Jacobian {
103
- { Name Jac ;
104
- Case { { Region <<nc.omega>><<nc.air_far_field>> ;
105
- Jacobian VolSphShell {<<rm.air_far_field.vol.radius_in>>, <<rm.air_far_field.vol.radius_out>>} ; }
106
- { Region All ; Jacobian Vol ; }
1131
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1132
+ { Name Jac_Vol_EM ;
1133
+ Case {
1134
+ { Region <<nc.omega>><<nc.air_far_field>>_EM ;
1135
+ Jacobian VolSphShell {<<rm_EM.air_far_field.vol.radius_in>>, <<rm_EM.air_far_field.vol.radius_out>>} ; }
1136
+ { Region All ; Jacobian Vol ; }
107
1137
  }
108
1138
  }
1139
+ {% endif %}
1140
+
1141
+ {% if dm.magnet.solve.thermal.solve_type %}
1142
+ { Name Jac_Vol_TH ;
1143
+ Case {
1144
+ { Region All ; Jacobian Vol ; }
1145
+ }
1146
+ }
1147
+ { Name Jac_Sur_TH ;
1148
+ Case {
1149
+ { Region All ; Jacobian Sur ; }
1150
+ }
1151
+ }
1152
+ {% endif %}
109
1153
  }
110
1154
 
111
1155
  Integration {
112
- { Name Int ;
113
- Case { { Type Gauss ;
114
- Case {
115
- { GeoElement Point ; NumberOfPoints 1 ; }
116
- { GeoElement Line ; NumberOfPoints 3 ; }
117
- { GeoElement Triangle{% if dm.mesh.ElementOrder == 2 %}2{% endif %} ; NumberOfPoints {% if dm.mesh.ElementOrder == 2 %}3{% else %}4{% endif %} ; }
118
- { GeoElement Quadrangle ; NumberOfPoints 4 ; }
119
- }
120
- } }
1156
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1157
+ { Name Int_EM ;
1158
+ Case {
1159
+ { Type Gauss ;
1160
+ Case {
1161
+ { GeoElement Point ; NumberOfPoints 1 ; }
1162
+ { GeoElement Line ; NumberOfPoints 2 ; }
1163
+ { GeoElement Triangle ; NumberOfPoints 3 ; }
1164
+ { GeoElement Quadrangle ; NumberOfPoints 4 ; }
1165
+ }
1166
+ }
1167
+ }
1168
+ }
1169
+ {% endif %}
1170
+
1171
+ {% if dm.magnet.solve.thermal.solve_type %}
1172
+ { Name Int_line_TH ;
1173
+ Case {
1174
+ { Type Gauss ;
1175
+ Case {
1176
+ { GeoElement Line ; NumberOfPoints 2 ; }
1177
+ }
1178
+ }
1179
+ }
1180
+ }
1181
+
1182
+ { Name Int_conducting_TH ;
1183
+ Case {
1184
+ { Type Gauss ;
1185
+ Case {
1186
+ { GeoElement Triangle ; NumberOfPoints 3 ; }
1187
+ { GeoElement Quadrangle ; NumberOfPoints 4 ; }
1188
+ }
1189
+ }
1190
+ }
1191
+ }
1192
+
1193
+ { Name Int_insulating_TH ;
1194
+ Case {
1195
+ { Type Gauss ;
1196
+ Case {
1197
+ { GeoElement Triangle ; NumberOfPoints 3 ; }
1198
+ { GeoElement Quadrangle ; NumberOfPoints 4 ; }
1199
+ }
1200
+ }
1201
+ }
121
1202
  }
1203
+ {% endif %}
122
1204
  }
123
1205
 
124
1206
  Formulation {
1207
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
125
1208
  { Name Magnetostatics_a_2D; Type FemEquation;
126
1209
  Quantity {
127
1210
  { Name a ; Type Local; NameOfSpace Hcurl_a_Mag_2D; }
128
1211
  { Name js; Type Local; NameOfSpace Hregion_j_Mag_2D; }
129
1212
  }
130
1213
  Equation {
131
- // all terms on the left-hand side (hence the "-" sign in front of
132
- // Dof{js}):
133
- //Integral { [ nu[] * Dof{d a} , {d a} ];
134
- //In <<nc.omega>>; Jacobian Jac; Integration Int; }
135
1214
  Integral { [ nu[{d a}] * Dof{d a} , {d a} ];
136
- In <<nc.omega>>; Jacobian Jac; Integration Int; }
1215
+ In <<nc.omega>>_EM; Jacobian Jac_Vol_EM; Integration Int_EM; }
137
1216
 
138
- {% if dm.geometry.with_iron_yoke %}
139
- Integral { JacNL[ dnuIronYoke[{d a}] * Dof{d a} , {d a} ];
140
- In <<nc.omega>><<nc.iron>>; Jacobian Jac; Integration Int; }
141
- {% endif %}
1217
+ {% if dm.magnet.geometry.electromagnetics.with_iron_yoke %}
1218
+ Integral { JacNL[ dnuIronYoke[{d a}] * Dof{d a} , {d a} ];
1219
+ In <<nc.omega>><<nc.iron>>_EM; Jacobian Jac_Vol_EM; Integration Int_EM; }
1220
+ {% endif %}
142
1221
 
143
1222
  Integral { [ -Dof{js} , {a} ];
144
- In <<nc.omega>><<nc.powered>>; Jacobian Jac; Integration Int; }
1223
+ In <<nc.omega>><<nc.powered>>_EM; Jacobian Jac_Vol_EM; Integration Int_EM; }
145
1224
  }
146
1225
  }
147
- }
148
1226
 
149
- relTol = 1e-5;
150
- absTol = 1e-5;
151
- relaxFactor = 0.9;
152
- NmaxIterations = 100;
1227
+ {% if dm.magnet.solve.thermal.solve_type %}
1228
+ // Dummy formulation just to save the values of the norm of B from the EM mesh on the Gaussian points of
1229
+ // the thermal mesh. Alternatively, a Galerkin projection could be used.
1230
+ { Name Projection_EM_to_TH; Type FemEquation;
1231
+ Quantity {
1232
+ {Name a_before_projection; Type Local; NameOfSpace Hcurl_a_Mag_2D; }
1233
+ {Name a_artificial_dof; Type Local; NameOfSpace H_curl_a_artificial_dof; }
1234
+ }
1235
+ Equation {
1236
+ Integral { [ - SetVariable[Norm[{d a_before_projection}], ElementNum[], QuadraturePointIndex[]]{$Bnorm}, {d a_artificial_dof} ];
1237
+ In <<nc.omega>><<nc.powered>>_TH; Integration Int_conducting_TH; Jacobian Jac_Vol_TH; }
1238
+
1239
+ Integral { [ Dof{d a_artificial_dof}, {d a_artificial_dof} ];
1240
+ In <<nc.omega>><<nc.powered>>_TH; Integration Int_conducting_TH; Jacobian Jac_Vol_TH; }
1241
+ }
1242
+ }
1243
+ {% endif %}
1244
+ {% endif %}
1245
+
1246
+ {% if dm.magnet.solve.thermal.solve_type %}
1247
+ { Name Thermal_T; Type FemEquation;
1248
+ Quantity {
1249
+ // cont temperature
1250
+ { Name T; Type Local; NameOfSpace Hgrad_T; }
1251
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1252
+ For j In {1:2} // "vertical" and "horizontal" separated
1253
+ {% for nr, n_ele in enumerate(TSAinsulationAndQH_layers_number) %}
1254
+
1255
+ // outer temp up
1256
+ { Name Ti~{0}~{j}~{<<nr + 1>>}; Type Local;
1257
+ NameOfSpace Hgrad_T[Shell_Up~{j}]; }
1258
+ // auxiliary shells in between
1259
+ For i In {1:<<n_ele>>-1}
1260
+ { Name Ti~{i}~{j}~{<<nr + 1>>} ; Type Local ;
1261
+ NameOfSpace Hgrad_T~{i}~{j}~{<<nr + 1>>}; }
1262
+ EndFor
1263
+ //outer temp down
1264
+ { Name Ti~{<<n_ele>>}~{j}~{<<nr + 1>>}; Type Local;
1265
+ NameOfSpace Hgrad_T[Shell_Down~{j}]; }
1266
+ {% endfor %}
1267
+ EndFor
1268
+ {% endif %}
1269
+ }
1270
+
1271
+ Equation {
1272
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1273
+ Integral { [ kappa[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] * Dof{d T} , {d T} ] ;
1274
+ In Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>{% endif %}{% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %} } ]; Integration Int_conducting_TH ; Jacobian Jac_Vol_TH ; }
1275
+ {% else %}
1276
+ Integral { [ kappa[{T}] * Dof{d T} , {d T} ] ;
1277
+ In Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>{% endif %}{% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %} } ]; Integration Int_conducting_TH ; Jacobian Jac_Vol_TH ; }
1278
+ {% endif %}
1279
+
1280
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1281
+ Integral { DtDof[ heatCap[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] * Dof{T}, {T} ];
1282
+ In Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>{% endif %}{% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %} } ]; Integration Int_conducting_TH; Jacobian Jac_Vol_TH; }
1283
+ {% else %}
1284
+ Integral { DtDof[ heatCap[{T}] * Dof{T}, {T} ];
1285
+ In Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>{% endif %}{% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %} } ]; Integration Int_conducting_TH; Jacobian Jac_Vol_TH; }
1286
+ {% endif %}
1287
+
1288
+ {% if not dm.magnet.geometry.thermal.use_TSA %}
1289
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1290
+ Integral { [ kappa[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] * Dof{d T} , {d T} ] ;
1291
+ In <<nc.omega>><<nc.insulator>>_TH; Integration Int_insulating_TH ; Jacobian Jac_Vol_TH ; }
1292
+ {% else %}
1293
+ Integral { [ kappa[{T}] * Dof{d T} , {d T} ] ;
1294
+ In <<nc.omega>><<nc.insulator>>_TH; Integration Int_insulating_TH ; Jacobian Jac_Vol_TH ; }
1295
+ {% endif %}
1296
+
1297
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1298
+ Integral { DtDof[ heatCap[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] * Dof{T}, {T} ];
1299
+ In <<nc.omega>><<nc.insulator>>_TH; Integration Int_insulating_TH; Jacobian Jac_Vol_TH; }
1300
+ {% else %}
1301
+ Integral { DtDof[ heatCap[{T}] * Dof{T}, {T} ];
1302
+ In <<nc.omega>><<nc.insulator>>_TH; Integration Int_insulating_TH; Jacobian Jac_Vol_TH; }
1303
+ {% endif %}
1304
+ {% endif %}
1305
+
1306
+ // TODO: implement derivatives, missing copper for example
1307
+ /* Integral { JacNL[ dkappadT[{T}, {d a}] * {d T} * Dof{T} , {d T} ] ;
1308
+ In <<nc.omega>>_TH; Integration Int<> ; Jacobian Jac_Vol_TH ; } */
1309
+
1310
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1311
+ Integral { [ - jouleLosses[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}], {T}];
1312
+ In <<nc.omega>><<nc.powered>>_TH; Integration Int_conducting_TH; Jacobian Jac_Vol_TH; }
1313
+ {% else %}
1314
+ Integral { [ - jouleLosses[{T}], {T}];
1315
+ In <<nc.omega>><<nc.powered>>_TH; Integration Int_conducting_TH; Jacobian Jac_Vol_TH; }
1316
+ {% endif %}
1317
+
1318
+ {% if dm.magnet.geometry.thermal.use_TSA %}
1319
+ {% for nr, n_ele in enumerate(TSAinsulationAndQH_layers_number) %}
1320
+ For i In {0:<<n_ele-1>>} // loop over 1D FE elements
1321
+ For j In {1:2} // separation between vertical and horizontal
1322
+ {% for k in range(1,3) %}
1323
+ {% for l in range(1,3) %}
1324
+ Integral {
1325
+ [ thermalConductivityMass_<<k>>_<<l>>~{i}[{Ti~{i}~{j}~{<<nr + 1>>}}, {Ti~{i+1}~{j}~{<<nr + 1>>}}, delta~{i}[]] *
1326
+ Dof{d Ti~{i + <<k>> - 1}~{j}~{<<nr + 1>>}} , {d Ti~{i + <<l>> - 1}~{j}~{<<nr + 1>>}}];
1327
+ In intDomain~{j}~{<<nr + 1>>}; Integration Int_line_TH; Jacobian Jac_Sur_TH;
1328
+ }
1329
+
1330
+ Integral {
1331
+ [thermalConductivityStiffness_<<k>>_<<l>>~{i}[{Ti~{i}~{j}~{<<nr + 1>>}}, {Ti~{i+1}~{j}~{<<nr + 1>>}}, delta~{i}[]] *
1332
+ Dof{Ti~{i + <<k>> - 1}~{j}~{<<nr + 1>>}} , {Ti~{i + <<l>> - 1}~{j}~{<<nr + 1>>}} ];
1333
+ In intDomain~{j}~{<<nr + 1>>}; Integration Int_line_TH; Jacobian Jac_Sur_TH;
1334
+ }
1335
+
1336
+ Integral {
1337
+ DtDof[ specificHeatCapacity_<<k>>_<<l>>~{i}[{Ti~{i}~{j}~{<<nr + 1>>}}, {Ti~{i+1}~{j}~{<<nr + 1>>}}, delta~{i}[]] *
1338
+ Dof{Ti~{i + <<k>> - 1}~{j}~{<<nr + 1>>}} , {Ti~{i + <<l>> - 1}~{j}~{<<nr + 1>>}} ];
1339
+ In intDomain~{j}~{<<nr + 1>>}; Integration Int_line_TH; Jacobian Jac_Sur_TH;
1340
+ }
1341
+
1342
+ {% endfor %}
1343
+
1344
+ {% endfor %}
1345
+ EndFor // j
1346
+ EndFor // i
1347
+ {% endfor %}
1348
+
1349
+ {% for nr, n_ele in enumerate(rm_TH.thin_shells.quench_heaters.layers_number) %}
1350
+ {% set qu_nr = nr + len(rm_TH.thin_shells.insulation_types.thin_shells) %}
1351
+
1352
+ For i In {0:<<n_ele-1>>} // loop over 1D FE elements
1353
+ For j In {1:2} // separation between vertical and horizontal
1354
+ {% for k in range(1,3) %}
1355
+
1356
+ Integral { [- powerDensity_<<k>>~{i}[{Ti~{i}~{j}~{<<qu_nr + 1>>}}, {Ti~{i+1}~{j}~{<<qu_nr + 1>>}}, delta~{i}[]], {Ti~{i + <<k>> - 1}~{j}~{<<qu_nr + 1>>}} ];
1357
+ In intDomain~{j}~{<<qu_nr + 1>>}; Integration Int_line_TH; Jacobian Jac_Sur_TH; }
1358
+
1359
+ {% endfor %}
1360
+ EndFor // j
1361
+ EndFor // i
1362
+ {% endfor %}
1363
+
1364
+ // one fewer for loop cause no horVerLayers --> but one more bc of function for N_eleL
1365
+ If (num_robin > 0)
1366
+ {% for nr, n_ele in enumerate(TSAinsulationAndQH_layers_number) %}
1367
+ // ----------------- ROBIN -----------------------------------------------
1368
+ For j In {1:2} // separation between vertical and horizontal
1369
+ For x In {1:2}
1370
+ For a In {1:2}
1371
+ Integral { [heatExchCoeff[{Ti~{outerElem~{j}~{x}~{a}~{<<nr + 1>>}}~{j}~{<<nr + 1>>}}, Tinf[]] * Dof{Ti~{outerElem~{j}~{x}~{a}~{<<nr + 1>>}}~{j}~{<<nr + 1>>}},
1372
+ {Ti~{outerElem~{j}~{x}~{a}~{<<nr + 1>>}}~{j}~{<<nr + 1>>}} ] ;
1373
+ In bndRobinInt~{j}~{x}~{a}~{<<nr + 1>>}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1374
+
1375
+ Integral { [-heatExchCoeff[{Ti~{outerElem~{j}~{x}~{a}~{<<nr + 1>>}}~{j}~{<<nr + 1>>}}, Tinf[]] * Tinf[], {Ti~{outerElem~{j}~{x}~{a}~{<<nr + 1>>}}~{j}~{<<nr + 1>>}} ] ;
1376
+ In bndRobinInt~{j}~{x}~{a}~{<<nr + 1>>}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1377
+ EndFor
1378
+ EndFor
1379
+ EndFor
1380
+ {% endfor %}
1381
+ EndIf
1382
+
1383
+ // ----------------- NEUMANN -----------------------------------------------
1384
+ // one fewer for loop cause no horVerLayers --> but one more bc of function for N_eleL
1385
+ If (num_neumann > 0)
1386
+ {% for nr, n_ele in enumerate(TSAinsulationAndQH_layers_number) %}
1387
+ // ----------------- Neumann -----------------------------------------------
1388
+ For j In {1:2} // separation between vertical and horizontal
1389
+ For x In {1:2}
1390
+ For a In {1:2}
1391
+ Integral { [-heatFlux[],
1392
+ {Ti~{outerElem~{j}~{x}~{a}~{<<nr + 1>>}}~{j}~{<<nr + 1>>}} ] ;
1393
+ In bndNeuInt~{j}~{x}~{a}~{<<nr + 1>>}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1394
+ EndFor
1395
+ EndFor
1396
+ EndFor
1397
+ {% endfor %}
1398
+ EndIf
1399
+
1400
+ {% else %} {# not TSA #}
1401
+
1402
+ // Neumann
1403
+ {% for nr, value in enumerate(rm_TH.boundaries.thermal.heat_flux.bc.value) %}
1404
+ Integral { [- <<value>> , {T} ] ;
1405
+ In {% if dm.magnet.solve.thermal.He_cooling.sides != 'external' and nr == 0 %} general_adiabatic {% else %} <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.heat_flux)[nr - 1 if dm.magnet.solve.thermal.He_cooling.sides != 'external' else nr]>> {% endif %}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1406
+ {% endfor %}
1407
+
1408
+ // Robin
1409
+ // n * kappa grad (T) = h (T - Tinf) becomes two terms since GetDP can only
1410
+ // handle linear and not affine terms
1411
+ // NOTE: signs might be switched
1412
+ {% for nr, values in enumerate(rm_TH.boundaries.thermal.cooling.bc.values) %}
1413
+ {% if isinstance(values[0], str) %}
1414
+ Integral { [<<values[0]>>[{T}, <<values[1]>>] * Dof{T}, {T} ] ;
1415
+ In {% if dm.magnet.solve.thermal.He_cooling.enabled and nr == 0 %} general_cooling {% else %} <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling)[nr - 1 if dm.magnet.solve.thermal.He_cooling.enabled else nr]>> {% endif %}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1416
+ Integral { [-<<values[0]>>[{T}, <<values[1]>>] * <<values[1]>> , {T} ] ;
1417
+ In {% if dm.magnet.solve.thermal.He_cooling.enabled and nr == 0 %} general_cooling {% else %} <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling)[nr - 1 if dm.magnet.solve.thermal.He_cooling.enabled else nr]>> {% endif %}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1418
+ {% else %}
1419
+ Integral { [<<values[0]>> * Dof{T}, {T} ] ;
1420
+ In {% if dm.magnet.solve.thermal.He_cooling.enabled and nr == 0 %} general_cooling {% else %} <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling)[nr - 1 if dm.magnet.solve.thermal.He_cooling.enabled else nr]>> {% endif %}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1421
+ Integral { [-<<values[0]>> * <<values[1]>> , {T} ] ;
1422
+ In {% if dm.magnet.solve.thermal.He_cooling.enabled and nr == 0 %} general_cooling {% else %} <<list(dm.magnet.solve.thermal.overwrite_boundary_conditions.cooling)[nr - 1 if dm.magnet.solve.thermal.He_cooling.enabled else nr]>> {% endif %}; Integration Int_line_TH ; Jacobian Jac_Sur_TH ; }
1423
+ {% endif %}
1424
+ {% endfor %}
1425
+ {% endif %}
1426
+ }
1427
+ }
1428
+ {% endif %}
1429
+ }
153
1430
 
154
1431
  Resolution {
155
- { Name MagSta_a;
1432
+ { Name resolution;
156
1433
  System {
157
- { Name Sys_Mag; NameOfFormulation Magnetostatics_a_2D; } // NameOfMesh "mesh.msh";
1434
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1435
+ { Name Sys_Mag; NameOfFormulation Magnetostatics_a_2D; NameOfMesh "<<mf['EM']>>"; }
1436
+ {% endif %}
1437
+ {% if dm.magnet.solve.thermal.solve_type %}
1438
+ { Name Sys_The; NameOfFormulation Thermal_T; NameOfMesh "<<mf['TH']>>"; }
1439
+ {% endif %}
1440
+ {% if (dm.magnet.solve.electromagnetics.solve_type and dm.magnet.solve.thermal.solve_type) %}
1441
+ { Name sys_Mag_projection; NameOfFormulation Projection_EM_to_TH; NameOfMesh "<<mf['TH']>>";}
1442
+ {% endif %}
158
1443
  }
159
1444
  Operation {
1445
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
160
1446
  InitSolution[Sys_Mag];
161
- IterativeLoopN[NmaxIterations, relaxFactor,
162
- System { { Sys_Mag, relTol, absTol, Solution LinfNorm } }
163
- // PostOperation { { V_Top, ReltolP, AbstolP, MeanL1Norm } }
164
- ] {
165
- GenerateJac[Sys_Mag]; SolveJac[Sys_Mag];
1447
+ IterativeLoopN[<<dm.magnet.solve.electromagnetics.non_linear_solver.max_iterations>>, <<dm.magnet.solve.electromagnetics.non_linear_solver.relaxation_factor>>,
1448
+ System { { Sys_Mag, <<dm.magnet.solve.electromagnetics.non_linear_solver.rel_tolerance>>, <<dm.magnet.solve.electromagnetics.non_linear_solver.abs_tolerance>>, Solution <<dm.magnet.solve.electromagnetics.non_linear_solver.norm_type>> } }
1449
+ ] { GenerateJac[Sys_Mag]; SolveJac[Sys_Mag]; }
1450
+ PostOperation[Map_a];
1451
+ {% endif %}
1452
+
1453
+ {% if (dm.magnet.solve.electromagnetics.solve_type and dm.magnet.solve.thermal.solve_type) %}
1454
+ Generate[sys_Mag_projection]; Solve[sys_Mag_projection];
1455
+ SaveSolution[sys_Mag_projection]; //PostOperation[b_after_projection_pos];
1456
+ {% endif %}
1457
+
1458
+ {% if dm.magnet.solve.thermal.solve_type %}
1459
+ SetExtrapolationOrder[0];
1460
+ InitSolution Sys_The; // init. the solution using init. constraints
1461
+
1462
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1463
+ //PostOperation[b_thermal];
1464
+ {% endif %}
1465
+
1466
+ {% if dm.magnet.postproc.thermal.output_time_steps_txt %}
1467
+ CreateDirectory["T_avg"];
1468
+ {% endif %}
1469
+ {% if dm.magnet.postproc.thermal.output_time_steps_txt == 1 %}
1470
+ PostOperation[T_avg];
1471
+ {% endif %}
1472
+
1473
+ {% if dm.magnet.postproc.thermal.output_time_steps_pos == 1 %}
1474
+ PostOperation[Map_T];
1475
+ {% endif %}
1476
+
1477
+ // initialized cumulate times to zero to avoid warning
1478
+ Evaluate[$tg_cumul_cpu = 0, $ts_cumul_cpu = 0, $tg_cumul_wall = 0, $ts_cumul_wall = 0];
1479
+ Print["timestep,gen_wall,gen_cpu,sol_wall,sol_cpu,pos_wall,pos_cpu,gen_wall_cumul,gen_cpu_cumul,sol_wall_cumul,sol_cpu_cumul,pos_wall_cumul,pos_cpu_cumul", File "computation_times.csv"];
1480
+ //PostOperation[b_after_projection_pos];
1481
+
1482
+ {% if dm.magnet.solve.thermal.solve_type == 'transient' %}
1483
+
1484
+ Evaluate[$tg_wall = 0, $tg_cpu = 0, $ts_wall = 0, $ts_cpu = 0];
1485
+
1486
+ TimeLoopAdaptive
1487
+ [ <<dm.magnet.solve.thermal.time_stepping.initial_time>>, <<dm.magnet.solve.thermal.time_stepping.final_time>>, <<dm.magnet.solve.thermal.time_stepping.initial_time_step>>, <<dm.magnet.solve.thermal.time_stepping.min_time_step>>, <<dm.magnet.solve.thermal.time_stepping.max_time_step>>, "<<dm.magnet.solve.thermal.time_stepping.integration_method>>", List[Breakpoints],
1488
+ System { { Sys_The, <<dm.magnet.solve.thermal.time_stepping.rel_tol_time>>, <<dm.magnet.solve.thermal.time_stepping.abs_tol_time>>, <<dm.magnet.solve.thermal.time_stepping.norm_type>> } } ]
1489
+ {
1490
+ IterativeLoopN[<<dm.magnet.solve.thermal.non_linear_solver.max_iterations>>, <<dm.magnet.solve.thermal.non_linear_solver.relaxation_factor>>,
1491
+ System { { Sys_The, <<dm.magnet.solve.thermal.non_linear_solver.rel_tolerance>>, <<dm.magnet.solve.thermal.non_linear_solver.abs_tolerance>>, Solution <<dm.magnet.solve.thermal.non_linear_solver.norm_type>> } }]
1492
+ {
1493
+ Evaluate[ $tg1_wall = GetWallClockTime[], $tg1_cpu = GetCpuTime[] ];
1494
+ GenerateJac Sys_The ;
1495
+ Evaluate[ $tg2_wall = GetWallClockTime[], $tg2_cpu = GetCpuTime[] ];
1496
+
1497
+ // add to generation times of previous rejected time steps
1498
+ Evaluate[ $tg_wall = $tg_wall + $tg2_wall - $tg1_wall, $tg_cpu = $tg_cpu + $tg2_cpu - $tg1_cpu ];
1499
+
1500
+ Evaluate[ $ts1_wall = GetWallClockTime[], $ts1_cpu = GetCpuTime[] ];
1501
+ SolveJac Sys_The;
1502
+ Evaluate[ $ts2_wall = GetWallClockTime[], $ts2_cpu = GetCpuTime[] ];
1503
+
1504
+ // add to solution times of previous rejected time steps
1505
+ Evaluate[ $ts_wall = $ts_wall + $ts2_wall - $ts1_wall, $ts_cpu = $ts_cpu + $ts2_cpu - $ts1_cpu ];
1506
+
1507
+ {% if dm.magnet.solve.thermal.enforce_init_temperature_as_minimum %}
1508
+ SolutionSetMin[Sys_The, <<dm.magnet.solve.thermal.init_temperature>>];
1509
+ {% endif %}
1510
+ }
1511
+ }
1512
+ {
1513
+ // save solution to .res file
1514
+ SaveSolution[Sys_The];
1515
+
1516
+ Evaluate[ $tp1_wall = GetWallClockTime[], $tp1_cpu = GetCpuTime[] ];
1517
+ // print average temperature
1518
+ {% if (not dm.magnet.postproc.thermal.save_txt_at_the_end and dm.magnet.postproc.thermal.output_time_steps_txt) %}
1519
+ {% if dm.magnet.postproc.thermal.output_time_steps_txt > 1%}
1520
+ Test[$TimeStep > 1] {
1521
+ PostOperation[T_avg];
166
1522
  }
167
- // Generate[Sys_Mag]; Solve[Sys_Mag]; SaveSolution[Sys_Mag];
1523
+ {% else %}
1524
+ PostOperation[T_avg];
1525
+ {% endif %}
1526
+ {% endif %}
1527
+
1528
+ // print temperature map
1529
+ {% if (not dm.magnet.postproc.thermal.save_pos_at_the_end and dm.magnet.postproc.thermal.output_time_steps_pos) %}
1530
+ {% if dm.magnet.postproc.thermal.output_time_steps_pos > 1%}
1531
+ Test[$TimeStep > 1] {
1532
+ PostOperation[Map_T];
1533
+ }
1534
+ {% else %}
1535
+ PostOperation[Map_T];
1536
+ {% endif %}
1537
+ {% endif %}
1538
+
1539
+ PostOperation[PrintMaxTemp]; // save maximum temperature in register 1
1540
+ Evaluate[ $tp2_wall = GetWallClockTime[], $tp2_cpu = GetCpuTime[] ];
1541
+
1542
+ Evaluate[ $tp_wall = $tp2_wall - $tp1_wall, $tp_cpu = $tp2_cpu - $tp1_cpu ];
1543
+
1544
+ // cumulated times
1545
+ Evaluate[ $tg_cumul_wall = $tg_cumul_wall + $tg_wall, $tg_cumul_cpu = $tg_cumul_cpu + $tg_cpu, $ts_cumul_wall = $ts_cumul_wall + $ts_wall, $ts_cumul_cpu = $ts_cumul_cpu + $ts_cpu, $tp_cumul_wall = $tp_cumul_wall + $tp2_wall - $tp1_wall, $tp_cumul_cpu = $tp_cumul_cpu + $tp2_cpu - $tp1_cpu];
1546
+
1547
+ // print to file
1548
+ Print[{$TimeStep, $tg_wall, $tg_cpu, $ts_wall, $ts_cpu, $tp_wall, $tp_cpu, $tg_cumul_wall, $tg_cumul_cpu, $ts_cumul_wall, $ts_cumul_cpu, $tp_cumul_wall, $tp_cumul_cpu}, Format "%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g", File "computation_times.csv"];
1549
+
1550
+ // reset after accepted time step
1551
+ Evaluate[$tg_wall = 0, $tg_cpu = 0, $ts_wall = 0, $ts_cpu = 0];
1552
+
1553
+ // check if maximum temperature is reached
1554
+
1555
+ {# raw block needed since use of # in following code #}
1556
+ {% raw %}
1557
+ Print[{#1}, Format "Maximum temperature: %g "];
1558
+ Test[#1 > stop_temperature] {
1559
+ Break[];
1560
+ }
1561
+ {% endraw %}
1562
+ }
1563
+
1564
+ {% else %} // stationary
1565
+
1566
+ Evaluate[$tg_wall = 0, $tg_cpu = 0, $ts_wall = 0, $ts_cpu = 0];
1567
+
1568
+ IterativeLoopN[<<dm.magnet.solve.thermal.non_linear_solver.max_iterations>>, <<dm.magnet.solve.thermal.non_linear_solver.relaxation_factor>>,
1569
+ System { { Sys_The, <<dm.magnet.solve.thermal.non_linear_solver.rel_tolerance>>, <<dm.magnet.solve.thermal.non_linear_solver.abs_tolerance>>, Solution <<dm.magnet.solve.thermal.non_linear_solver.norm_type>> } }]
1570
+ {
1571
+ Evaluate[ $tg1_wall = GetWallClockTime[], $tg1_cpu = GetCpuTime[] ];
1572
+ GenerateJac Sys_The ;
1573
+ Evaluate[ $tg2_wall = GetWallClockTime[], $tg2_cpu = GetCpuTime[] ];
1574
+
1575
+ // add to generation times of previous rejected time steps
1576
+ Evaluate[ $tg_wall = $tg_wall + $tg2_wall - $tg1_wall, $tg_cpu = $tg_cpu + $tg2_cpu - $tg1_cpu ];
1577
+
1578
+ Evaluate[ $ts1_wall = GetWallClockTime[], $ts1_cpu = GetCpuTime[] ];
1579
+ SolveJac Sys_The;
1580
+ Evaluate[ $ts2_wall = GetWallClockTime[], $ts2_cpu = GetCpuTime[] ];
1581
+
1582
+ // add to solution times of previous rejected time steps
1583
+ Evaluate[ $ts_wall = $ts_wall + $ts2_wall - $ts1_wall, $ts_cpu = $ts_cpu + $ts2_cpu - $ts1_cpu ];
1584
+
1585
+ {% if dm.magnet.solve.thermal.enforce_init_temperature_as_minimum %}
1586
+ SolutionSetMin[Sys_The, <<dm.magnet.solve.thermal.init_temperature>>];
1587
+ {% endif %}
1588
+ }
1589
+
1590
+ // cumulated times
1591
+ Evaluate[ $tg_cumul_wall = $tg_cumul_wall + $tg_wall, $tg_cumul_cpu = $tg_cumul_cpu + $tg_cpu, $ts_cumul_wall = $ts_cumul_wall + $ts_wall, $ts_cumul_cpu = $ts_cumul_cpu + $ts_cpu ];
1592
+
1593
+ // print to file
1594
+ Print[{$TimeStep, $tg_wall, $tg_cpu, $ts_wall, $ts_cpu, $tp_wall, $tp_cpu, $tg_cumul_wall, $tg_cumul_cpu, $ts_cumul_wall, $ts_cumul_cpu, $tp_cumul_wall, $tp_cumul_cpu}, Format "%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g", File "computation_times.csv"];
1595
+
1596
+ SaveSolution[Sys_The];
1597
+ {% endif %}
1598
+
1599
+ Evaluate[ $tp1_wall = GetWallClockTime[], $tp1_cpu = GetCpuTime[] ];
1600
+ {% if (dm.magnet.postproc.thermal.save_txt_at_the_end and dm.magnet.postproc.thermal.output_time_steps_txt) %}
1601
+ PostOperation[T_avg];
1602
+ {% endif %}
1603
+
1604
+ {% if (dm.magnet.postproc.thermal.save_pos_at_the_end and dm.magnet.postproc.thermal.output_time_steps_pos) %}
1605
+ PostOperation[Map_T];
1606
+ {% endif %}
1607
+ Evaluate[ $tp2_wall = GetWallClockTime[], $tp2_cpu = GetCpuTime[] ];
1608
+
1609
+ Evaluate[ $tp_wall = $tp2_wall - $tp1_wall, $tp_cpu = $tp2_cpu - $tp1_cpu ];
1610
+
1611
+ Print[{$tp_wall, $tp_cpu, $tg_cumul_wall, $tg_cumul_cpu, $ts_cumul_wall, $ts_cumul_cpu, $tp_cumul_wall, $tp_cumul_cpu}, Format "-1,0,0,0,0,%g,%g,%g,%g,%g,%g,%g,%g", File "computation_times.csv"];
1612
+ {% endif %}
168
1613
  }
169
1614
  }
170
1615
  }
171
1616
 
172
1617
  PostProcessing {
173
- { Name MagSta_a_2D; NameOfFormulation Magnetostatics_a_2D;
1618
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1619
+ { Name MagSta_a_2D; NameOfFormulation Magnetostatics_a_2D; NameOfSystem Sys_Mag;
174
1620
  Quantity {
175
1621
  { Name a;
176
1622
  Value {
177
- Term { [ {a} ]; In <<nc.omega>>; Jacobian Jac; }
1623
+ Term { [ {a} ]; In <<nc.omega>>_EM; Jacobian Jac_Vol_EM; }
178
1624
  }
179
1625
  }
180
1626
  { Name az;
181
1627
  Value {
182
- Term { [ CompZ[{a}] ]; In <<nc.omega>>; Jacobian Jac; }
1628
+ Term { [ CompZ[{a}] ]; In <<nc.omega>>_EM; Jacobian Jac_Vol_EM; }
183
1629
  }
184
1630
  }
185
1631
  { Name b;
186
1632
  Value {
187
- Term { [ {d a} ]; In <<nc.omega>>; Jacobian Jac; }
1633
+ Term { [ {d a} ]; In <<nc.omega>>_EM; Jacobian Jac_Vol_EM; }
188
1634
  }
189
1635
  }
190
1636
  { Name h;
191
1637
  Value {
192
- Term { [ nu[{d a}] * {d a} ]; In <<nc.omega>>; Jacobian Jac; }
1638
+ Term { [ nu[{d a}] * {d a} ]; In <<nc.omega>>_EM; Jacobian Jac_Vol_EM; }
193
1639
  }
194
1640
  }
195
1641
  { Name js;
196
1642
  Value {
197
- Term { [ {js} ]; In <<nc.omega>>; Jacobian Jac; }
1643
+ Term { [ {js} ]; In <<nc.omega>>_EM; Jacobian Jac_Vol_EM; }
1644
+ }
1645
+ }
1646
+ }
1647
+ }
1648
+ {% endif %}
1649
+
1650
+ {% if dm.magnet.solve.thermal.solve_type %}
1651
+ { Name Thermal_T ; NameOfFormulation Thermal_T ; NameOfSystem Sys_The ;
1652
+ PostQuantity {
1653
+ // Temperature
1654
+ { Name T ;
1655
+ Value {
1656
+ Local { [ {T} ] ;
1657
+ In <<nc.omega>>_TH ; Jacobian Jac_Vol_TH ; }
1658
+ }
1659
+ }
1660
+
1661
+ { Name jOverJc ;
1662
+ Value {
1663
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1664
+ Term { [ source_current/SurfaceArea[] * 1/(criticalCurrentDensity[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] + 1) ] ;
1665
+ In <<nc.omega>>_TH ; Jacobian Jac_Vol_TH ; }
1666
+ {% else %}
1667
+ Term { [ source_current/SurfaceArea[] * 1/(criticalCurrentDensity[{T}] + 1) ] ;
1668
+ In <<nc.omega>>_TH ; Jacobian Jac_Vol_TH ; }
1669
+ {% endif %}
1670
+ }
1671
+ }
1672
+
1673
+ // Temperature average as integral quantity
1674
+ { Name T_avg ;
1675
+ Value {
1676
+ Integral { [ {T} / SurfaceArea[] ] ;
1677
+ In Region[ {<<nc.omega>><<nc.powered>>_TH{% if dm.magnet.geometry.thermal.with_iron_yoke %}, <<nc.omega>><<nc.iron>>{% endif %}{% if dm.magnet.geometry.thermal.with_wedges %}, <<nc.omega>><<nc.induced>>_TH{% endif %} } ] ; Jacobian Jac_Vol_TH ; Integration Int_conducting_TH; }
1678
+
1679
+ {% if not dm.magnet.geometry.thermal.use_TSA %}
1680
+ Integral { [ {T} / SurfaceArea[] ] ;
1681
+ In <<nc.omega>><<nc.insulator>>_TH ; Jacobian Jac_Vol_TH ; Integration Int_insulating_TH; }
1682
+ {% endif %}
1683
+ }
1684
+ }
1685
+
1686
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1687
+ { Name b_thermal ;
1688
+ Value {
1689
+ Local { [GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] ;
1690
+ In <<nc.omega>><<nc.powered>>_TH ; Jacobian Jac_Vol_TH ; }
198
1691
  }
199
1692
  }
200
- /*{ Name field_current;
201
- Value { Integral{[ Abs[CompZ[{js}]] ];
202
- In <<nc.omega>><<nc.powered>>; Jacobian Jac; Integration Int; }
203
- }
204
- }*/
1693
+ {% endif %}
205
1694
 
1695
+ { Name rho ;
1696
+ Value {
1697
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1698
+ Term { [ rho[{T}, GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] ] ;
1699
+ {% else %}
1700
+ Term { [ rho[{T}] ] ;
1701
+ {% endif %}
1702
+ In <<nc.omega>><<nc.powered>>_TH ; Jacobian Jac_Vol_TH ; }
1703
+ }
1704
+ }
206
1705
  }
207
1706
  }
1707
+
1708
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1709
+ { Name post_projection; NameOfFormulation Projection_EM_to_TH; NameOfSystem sys_Mag_projection;
1710
+ PostQuantity {
1711
+ { Name b_before_projection ;
1712
+ Value {
1713
+ Term { [Norm[{d a_before_projection}]] ;
1714
+ In <<nc.omega>><<nc.powered>>_TH ; Jacobian Jac_Vol_TH ; }
1715
+ }
1716
+ }
1717
+ { Name b_after_projection ;
1718
+ Value {
1719
+ Term { [GetVariable[ElementNum[], QuadraturePointIndex[]]{$Bnorm}] ;
1720
+ In <<nc.omega>><<nc.powered>>_TH ; Jacobian Jac_Vol_TH ; }
1721
+ }
1722
+ }
1723
+ }
1724
+ }
1725
+ {% endif %}
1726
+ {% endif %}
208
1727
  }
209
1728
 
210
- /*e = 1.e-5;
211
- h = 0.02;
212
- p2 = {0.25-e,h,0}; // horizontal cut through model, just above x-axis.*/
1729
+ {% if dm.magnet.solve.thermal.solve_type %}
1730
+ PostOperation PrintMaxTemp UsingPost Thermal_T {
1731
+ // Get maximum in bare region and store in register 1
1732
+ Print[ T, OnElementsOf <<nc.omega>>_TH, StoreMaxInRegister 1, Format Table,
1733
+ LastTimeStepOnly 1, File "dummy.txt", SendToServer "No"] ;
1734
+ }
1735
+ {% endif %}
213
1736
 
214
- p1 = {0,0,0};
215
- p2 = {<<rm.air_far_field.vol.radius_out>>,0,0};
216
1737
  PostOperation {
1738
+ { Name Dummy; NameOfPostProcessing {% if dm.magnet.solve.thermal.solve_type %} Thermal_T {% else %} MagSta_a_2D {% endif %};
1739
+ Operation { }
1740
+ }
1741
+
1742
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
217
1743
  { Name Map_a; NameOfPostProcessing MagSta_a_2D;
218
1744
  Operation {
219
- /* Echo[ Str["l=PostProcessing.NbViews-1;",
220
- "View[l].IntervalsType = 1;",
221
- "View[l].NbIso = 40;"],
222
- File "tmp.geo", LastTimeStepOnly] ; */
223
- {% for var_name, vol_name, file_ext in zip(dm.postproc.variables, dm.postproc.volumes, dm.postproc.file_exts) %}
224
- Print[ <<var_name>>, OnElementsOf <<vol_name>>, File "<<var_name>>_<<vol_name>>.<<file_ext>>"] ;
225
- {% endfor %}
226
- Print [ b, OnLine {{List[p1]}{List[p2]}} {1000}, Format SimpleTable, File "Center_line.csv"];
227
- //Print[ field_current[block_1_1_pos], OnGlobal, Format Table, File "field_current.txt" ];
228
- //Print[ b, OnLine{{List[p1]}{List[p2]}} {50}, File "by.pos" ];
1745
+ {% for var_name, vol_name in zip(dm.magnet.postproc.electromagnetics.variables, dm.magnet.postproc.electromagnetics.volumes) %}
1746
+ Print[ <<var_name>>, OnElementsOf <<vol_name>>_EM, File "<<var_name>>_<<vol_name>>.pos"] ;
1747
+ {% endfor %}
1748
+ //Print [ b, OnLine {{List[{0,0,0}]}{List[{<<rm_EM.air_far_field.vol.radius_out>>,0,0}]}} {1000}, Format SimpleTable, File "Center_line.csv"];
1749
+ }
1750
+ }
1751
+ {% endif %}
1752
+
1753
+ {% if dm.magnet.solve.thermal.solve_type %}
1754
+ {% if dm.magnet.solve.electromagnetics.solve_type %}
1755
+ { Name b_thermal; NameOfPostProcessing Thermal_T;
1756
+ Operation {
1757
+ Print[ b_thermal, OnElementsOf <<nc.omega>><<nc.powered>>_TH, File "b_thermal.pos"] ;
1758
+ }
1759
+ }
1760
+ { Name b_after_projection_pos; NameOfPostProcessing post_projection;
1761
+ Operation {
1762
+ Print[ b_before_projection, OnElementsOf <<nc.omega>><<nc.powered>>_TH, File "b_before_projection_gmsh.pos"] ;
1763
+ Print[ b_after_projection, OnElementsOf <<nc.omega>><<nc.powered>>_TH, File "b_after_projection.pos"] ;
1764
+ }
1765
+ }
1766
+ {% endif %}
1767
+
1768
+ { Name Map_T; NameOfPostProcessing Thermal_T;
1769
+ {% if dm.magnet.postproc.thermal.output_time_steps_pos > 1 %}
1770
+ {% set resample_step = (dm.magnet.solve.thermal.time_stepping.final_time - dm.magnet.solve.thermal.time_stepping.initial_time)/dm.magnet.postproc.thermal.output_time_steps_pos %}
1771
+ {% set last_time_step_only = 0 %}
1772
+ ResampleTime[<<dm.magnet.solve.thermal.time_stepping.initial_time>>, <<dm.magnet.solve.thermal.time_stepping.final_time>>, <<resample_step>>];
1773
+ {% elif (dm.magnet.postproc.thermal.output_time_steps_pos == 1 and not dm.magnet.postproc.thermal.save_pos_at_the_end) %}
1774
+ {% set last_time_step_only = 1 %}
1775
+ {% else %}
1776
+ {% set last_time_step_only = 0 %}
1777
+ {% endif %}
1778
+ Operation {
1779
+ {% for var_name, vol_name in zip(dm.magnet.postproc.thermal.variables, dm.magnet.postproc.thermal.volumes) %}
1780
+ Print[ <<var_name>>, OnElementsOf <<vol_name>>_TH, File "<<var_name>>_<<vol_name>>.pos", SendToServer "No", LastTimeStepOnly <<last_time_step_only>>, AppendToExistingFile <<last_time_step_only>> ] ;
1781
+ {% endfor %}
1782
+ //Print[ JoverJc, OnElementsOf <<nc.omega>><<nc.powered>>_TH, File "JoverJc_<<nc.omega>><<nc.powered>>.pos", SendToServer "No", LastTimeStepOnly <<last_time_step_only>>, AppendToExistingFile <<last_time_step_only>>, AtGaussPoints 4, Depth 0 ] ;
1783
+ //Print[ rho, OnElementsOf <<nc.omega>><<nc.powered>>_TH, File "rho_<<nc.omega>><<nc.powered>>.pos", SendToServer "No", LastTimeStepOnly <<last_time_step_only>>, AppendToExistingFile <<last_time_step_only>> ] ;
229
1784
  }
230
1785
  }
231
- }
232
1786
 
233
- /*DefineConstant[
234
- R_ = {"Analysis", Name "GetDP/1ResolutionChoices", Visible 0},
235
- C_ = {"-solve -v2", Name "GetDP/9ComputeCommand", Visible 0},
236
- P_ = {"", Name "GetDP/2PostOperationChoices", Visible 0}
237
- ];*/
1787
+ { Name T_avg; NameOfPostProcessing Thermal_T;
1788
+ {% if dm.magnet.postproc.thermal.output_time_steps_txt > 1 %}
1789
+ {% set resample_step = (dm.magnet.solve.thermal.time_stepping.final_time - dm.magnet.solve.thermal.time_stepping.initial_time)/dm.magnet.postproc.thermal.output_time_steps_txt %}
1790
+ {% set last_time_step_only = 0 %}
1791
+ ResampleTime[<<dm.magnet.solve.thermal.time_stepping.initial_time>>, <<dm.magnet.solve.thermal.time_stepping.final_time>>, <<resample_step>>];
1792
+ {% elif (dm.magnet.postproc.thermal.output_time_steps_txt == 1 and not dm.magnet.postproc.thermal.save_txt_at_the_end) %}
1793
+ {% set last_time_step_only = 1 %}
1794
+ {% else %}
1795
+ {% set last_time_step_only = 0 %}
1796
+ {% endif %}
1797
+ Operation {
1798
+ // writes pairs of time step and average temperature to file, one line for each time step
1799
+ {% for idx, half_turn in enumerate(rm_TH.powered['r1_a1'].vol.numbers + rm_TH.powered['r2_a1'].vol.numbers + rm_TH.powered['r1_a2'].vol.numbers + rm_TH.powered['r2_a2'].vol.numbers) %}
1800
+ Print[ T_avg[Region[<<half_turn>>]], OnGlobal, File "T_avg/T_avg_<<idx>>.txt", Format Table, SendToServer "No", LastTimeStepOnly <<last_time_step_only>>, AppendToExistingFile <<last_time_step_only>>] ;
1801
+ {% endfor %}
1802
+ }
1803
+ }
1804
+ {% endif %}
1805
+ }