fiqus 2024.6.0__py3-none-any.whl → 2024.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 -840
  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.0.dist-info/METADATA +130 -0
  57. fiqus-2024.12.0.dist-info/RECORD +84 -0
  58. {fiqus-2024.6.0.dist-info → fiqus-2024.12.0.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.6.0.dist-info/METADATA +0 -103
  68. fiqus-2024.6.0.dist-info/RECORD +0 -79
  69. {fiqus-2024.6.0.dist-info → fiqus-2024.12.0.dist-info}/top_level.txt +0 -0
@@ -82,9 +82,13 @@ class Solve(Base):
82
82
  "solution"
83
83
  ][-_no_of_previous_solutions:]
84
84
 
85
+ if fdm.magnet.solve.time.start != parsed_init_res.solution["time_real"][0]:
86
+ raise ValueError(f"Initial time {fdm.magnet.solve.time.start} does not match with the initFromPrevious res file time {parsed_init_res.solution['time_real'][0]}.")
87
+
85
88
  self.res_file_without_previous_solutions = os.path.join(
86
89
  self.solution_folder, self.magnet_name + ".res"
87
90
  )
91
+
88
92
  ParserRES(self.res_file_without_previous_solutions, parsed_init_res)
89
93
 
90
94
  # Create pro file:
@@ -92,7 +96,7 @@ class Solve(Base):
92
96
 
93
97
  # Start GMSH:
94
98
  self.gu = GmshUtils(self.mesh_folder)
95
- self.gu.initialize()
99
+ self.gu.initialize(verbosity_Gmsh=fdm.run.verbosity_Gmsh)
96
100
 
97
101
  # Read regions model:
98
102
  self.rm = FilesAndFolders.read_data_from_yaml(self.regions_file, RegionsModel)
@@ -136,7 +140,12 @@ class Solve(Base):
136
140
  logger.info("Solving Pancake3D magnet has been started.")
137
141
  start_time = timeit.default_timer()
138
142
 
139
- getdpArguments = ["-v2", "-mat_mumps_cntl_1", "0", "-verbose", "6"]
143
+ getdpArguments = ["-v2", "-verbose", str(self.dm.run.verbosity_GetDP)]
144
+
145
+ if self.dm.magnet.solve.EECircuit.enable:
146
+ getdpArguments += ["-mat_mumps_cntl_1", "1e-6"]
147
+ else:
148
+ getdpArguments += ["-mat_mumps_cntl_1", "0"]
140
149
 
141
150
  if self.dm.magnet.solve.initFromPrevious:
142
151
  getdpArguments.extend(
@@ -178,11 +187,23 @@ class Solve(Base):
178
187
 
179
188
  # Add pre-processing argument
180
189
  getdpArguments.extend(["-pre", f"RESOLUTION_{self.solve.type}"])
190
+
181
191
 
182
192
  getdp_binary = self.GetDP_path
183
193
 
194
+ if self.solve.noOfMPITasks:
195
+ try:
196
+ import shutil
197
+ mpi_bin = shutil.which("mpiexec")
198
+ mpi_prefix = [mpi_bin, "-np", str(self.solve.noOfMPITasks)]
199
+ except:
200
+ logger.error("mpiexec not found. Running GetDP in serial mode.")
201
+ raise Exception("mpiexec not found. Running GetDP in serial mode.")
202
+ else:
203
+ mpi_prefix = []
204
+
184
205
  getdpProcess = subprocess.Popen(
185
- [getdp_binary, self.pro_file] + getdpArguments,
206
+ mpi_prefix + [getdp_binary, self.pro_file] + getdpArguments,
186
207
  stdout=subprocess.PIPE,
187
208
  stderr=subprocess.STDOUT,
188
209
  )
@@ -202,7 +223,7 @@ class Solve(Base):
202
223
  logger.error(parsedLine)
203
224
  logger.error("Solving Pancake3D magnet has failed.")
204
225
  raise Exception(parsedLine)
205
- elif "Critical" in line:
226
+ elif "Critical:" in line:
206
227
  parsedLine = re.sub(r"Critical\s*:\s*", "", line)
207
228
  if "Quench started!" in parsedLine:
208
229
  logger.critical(r" _____ _ ___ ____ ")
@@ -214,8 +235,9 @@ class Solve(Base):
214
235
  logger.critical("The coil has been quenched!")
215
236
  else:
216
237
  logger.critical(parsedLine)
217
- # else:
218
- # logger.info(line)
238
+ # this activates the debugging message mode
239
+ elif self.dm.run.verbosity_GetDP > 99:
240
+ logger.info(line)
219
241
 
220
242
  getdpProcess.wait()
221
243
 
fiqus/mains/MainCCT.py CHANGED
@@ -81,7 +81,7 @@ class MainCCT:
81
81
  os.chdir(self.solution_folder)
82
82
  gb = Generate_BREPs(fdm=self.fdm, verbose=self.verbose)
83
83
  gb.generate_regions_file()
84
- rg = RunGetdpCCT(fdm=self.fdm, settings=self.settings)
84
+ rg = RunGetdpCCT(fdm=self.fdm, GetDP_path=self.GetDP_path)
85
85
  rg.assemble_pro()
86
86
  start_time = time.time()
87
87
  rg.solve_and_postprocess(gui=gui)
@@ -93,7 +93,7 @@ class MainCCT:
93
93
  os.chdir(self.solution_folder)
94
94
  gb = Generate_BREPs(fdm=self.fdm, verbose=self.verbose)
95
95
  gb.generate_regions_file()
96
- rg = RunGetdpCCT(fdm=self.fdm, settings=self.settings)
96
+ rg = RunGetdpCCT(fdm=self.fdm, GetDP_path=self.GetDP_path)
97
97
  rg.assemble_pro()
98
98
  rg.postprocess(gui=gui)
99
99
  self.model_file = rg.model_file
@@ -1,133 +1,133 @@
1
- import os
2
-
3
- from fiqus.geom_generators.GeometryConductorAC_Strand import Geometry
4
- from fiqus.mesh_generators.MeshConductorAC_Strand import Mesh, StrandMesh
5
- from fiqus.getdp_runners.RunGetdpConductorAC_Strand import Solve
6
- from fiqus.post_processors.PostProcessConductorAC import PostProcess
7
- from fiqus.plotters.PlotPythonConductorAC import PlotPython
8
-
9
- class MainConductorAC_Strand:
10
- def __init__(self, fdm, inputs_folder_path='', outputs_folder_path='', verbose=True):
11
- """
12
- Main class for working with simulations for the Conductor AC model.
13
- :param fdm: FiQuS data model
14
- :param inputs_folder_path: full path to folder with input files
15
- :param verbose: if True, more info is printed in the console
16
- """
17
- self.verbose = verbose
18
- self.fdm = fdm
19
- self.inputs_folder_path = inputs_folder_path
20
- self.outputs_folder_path = outputs_folder_path
21
- self.GetDP_path = None
22
- self.geom_folder = None
23
- self.mesh_folder = None
24
- self.solution_folder = None
25
- self.model_file = None
26
- self.model_folder = None
27
-
28
-
29
- def generate_geometry(self, gui=False):
30
- """
31
- Generates the strand geometry.
32
- """
33
- os.chdir(self.geom_folder)
34
- g = Geometry(fdm=self.fdm, inputs_folder_path=self.inputs_folder_path, verbose=self.verbose)
35
- g.generate_strand_geometry(gui)
36
-
37
-
38
- def load_geometry(self, gui: bool = False):
39
- """
40
- Loads the previously generated geometry from the .brep file.
41
- """
42
- os.chdir(self.geom_folder)
43
- g = Geometry(fdm=self.fdm, inputs_folder_path=self.inputs_folder_path, verbose=self.verbose)
44
- g.load_conductor_geometry(gui)
45
- # self.model_file = g.model_file
46
-
47
- def pre_process(self, gui=False):
48
- pass
49
-
50
- def mesh(self, gui: bool = False):
51
- """
52
- Generates the mesh for the strand geometry.
53
- """
54
- os.chdir(self.mesh_folder)
55
-
56
- m = StrandMesh(fdm=self.fdm, verbose=self.verbose)
57
- m.generate_mesh(self.geom_folder)
58
- m.generate_cuts()
59
- m.generate_regions_file()
60
- m.save_mesh(gui)
61
-
62
- return {"test": 0}
63
-
64
- def load_mesh(self, gui=False):
65
- """
66
- Loads the previously generated mesh from the MSH file.
67
- """
68
- os.chdir(self.mesh_folder)
69
- m = Mesh(fdm=self.fdm, verbose=self.verbose)
70
- m.load_mesh(gui)
71
-
72
- # self.model_file = m.mesh_file
73
-
74
- def solve_and_postprocess_getdp(self, gui: bool = False):
75
- """
76
- Assembles the .pro-file from the template, then runs the simulation and the post-processing steps using GetDP.
77
- """
78
- os.chdir(self.solution_folder)
79
-
80
- s = Solve(self.fdm, self.GetDP_path, self.geom_folder, self.mesh_folder, self.verbose)
81
- s.read_excitation(inputs_folder_path=self.inputs_folder_path)
82
- s.get_solution_parameters_from_yaml(inputs_folder_path=self.inputs_folder_path)
83
- s.assemble_pro()
84
- s.run_getdp(solve = True, postOperation = True, gui = gui)
85
- s.cleanup()
86
-
87
- # def pre_process(self):
88
- # os.chdir(self.solution_folder)
89
-
90
- # s = Solve(self.fdm, self.GetDP_path, self.mesh_folder, self.verbose)
91
-
92
- def post_process_getdp(self, gui: bool = False):
93
- """
94
- Runs the post-processing steps trough GetDP.
95
- """
96
- os.chdir(self.solution_folder)
97
-
98
- s = Solve(self.fdm, self.GetDP_path, self.geom_folder, self.mesh_folder, self.verbose)
99
- s.read_excitation(inputs_folder_path=self.inputs_folder_path)
100
- s.assemble_pro()
101
- s.run_getdp(solve = False, postOperation = True, gui = gui)
102
- #
103
- def post_process_python(self, gui: bool = False):
104
- # os.chdir(self.solution_folder)
105
- postProc = PostProcess(self.fdm, self.outputs_folder_path)
106
- postProc.plot_instantaneous_loss()
107
-
108
- return {'test': 0}
109
-
110
- def batch_post_process_python(self, gui: bool = False):
111
- """
112
- Runs batch post-processing steps using Python.
113
- Used for gathering, analysing, comparing and plotting data from multiple simulations.
114
- """
115
- plotter = PlotPython(self.fdm, csv_filename=self.fdm.magnet.postproc.batch_postproc.postProc_csv, lossMap_gridData_folder=None, inputs_folder_path=self.inputs_folder_path, outputs_folder_path=self.outputs_folder_path)
116
-
117
- if self.fdm.magnet.postproc.batch_postproc.loss_map.produce_loss_map:
118
- # plotter.save_lossMap_gridData()
119
- # plotter.save_magnetization()
120
- plotter.create_lossMap()
121
-
122
- if self.fdm.magnet.postproc.batch_postproc.loss_map.cross_section.plot_cross_section:
123
- plotter.plot_lossMap_crossSection()
124
-
125
- if self.fdm.magnet.postproc.batch_postproc.loss_map.cross_section_sweep.animate_cross_section_sweep:
126
- plotter.animate_lossMap_crossSection()
127
-
128
- if self.fdm.magnet.postproc.batch_postproc.plot2d.produce_plot2d:
129
- plotter.plot2d()
130
-
131
-
132
- # def plot_python(self):
1
+ import os
2
+
3
+ from fiqus.geom_generators.GeometryConductorAC_Strand import Geometry
4
+ from fiqus.mesh_generators.MeshConductorAC_Strand import Mesh, StrandMesh
5
+ from fiqus.getdp_runners.RunGetdpConductorAC_Strand import Solve
6
+ from fiqus.post_processors.PostProcessConductorAC import PostProcess
7
+ from fiqus.plotters.PlotPythonConductorAC import PlotPython
8
+
9
+ class MainConductorAC_Strand:
10
+ def __init__(self, fdm, inputs_folder_path='', outputs_folder_path='', verbose=True):
11
+ """
12
+ Main class for working with simulations for the Conductor AC model.
13
+ :param fdm: FiQuS data model
14
+ :param inputs_folder_path: full path to folder with input files
15
+ :param verbose: if True, more info is printed in the console
16
+ """
17
+ self.verbose = verbose
18
+ self.fdm = fdm
19
+ self.inputs_folder_path = inputs_folder_path
20
+ self.outputs_folder_path = outputs_folder_path
21
+ self.GetDP_path = None
22
+ self.geom_folder = None
23
+ self.mesh_folder = None
24
+ self.solution_folder = None
25
+ self.model_file = None
26
+ self.model_folder = None
27
+
28
+
29
+ def generate_geometry(self, gui=False):
30
+ """
31
+ Generates the strand geometry.
32
+ """
33
+ os.chdir(self.geom_folder)
34
+ g = Geometry(fdm=self.fdm, inputs_folder_path=self.inputs_folder_path, verbose=self.verbose)
35
+ g.generate_strand_geometry(gui)
36
+
37
+
38
+ def load_geometry(self, gui: bool = False):
39
+ """
40
+ Loads the previously generated geometry from the .brep file.
41
+ """
42
+ os.chdir(self.geom_folder)
43
+ g = Geometry(fdm=self.fdm, inputs_folder_path=self.inputs_folder_path, verbose=self.verbose)
44
+ g.load_conductor_geometry(gui)
45
+ # self.model_file = g.model_file
46
+
47
+ def pre_process(self, gui=False):
48
+ pass
49
+
50
+ def mesh(self, gui: bool = False):
51
+ """
52
+ Generates the mesh for the strand geometry.
53
+ """
54
+ os.chdir(self.mesh_folder)
55
+
56
+ m = StrandMesh(fdm=self.fdm, verbose=self.verbose)
57
+ m.generate_mesh(self.geom_folder)
58
+ m.generate_cuts()
59
+ m.generate_regions_file()
60
+ m.save_mesh(gui)
61
+
62
+ return {"test": 0}
63
+
64
+ def load_mesh(self, gui=False):
65
+ """
66
+ Loads the previously generated mesh from the MSH file.
67
+ """
68
+ os.chdir(self.mesh_folder)
69
+ m = Mesh(fdm=self.fdm, verbose=self.verbose)
70
+ m.load_mesh(gui)
71
+
72
+ # self.model_file = m.mesh_file
73
+
74
+ def solve_and_postprocess_getdp(self, gui: bool = False):
75
+ """
76
+ Assembles the .pro-file from the template, then runs the simulation and the post-processing steps using GetDP.
77
+ """
78
+ os.chdir(self.solution_folder)
79
+
80
+ s = Solve(self.fdm, self.GetDP_path, self.geom_folder, self.mesh_folder, self.verbose)
81
+ s.read_excitation(inputs_folder_path=self.inputs_folder_path)
82
+ s.get_solution_parameters_from_yaml(inputs_folder_path=self.inputs_folder_path)
83
+ s.assemble_pro()
84
+ s.run_getdp(solve = True, postOperation = True, gui = gui)
85
+ s.cleanup()
86
+
87
+ # def pre_process(self):
88
+ # os.chdir(self.solution_folder)
89
+
90
+ # s = Solve(self.fdm, self.GetDP_path, self.mesh_folder, self.verbose)
91
+
92
+ def post_process_getdp(self, gui: bool = False):
93
+ """
94
+ Runs the post-processing steps trough GetDP.
95
+ """
96
+ os.chdir(self.solution_folder)
97
+
98
+ s = Solve(self.fdm, self.GetDP_path, self.geom_folder, self.mesh_folder, self.verbose)
99
+ s.read_excitation(inputs_folder_path=self.inputs_folder_path)
100
+ s.assemble_pro()
101
+ s.run_getdp(solve = False, postOperation = True, gui = gui)
102
+ #
103
+ def post_process_python(self, gui: bool = False):
104
+ # os.chdir(self.solution_folder)
105
+ postProc = PostProcess(self.fdm, self.outputs_folder_path)
106
+ postProc.plot_instantaneous_loss()
107
+
108
+ return {'test': 0}
109
+
110
+ def batch_post_process_python(self, gui: bool = False):
111
+ """
112
+ Runs batch post-processing steps using Python.
113
+ Used for gathering, analysing, comparing and plotting data from multiple simulations.
114
+ """
115
+ plotter = PlotPython(self.fdm, csv_filename=self.fdm.magnet.postproc.batch_postproc.postProc_csv, lossMap_gridData_folder=None, inputs_folder_path=self.inputs_folder_path, outputs_folder_path=self.outputs_folder_path)
116
+
117
+ if self.fdm.magnet.postproc.batch_postproc.loss_map.produce_loss_map:
118
+ # plotter.save_lossMap_gridData()
119
+ # plotter.save_magnetization()
120
+ plotter.create_lossMap()
121
+
122
+ if self.fdm.magnet.postproc.batch_postproc.loss_map.cross_section.plot_cross_section:
123
+ plotter.plot_lossMap_crossSection()
124
+
125
+ if self.fdm.magnet.postproc.batch_postproc.loss_map.cross_section_sweep.animate_cross_section_sweep:
126
+ plotter.animate_lossMap_crossSection()
127
+
128
+ if self.fdm.magnet.postproc.batch_postproc.plot2d.produce_plot2d:
129
+ plotter.plot2d()
130
+
131
+
132
+ # def plot_python(self):
133
133
  # pass
@@ -14,86 +14,129 @@ from fiqus.plotters.PlotPythonMultipole import PlotPythonMultipole
14
14
 
15
15
 
16
16
  class MainMultipole:
17
- def __init__(self, fdm: dF.FDM = None, sdm: dF.FiQuSSettings = None, rgd_path: str = None,
18
- verbose: bool = None):
17
+ def __init__(self, fdm: dF.FDM = None, rgd_path: str = None, verbose: bool = None):
19
18
  """
20
19
  Main class for working with simulations for multipole type magnets
21
20
  :param fdm: FiQuS data model
22
21
  :param rgd_path: ROXIE geometry data path
23
- :param sdm: settings data model
24
22
  :param verbose: if True, more info is printed in the console
25
23
  """
26
24
  self.fdm = fdm
27
- self.sett = sdm
28
25
  self.rgd = rgd_path
29
26
  self.verbose = verbose
30
27
 
31
- self.settings = None
28
+ self.GetDP_path = None
32
29
  self.geom_folder = None
33
30
  self.mesh_folder = None
34
31
  self.solution_folder = None
35
- self.model_file = None
36
32
 
33
+ def force_symmetry(self):
34
+ fdm = self.fdm.__deepcopy__()
35
+ fdm.magnet.geometry.electromagnetics.symmetry = 'x'
36
+ return fdm
37
37
  def generate_geometry(self, gui: bool = False):
38
38
  geom = Util.read_data_from_yaml(self.rgd, dF.FiQuSGeometry)
39
- gg = Geometry(data=self.fdm, geom=geom, sett=self.sett, geom_folder=self.geom_folder, verbose=self.verbose)
40
- self.model_file = gg.model_file
41
- gg.saveStrandPositions()
42
- if self.fdm.magnet.geometry.with_iron_yoke:
43
- gg.constructIronGeometry()
44
- gg.constructWedgeGeometry()
45
- gg.constructCoilGeometry()
46
- gg.buildDomains()
47
- gg.saveBoundaryRepresentationFile()
48
- gg.loadBoundaryRepresentationFile()
49
- gg.updateTags()
50
- gg.saveAuxiliaryFile()
39
+ fdm = self.force_symmetry() if 'solenoid' in geom.Roxie_Data.coil.coils[1].type else self.fdm # todo: this should be handled by pydantic
40
+ if self.fdm.magnet.geometry.plot_preview:
41
+ plotter = PlotPythonMultipole(geom, self.fdm)
42
+ plotter.plot_coil_wedges()
43
+ gg = Geometry(data=fdm, geom=geom, geom_folder=self.geom_folder, verbose=self.verbose)
44
+ gg.saveHalfTurnCornerPositions()
45
+ geometry_settings = {'EM': fdm.magnet.geometry.electromagnetics, 'TH': self.fdm.magnet.geometry.thermal}
46
+ geometry_type_list = []
47
+ if fdm.magnet.geometry.electromagnetics.create: geometry_type_list.append('EM')
48
+ if fdm.magnet.geometry.thermal.create: geometry_type_list.append('TH')
49
+ for geometry_type in geometry_type_list:
50
+ gg.saveStrandPositions(geometry_type)
51
+ if geometry_settings[geometry_type].with_iron_yoke:
52
+ gg.constructIronGeometry(geometry_settings[geometry_type].symmetry if geometry_type == 'EM' else 'none')
53
+ gg.constructCoilGeometry(geometry_type)
54
+ if geometry_settings[geometry_type].with_wedges:
55
+ gg.constructWedgeGeometry(geometry_settings[geometry_type].use_TSA if geometry_type == 'TH' else False)
56
+ gmsh.model.occ.synchronize()
57
+ if geometry_type == 'TH':
58
+ if geometry_settings[geometry_type].use_TSA:
59
+ gg.constructThinShells(geometry_settings[geometry_type].with_wedges)
60
+ else:
61
+ gg.constructInsulationGeometry()
62
+ gg.buildDomains(geometry_type, geometry_settings[geometry_type].symmetry if geometry_type == 'EM' else 'none')
63
+ if geometry_type == 'EM':
64
+ gg.fragment()
65
+ gg.saveBoundaryRepresentationFile(geometry_type)
66
+ gg.loadBoundaryRepresentationFile(geometry_type)
67
+ gg.updateTags(geometry_type, geometry_settings[geometry_type].symmetry if geometry_type == 'EM' else 'none')
68
+ gg.saveAuxiliaryFile(geometry_type)
69
+ gg.clear()
51
70
  gg.ending_step(gui)
52
71
 
53
72
  def load_geometry(self, gui: bool = False):
54
- gu = GmshUtils(self.geom_folder, self.verbose)
55
- gu.initialize()
56
- self.model_file = f"{os.path.join(self.geom_folder, self.fdm.general.magnet_name)}.brep"
57
- gmsh.option.setString('Geometry.OCCTargetUnit', 'M') # set units to meters
58
- gmsh.open(self.model_file)
59
- if gui:
60
- gu.launch_interactive_GUI()
73
+ pass
74
+ # gu = GmshUtils(self.geom_folder, self.verbose)
75
+ # gu.initialize(verbosity_Gmsh=self.fdm.run.verbosity_Gmsh)
76
+ # model_file = os.path.join(self.geom_folder, self.fdm.general.magnet_name)
77
+ # gmsh.option.setString(name='Geometry.OCCTargetUnit', value='M') # set units to meters
78
+ # gmsh.open(model_file + '_EM.brep')
79
+ # gmsh.open(model_file + '_TH.brep')
80
+ # if gui: gu.launch_interactive_GUI()
61
81
 
62
82
  def pre_process(self, gui: bool = False):
63
83
  pass
64
84
 
85
+ def load_geometry_for_mesh(self, run_type):
86
+ gu = GmshUtils(self.geom_folder, self.verbose)
87
+ gu.initialize(verbosity_Gmsh=self.fdm.run.verbosity_Gmsh)
88
+ model_file = os.path.join(self.geom_folder, self.fdm.general.magnet_name)
89
+ gmsh.option.setString(name='Geometry.OCCTargetUnit', value='M') # set units to meters
90
+ gmsh.open(model_file + f'_{run_type}.brep')
91
+
65
92
  def mesh(self, gui: bool = False):
66
- mm = Mesh(data=self.fdm, sett=self.sett, mesh_folder=self.mesh_folder, verbose=self.verbose)
67
- self.model_file = mm.model_file
68
- mm.loadAuxiliaryFile()
69
- mm.getIronCurvesTags()
70
- mm.defineMesh()
71
- mm.fragment()
72
- mm.createPhysicalGroups()
73
- mm.updateAuxiliaryFile()
74
- mm.assignRegionsTags()
75
- mm.saveRegionFile()
76
- mm.setMeshOptions()
77
- mm.generateMesh()
78
- mm.checkMeshQuality()
79
- mm.saveMeshFile()
93
+ mm = Mesh(data=self.fdm, mesh_folder=self.mesh_folder, verbose=self.verbose)
94
+ geom = Util.read_data_from_yaml(self.rgd, dF.FiQuSGeometry)
95
+ fdm = self.force_symmetry() if 'solenoid' in geom.Roxie_Data.coil.coils[1].type else self.fdm
96
+ geometry_settings = {'EM': fdm.magnet.geometry.electromagnetics, 'TH': self.fdm.magnet.geometry.thermal}
97
+ mesh_settings = {'EM': fdm.magnet.mesh.electromagnetics, 'TH': fdm.magnet.mesh.thermal}
98
+ mesh_type_list = []
99
+ if fdm.magnet.mesh.electromagnetics.create: mesh_type_list.append('EM')
100
+ if fdm.magnet.mesh.thermal.create: mesh_type_list.append('TH')
101
+ for physics_solved in mesh_type_list:
102
+ self.load_geometry_for_mesh(physics_solved)
103
+ if physics_solved == 'TH' and self.fdm.magnet.geometry.thermal.use_TSA:
104
+ mm.loadStrandPositions(physics_solved)
105
+ mm.loadAuxiliaryFile(physics_solved)
106
+ if geometry_settings[physics_solved].with_iron_yoke:
107
+ mm.getIronCurvesTags()
108
+ mm.defineMesh(geometry_settings[physics_solved], mesh_settings[physics_solved], physics_solved)
109
+ mm.createPhysicalGroups(geometry_settings[physics_solved])
110
+ mm.updateAuxiliaryFile(physics_solved)
111
+ if geometry_settings[physics_solved].dict().get('use_TSA', False):
112
+ mm.rearrangeThinShellsData()
113
+ mm.assignRegionsTags(geometry_settings[physics_solved], mesh_settings[physics_solved])
114
+ mm.saveRegionFile(physics_solved)
115
+ mm.setMeshOptions(physics_solved)
116
+ mm.generateMesh()
117
+ mm.checkMeshQuality()
118
+ mm.saveMeshFile(physics_solved)
119
+ if geometry_settings[physics_solved].dict().get('use_TSA', False):
120
+ mm.saveClosestNeighboursList()
121
+ if self.fdm.magnet.mesh.thermal.isothermal_conductors: mm.selectMeshNodes(elements='conductors')
122
+ if self.fdm.magnet.geometry.thermal.with_wedges and self.fdm.magnet.mesh.thermal.isothermal_wedges: mm.selectMeshNodes(elements='wedges')
123
+ mm.saveRegionCoordinateFile(physics_solved)
124
+ mm.clear()
80
125
  mm.ending_step(gui)
81
126
  return mm.mesh_parameters
82
127
 
83
128
  def load_mesh(self, gui: bool = False):
84
129
  gu = GmshUtils(self.geom_folder, self.verbose)
85
- gu.initialize()
86
- self.model_file = f"{os.path.join(self.mesh_folder, self.fdm.general.magnet_name)}.msh"
87
- gmsh.open(self.model_file)
88
- if gui:
89
- gu.launch_interactive_GUI()
130
+ gu.initialize(verbosity_Gmsh=self.fdm.run.verbosity_Gmsh)
131
+ gmsh.open(f"{os.path.join(self.mesh_folder, self.fdm.general.magnet_name)}.msh")
132
+ if gui: gu.launch_interactive_GUI()
90
133
 
91
134
  def solve_and_postprocess_getdp(self, gui: bool = False):
92
135
  an = AssignNaming(data=self.fdm)
93
- rg = RunGetdpMultipole(data=an, sett=self.sett, solution_folder=self.solution_folder, settings=self.settings,
94
- verbose=self.verbose)
95
- self.model_file = rg.model_file
96
- rg.loadRegionFile()
136
+ rg = RunGetdpMultipole(data=an, solution_folder=self.solution_folder, GetDP_path=self.GetDP_path, verbose=self.verbose)
137
+ rg.loadRegionFiles()
138
+ if self.fdm.magnet.solve.thermal.solve_type and self.fdm.magnet.geometry.thermal.use_TSA:
139
+ rg.loadRegionCoordinateFile()
97
140
  rg.assemblePro()
98
141
  start_time = time.time()
99
142
  rg.solve_and_postprocess()
@@ -102,10 +145,10 @@ class MainMultipole:
102
145
 
103
146
  def post_process_getdp(self, gui: bool = False):
104
147
  an = AssignNaming(data=self.fdm)
105
- rg = RunGetdpMultipole(data=an, sett=self.sett, solution_folder=self.solution_folder, settings=self.settings,
106
- verbose=self.verbose)
107
- self.model_file = rg.model_file
108
- rg.loadRegionFile()
148
+ rg = RunGetdpMultipole(data=an, solution_folder=self.solution_folder, GetDP_path=self.GetDP_path, verbose=self.verbose)
149
+ rg.loadRegionFiles()
150
+ if self.fdm.magnet.solve.thermal.solve_type and self.fdm.magnet.geometry.thermal.use_TSA:
151
+ rg.loadRegionCoordinateFile()
109
152
  rg.assemblePro()
110
153
  rg.postprocess()
111
154
  rg.ending_step(gui)
@@ -114,18 +157,26 @@ class MainMultipole:
114
157
  if self.fdm.run.type == 'post_process_python_only':
115
158
  an = AssignNaming(data=self.fdm)
116
159
  data = an.data
117
- else:
118
- data = self.fdm
119
- pp = PostProcess(data=data, sett=self.sett, solution_folder=self.solution_folder, verbose=self.verbose)
120
- self.model_file = pp.model_file
121
- pp.loadStrandPositions()
122
- if self.fdm.magnet.postproc.plot_all:
123
- pp.loadHalfTurnCornerPositions()
124
- pp.postProcess()
160
+ else: data = self.fdm
161
+
162
+ run_types = []
163
+ if self.fdm.magnet.solve.electromagnetics.solve_type: run_types.append('EM')
164
+ if self.fdm.magnet.solve.thermal.solve_type: run_types.append('TH')
165
+ pp_settings = {'EM': self.fdm.magnet.postproc.electromagnetics, 'TH': self.fdm.magnet.postproc.thermal}
166
+ pp = PostProcess(data=data, solution_folder=self.solution_folder, verbose=self.verbose)
167
+ for run_type in run_types:
168
+ pp.prepare_settings(pp_settings[run_type])
169
+ pp.loadStrandPositions(run_type)
170
+ pp.loadAuxiliaryFile(run_type)
171
+ if pp_settings[run_type].plot_all != 'False': pp.loadHalfTurnCornerPositions()
172
+ if pp_settings[run_type].dict().get('take_average_conductor_temperature', False): pp.loadRegionFile()
173
+ pp.postProcess(pp_settings[run_type])
174
+ if run_type == 'EM' and self.fdm.magnet.geometry.electromagnetics.symmetry != 'none': pp.completeMap2d()
175
+ pp.clear()
125
176
  pp.ending_step(gui)
126
177
  return pp.postprocess_parameters
127
178
 
128
179
  def plot_python(self):
129
180
  os.chdir(self.solution_folder)
130
- p = PlotPythonMultipole(self.fdm)
131
- p.dummy_plot_func()
181
+ p = PlotPythonMultipole(self.fdm, self.fdm)
182
+ p.plot_coil_wedges()