Coverage for fiqus/mains/MainMultipole.py: 73%
153 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-12-27 02:39 +0100
« prev ^ index » next coverage.py v7.4.4, created at 2024-12-27 02:39 +0100
1import os
2import gmsh
3import time
5from fiqus.utils.Utils import GmshUtils
6from fiqus.utils.Utils import FilesAndFolders as Util
7from fiqus.data import DataFiQuS as dF
8from fiqus.geom_generators.GeometryMultipole import Geometry
9from fiqus.mesh_generators.MeshMultipole import Mesh
10from fiqus.getdp_runners.RunGetdpMultipole import RunGetdpMultipole
11from fiqus.getdp_runners.RunGetdpMultipole import AssignNaming
12from fiqus.post_processors.PostProcessMultipole import PostProcess
13from fiqus.plotters.PlotPythonMultipole import PlotPythonMultipole
16class MainMultipole:
17 def __init__(self, fdm: dF.FDM = None, rgd_path: str = None, verbose: bool = None):
18 """
19 Main class for working with simulations for multipole type magnets
20 :param fdm: FiQuS data model
21 :param rgd_path: ROXIE geometry data path
22 :param verbose: if True, more info is printed in the console
23 """
24 self.fdm = fdm
25 self.rgd = rgd_path
26 self.verbose = verbose
28 self.GetDP_path = None
29 self.geom_folder = None
30 self.mesh_folder = None
31 self.solution_folder = None
33 def force_symmetry(self):
34 fdm = self.fdm.__deepcopy__()
35 fdm.magnet.geometry.electromagnetics.symmetry = 'x'
36 return fdm
37 def generate_geometry(self, gui: bool = False):
38 geom = Util.read_data_from_yaml(self.rgd, dF.FiQuSGeometry)
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()
70 gg.ending_step(gui)
72 def load_geometry(self, gui: bool = False):
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()
82 def pre_process(self, gui: bool = False):
83 pass
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')
92 def mesh(self, gui: bool = False):
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()
125 mm.ending_step(gui)
126 return mm.mesh_parameters
128 def load_mesh(self, gui: bool = False):
129 gu = GmshUtils(self.geom_folder, self.verbose)
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()
134 def solve_and_postprocess_getdp(self, gui: bool = False):
135 an = AssignNaming(data=self.fdm)
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()
140 rg.assemblePro()
141 start_time = time.time()
142 rg.solve_and_postprocess()
143 rg.ending_step(gui)
144 return time.time() - start_time
146 def post_process_getdp(self, gui: bool = False):
147 an = AssignNaming(data=self.fdm)
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()
152 rg.assemblePro()
153 rg.postprocess()
154 rg.ending_step(gui)
156 def post_process_python(self, gui: bool = False):
157 if self.fdm.run.type == 'post_process_python_only':
158 an = AssignNaming(data=self.fdm)
159 data = an.data
160 else: data = self.fdm
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()
176 pp.ending_step(gui)
177 return pp.postprocess_parameters
179 def plot_python(self):
180 os.chdir(self.solution_folder)
181 p = PlotPythonMultipole(self.fdm, self.fdm)
182 p.plot_coil_wedges()