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

1import os 

2import gmsh 

3import time 

4 

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 

14 

15 

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 

27 

28 self.GetDP_path = None 

29 self.geom_folder = None 

30 self.mesh_folder = None 

31 self.solution_folder = None 

32 

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) 

71 

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() 

81 

82 def pre_process(self, gui: bool = False): 

83 pass 

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 

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 

127 

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() 

133 

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 

145 

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) 

155 

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 

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() 

176 pp.ending_step(gui) 

177 return pp.postprocess_parameters 

178 

179 def plot_python(self): 

180 os.chdir(self.solution_folder) 

181 p = PlotPythonMultipole(self.fdm, self.fdm) 

182 p.plot_coil_wedges()