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.
- fiqus/MainFiQuS.py +290 -134
- fiqus/data/DataConductor.py +301 -301
- fiqus/data/DataFiQuS.py +128 -84
- fiqus/data/DataFiQuSCCT.py +150 -150
- fiqus/data/DataFiQuSConductor.py +84 -84
- fiqus/data/DataFiQuSConductorAC_Strand.py +565 -565
- fiqus/data/DataFiQuSMultipole.py +716 -42
- fiqus/data/DataFiQuSPancake3D.py +737 -278
- fiqus/data/DataMultipole.py +180 -15
- fiqus/data/DataRoxieParser.py +90 -51
- fiqus/data/DataSettings.py +121 -0
- fiqus/data/DataWindingsCCT.py +37 -37
- fiqus/data/RegionsModelFiQuS.py +18 -6
- fiqus/geom_generators/GeometryCCT.py +905 -905
- fiqus/geom_generators/GeometryConductorAC_Strand.py +1391 -1391
- fiqus/geom_generators/GeometryMultipole.py +1827 -227
- fiqus/geom_generators/GeometryPancake3D.py +316 -117
- fiqus/geom_generators/GeometryPancake3DUtils.py +549 -0
- fiqus/getdp_runners/RunGetdpCCT.py +4 -4
- fiqus/getdp_runners/RunGetdpConductorAC_Strand.py +201 -201
- fiqus/getdp_runners/RunGetdpMultipole.py +115 -42
- fiqus/getdp_runners/RunGetdpPancake3D.py +28 -6
- fiqus/mains/MainCCT.py +2 -2
- fiqus/mains/MainConductorAC_Strand.py +132 -132
- fiqus/mains/MainMultipole.py +113 -62
- fiqus/mains/MainPancake3D.py +63 -23
- fiqus/mesh_generators/MeshCCT.py +209 -209
- fiqus/mesh_generators/MeshConductorAC_Strand.py +656 -656
- fiqus/mesh_generators/MeshMultipole.py +1243 -181
- fiqus/mesh_generators/MeshPancake3D.py +275 -192
- fiqus/parsers/ParserCOND.py +825 -0
- fiqus/parsers/ParserDAT.py +16 -16
- fiqus/parsers/ParserGetDPOnSection.py +212 -212
- fiqus/parsers/ParserGetDPTimeTable.py +134 -134
- fiqus/parsers/ParserMSH.py +53 -53
- fiqus/parsers/ParserPOS.py +214 -214
- fiqus/parsers/ParserRES.py +142 -142
- fiqus/plotters/PlotPythonCCT.py +133 -133
- fiqus/plotters/PlotPythonConductorAC.py +855 -855
- fiqus/plotters/PlotPythonMultipole.py +18 -18
- fiqus/post_processors/PostProcessCCT.py +440 -440
- fiqus/post_processors/PostProcessConductorAC.py +49 -49
- fiqus/post_processors/PostProcessMultipole.py +353 -229
- fiqus/post_processors/PostProcessPancake3D.py +8 -13
- fiqus/pre_processors/PreProcessCCT.py +175 -175
- fiqus/pro_assemblers/ProAssembler.py +14 -6
- fiqus/pro_material_functions/ironBHcurves.pro +246 -246
- fiqus/pro_templates/combined/CCT_template.pro +274 -274
- fiqus/pro_templates/combined/ConductorAC_template.pro +1025 -1025
- fiqus/pro_templates/combined/Multipole_template.pro +1694 -126
- fiqus/pro_templates/combined/Pancake3D_template.pro +2294 -1103
- fiqus/pro_templates/combined/TSA_materials.pro +162 -0
- fiqus/pro_templates/combined/materials.pro +36 -18
- fiqus/utils/Utils.py +508 -110
- fiqus/utils/update_data_settings.py +33 -0
- fiqus-2024.12.1.dist-info/METADATA +132 -0
- fiqus-2024.12.1.dist-info/RECORD +84 -0
- {fiqus-2024.7.0.dist-info → fiqus-2024.12.1.dist-info}/WHEEL +1 -1
- tests/test_FiQuS.py +1 -1
- tests/test_geometry_generators.py +101 -2
- tests/test_mesh_generators.py +154 -1
- tests/test_solvers.py +115 -21
- tests/utils/fiqus_test_classes.py +85 -21
- tests/utils/generate_reference_files_ConductorAC.py +57 -57
- tests/utils/generate_reference_files_Pancake3D.py +4 -5
- tests/utils/helpers.py +97 -97
- fiqus-2024.7.0.dist-info/METADATA +0 -103
- fiqus-2024.7.0.dist-info/RECORD +0 -79
- {fiqus-2024.7.0.dist-info → fiqus-2024.12.1.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", "-
|
|
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
|
-
|
|
218
|
-
|
|
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,
|
|
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,
|
|
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
|
fiqus/mains/MainMultipole.py
CHANGED
|
@@ -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,
|
|
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.
|
|
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
|
-
|
|
40
|
-
self.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
gg.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
55
|
-
gu.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
gmsh.
|
|
59
|
-
|
|
60
|
-
|
|
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,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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,
|
|
94
|
-
|
|
95
|
-
self.
|
|
96
|
-
|
|
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,
|
|
106
|
-
|
|
107
|
-
self.
|
|
108
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
self.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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.
|
|
181
|
+
p = PlotPythonMultipole(self.fdm, self.fdm)
|
|
182
|
+
p.plot_coil_wedges()
|