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
@@ -11,7 +11,6 @@ import matplotlib
11
11
  import matplotlib.pyplot as plt
12
12
 
13
13
  from fiqus.mains.MainPancake3D import Base
14
- import fiqus.data.DataFiQuSPancake3D as dm
15
14
  from fiqus.utils.Utils import GmshUtils
16
15
  from fiqus.parsers.ParserGetDPTimeTable import ParserGetDPTimeTable
17
16
  from fiqus.parsers.ParserGetDPOnSection import ParserGetDPOnSection
@@ -217,22 +216,18 @@ class Postprocess(Base):
217
216
  filePath = os.path.join(
218
217
  self.solution_folder, timeSeriesPlot.fileName + "-TimeTableFormat.csv"
219
218
  )
220
- # check if this is Pancake3DPositionInCoordinates or not:
221
- if isinstance(
222
- timeSeriesPlot, dm.Pancake3DPostprocessTimeSeriesPlotPositionRequired
223
- ):
224
- if isinstance(
225
- timeSeriesPlot.position, dm.Pancake3DPositionInCoordinates
226
- ):
219
+
220
+ if hasattr(timeSeriesPlot, 'position'):
221
+ if hasattr(timeSeriesPlot.position, 'turnNumber'):
227
222
  title = (
228
- f"{timeSeriesPlot.quantityProperName} at"
229
- f" ({timeSeriesPlot.position.x}, {timeSeriesPlot.position.y},"
230
- f" {timeSeriesPlot.position.z})"
223
+ f"{timeSeriesPlot.quantityProperName} at turn"
224
+ f" {timeSeriesPlot.position.turnNumber}"
231
225
  )
232
226
  else:
233
227
  title = (
234
- f"{timeSeriesPlot.quantityProperName} at turn"
235
- f" {timeSeriesPlot.position.turnNumber}"
228
+ f"{timeSeriesPlot.quantityProperName} at"
229
+ f" ({timeSeriesPlot.position.x}, {timeSeriesPlot.position.y},"
230
+ f" {timeSeriesPlot.position.z})"
236
231
  )
237
232
  else:
238
233
  title = f"{timeSeriesPlot.quantityProperName}"
@@ -1,175 +1,175 @@
1
- import math
2
- import os
3
- import timeit
4
- import json
5
- import gmsh
6
- import numpy as np
7
- from fiqus.utils.Utils import FilesAndFolders as uff
8
- from fiqus.utils.Utils import GmshUtils
9
- from fiqus.data.DataWindingsCCT import WindingsInformation # for volume information
10
-
11
-
12
- class Pre_Process:
13
- def __init__(self, fdm, verbose=True):
14
- """
15
- Class to preparing brep files by adding terminals.
16
- :param fdm: FiQuS data model
17
- :param verbose: If True more information is printed in python console.
18
- """
19
- self.cctdm = fdm.magnet
20
- self.model_folder = os.path.join(os.getcwd())
21
- self.magnet_name = fdm.general.magnet_name
22
- winding_info_file = os.path.join(self.model_folder, f'{self.magnet_name}.wi')
23
- self.cctwi = uff.read_data_from_yaml(winding_info_file, WindingsInformation)
24
- self.verbose = verbose
25
- self.gu = GmshUtils(self.model_folder, self.verbose)
26
- self.gu.initialize()
27
-
28
- def calculate_normals(self, gui=False):
29
- """
30
- Calculates normals for the cct channel directions, i.e. along winding direction, along radial direction of the former (height) and along axial direction (width). Normals are saved to a .json
31
- file and used later for post-processing of magnetic field into components along channel length, height and width. Note that this function does not give the correct 'sign of normals', i.e.
32
- normals facing inwards or outwards of the surface are not properly distinguished. The normals along the length are not reliable and only along the height and width are used for calculations and
33
- the field along the length is taken as a remaining field.
34
- This function needs full geom_generators .brep file and volume information files (.vi) for each individual powered volume.
35
- :param gui: if True, the gmsh graphical user interface is shown at the end and normals are displayed as a view
36
- :return: Nothing, a file for each powered geom_generators brep is
37
- """
38
- if self.verbose:
39
- print('Calculating Normals Started')
40
- start_time = timeit.default_timer()
41
- gmsh.open(os.path.join(self.model_folder, f'{self.magnet_name}.brep'))
42
-
43
- def _calc_normals_dir(tags_for_normals_in, surfs_idx, surfs_scale):
44
- v_to_suf = [[0, 1, 2, 3], [0, 1, 5, 4], [4, 5, 6, 7], [3, 7, 6, 2], [0, 3, 7, 4], [1, 5, 6, 2]]
45
- norm_e_x = [] # normal along x of volume
46
- norm_e_y = []
47
- norm_e_z = []
48
- norm_dict = {}
49
- normals_view = [] # this remains an empty list if view is False
50
- coor_e_x = [] # coordinate x of the center of volume
51
- coor_e_y = []
52
- coor_e_z = []
53
- for vol_tag in tags_for_normals_in:
54
- all_surf_tags = gmsh.model.getAdjacencies(3, vol_tag)[1]
55
- surf_tags = [all_surf_tags[index] for index in surfs_idx]
56
- norm = []
57
- node_coord = []
58
- vol_line_tags = []
59
- for surf_tag in all_surf_tags:
60
- line_tags_new = gmsh.model.getAdjacencies(2, surf_tag)[1]
61
- for line_tag in line_tags_new:
62
- if line_tag not in vol_line_tags:
63
- vol_line_tags.append(line_tag)
64
- point_tags = []
65
- for line_tag in vol_line_tags:
66
- point_tags_new = gmsh.model.getAdjacencies(1, line_tag)[1]
67
- for point_tag in point_tags_new:
68
- if point_tag not in point_tags:
69
- point_tags.append(int(point_tag))
70
- for surf_i, surf_tag, scale in zip(surfs_idx, surf_tags, surfs_scale):
71
- p_idx = v_to_suf[surf_i]
72
- s_node_coord = []
73
- for p_i in p_idx:
74
- xmin, ymin, zmin, xmax, ymax, zmax = gmsh.model.occ.getBoundingBox(0, point_tags[p_i])
75
- s_node_coord.append((xmin + xmax) / 2)
76
- s_node_coord.append((ymin + ymax) / 2)
77
- s_node_coord.append((zmin + zmax) / 2)
78
- parametricCoord = gmsh.model.getParametrization(2, surf_tag, s_node_coord)
79
- s_norm = gmsh.model.getNormal(surf_tag, parametricCoord)
80
- norm.extend(scale*s_norm)
81
- node_coord.extend(s_node_coord)
82
- coor_s_x = [] # coordinates surface x
83
- coor_s_y = []
84
- coor_s_z = []
85
- norm_s_x = [] # normals surface x
86
- norm_s_y = []
87
- norm_s_z = []
88
-
89
- for i in range(0, len(node_coord), 3):
90
- coor_s_x.append(node_coord[i])
91
- coor_s_y.append(node_coord[i+1])
92
- coor_s_z.append(node_coord[i+2])
93
- norm_s_x.append(norm[i])
94
- norm_s_y.append(norm[i+1])
95
- norm_s_z.append(norm[i+2])
96
-
97
- coor_e_x.append(np.mean(coor_s_x))
98
- coor_e_y.append(np.mean(coor_s_y))
99
- coor_e_z.append(np.mean(coor_s_z))
100
- # norm_e_x.append(np.mean(norm_s_x))
101
- # norm_e_y.append(np.mean(norm_s_y))
102
- # norm_e_z.append(np.mean(norm_s_z))
103
-
104
- # norm_e_x.append(np.sqrt(np.sum(np.square(norm_s_x)))/(2*np.sqrt(2)))
105
- # norm_e_y.append(np.sqrt(np.sum(np.square(norm_s_y)))/(2*np.sqrt(2)))
106
- # norm_e_z.append(np.sqrt(np.sum(np.square(norm_s_z)))/(2*np.sqrt(2)))
107
- v_x = np.sum(norm_s_x)
108
- v_y = np.sum(norm_s_y)
109
- v_z = np.sum(norm_s_z)
110
- ampl = math.sqrt(v_x**2 + v_y**2 + v_z**2)
111
-
112
- norm_e_x.append(v_x/ampl)
113
- norm_e_y.append(v_y/ampl)
114
- norm_e_z.append(v_z/ampl)
115
-
116
- for i in range(len(coor_e_x)):
117
- normals_view.append(coor_e_x[i])
118
- normals_view.append(coor_e_y[i])
119
- normals_view.append(coor_e_z[i])
120
- normals_view.append(norm_e_x[i])
121
- normals_view.append(norm_e_y[i])
122
- normals_view.append(norm_e_z[i])
123
- norm_dict['x'] = coor_e_x
124
- norm_dict['y'] = coor_e_y
125
- norm_dict['z'] = coor_e_z
126
- norm_dict['n_x'] = norm_e_x
127
- norm_dict['n_y'] = norm_e_y
128
- norm_dict['n_z'] = norm_e_z
129
- return norm_dict, normals_view
130
- """
131
- This is helper function called in a loop below.
132
- """
133
- max_tag = 0
134
- for f_name in self.cctwi.w_names+self.cctwi.f_names:
135
- vol_tags = json.load(open(os.path.join(self.model_folder, f'{f_name}.vi')))
136
- export_tags = vol_tags['export']
137
- tags_for_normals = [e + max_tag for e in export_tags]
138
- max_tag = np.max(vol_tags['all']) + max_tag
139
- surfs_idx_l = [0, 2] # along length of the former groove
140
- if f_name in self.cctwi.w_names:
141
- surfs_scale_l = [1, 1]
142
- elif f_name in self.cctwi.f_names:
143
- surfs_scale_l = [1, -1] # change direction for fqpl
144
- norm_l, norm_view_l = _calc_normals_dir(tags_for_normals, surfs_idx_l, surfs_scale_l)
145
- surfs_idx_h = [1, 3] # along height of the former groove
146
- surfs_scale_h = [1, -1]
147
- norm_h, norm_view_h = _calc_normals_dir(tags_for_normals, surfs_idx_h, surfs_scale_h)
148
- surfs_idx_w = [4, 5] # along width of the former groove
149
- surfs_scale_w = [1, -1]
150
- norm_w, norm_view_w = _calc_normals_dir(tags_for_normals, surfs_idx_w, surfs_scale_w)
151
- normals_dict = {'normals_l': norm_l, 'normals_h': norm_h, 'normals_w': norm_w}
152
- json.dump(normals_dict, open(f"{os.path.join(self.model_folder, f_name)}.normals", 'w'))
153
- if gui:
154
- normals_all = [norm_view_l, norm_view_h, norm_view_w]
155
- self.__add_normals_view(f_name, normals_all)
156
- if self.verbose:
157
- print(f'Calculating Normals Took {timeit.default_timer() - start_time:.2f} s')
158
- if gui:
159
- self.gu.launch_interactive_GUI()
160
-
161
- @staticmethod
162
- def __add_normals_view(name, normals_all, norm_list=[0, 1, 2]):
163
- """
164
- THis adds new view in gmsh.
165
- :param name: name of view
166
- :param normals_all: dictionary with normals
167
- :param norm_list: which normals to plot. Default is: [0, 1, 2] corresponds to [n_l, n_h, n_w]. If this array is shorter the corresponding normals are skipped in views.
168
- :return:
169
- """
170
- norm_names_all = [f"{name}_n_l", f"{name}_n_h", f"{name}_n_w"]
171
- norm_names = [norm_names_all[index] for index in norm_list]
172
- normals = [normals_all[index] for index in norm_list]
173
- for view_name, view_data in zip(norm_names, normals):
174
- gmsh.view.addListData(gmsh.view.add(view_name), "VP", len(view_data) // 6, view_data)
175
- gmsh.model.occ.synchronize()
1
+ import math
2
+ import os
3
+ import timeit
4
+ import json
5
+ import gmsh
6
+ import numpy as np
7
+ from fiqus.utils.Utils import FilesAndFolders as uff
8
+ from fiqus.utils.Utils import GmshUtils
9
+ from fiqus.data.DataWindingsCCT import WindingsInformation # for volume information
10
+
11
+
12
+ class Pre_Process:
13
+ def __init__(self, fdm, verbose=True):
14
+ """
15
+ Class to preparing brep files by adding terminals.
16
+ :param fdm: FiQuS data model
17
+ :param verbose: If True more information is printed in python console.
18
+ """
19
+ self.cctdm = fdm.magnet
20
+ self.model_folder = os.path.join(os.getcwd())
21
+ self.magnet_name = fdm.general.magnet_name
22
+ winding_info_file = os.path.join(self.model_folder, f'{self.magnet_name}.wi')
23
+ self.cctwi = uff.read_data_from_yaml(winding_info_file, WindingsInformation)
24
+ self.verbose = verbose
25
+ self.gu = GmshUtils(self.model_folder, self.verbose)
26
+ self.gu.initialize()
27
+
28
+ def calculate_normals(self, gui=False):
29
+ """
30
+ Calculates normals for the cct channel directions, i.e. along winding direction, along radial direction of the former (height) and along axial direction (width). Normals are saved to a .json
31
+ file and used later for post-processing of magnetic field into components along channel length, height and width. Note that this function does not give the correct 'sign of normals', i.e.
32
+ normals facing inwards or outwards of the surface are not properly distinguished. The normals along the length are not reliable and only along the height and width are used for calculations and
33
+ the field along the length is taken as a remaining field.
34
+ This function needs full geom_generators .brep file and volume information files (.vi) for each individual powered volume.
35
+ :param gui: if True, the gmsh graphical user interface is shown at the end and normals are displayed as a view
36
+ :return: Nothing, a file for each powered geom_generators brep is
37
+ """
38
+ if self.verbose:
39
+ print('Calculating Normals Started')
40
+ start_time = timeit.default_timer()
41
+ gmsh.open(os.path.join(self.model_folder, f'{self.magnet_name}.brep'))
42
+
43
+ def _calc_normals_dir(tags_for_normals_in, surfs_idx, surfs_scale):
44
+ v_to_suf = [[0, 1, 2, 3], [0, 1, 5, 4], [4, 5, 6, 7], [3, 7, 6, 2], [0, 3, 7, 4], [1, 5, 6, 2]]
45
+ norm_e_x = [] # normal along x of volume
46
+ norm_e_y = []
47
+ norm_e_z = []
48
+ norm_dict = {}
49
+ normals_view = [] # this remains an empty list if view is False
50
+ coor_e_x = [] # coordinate x of the center of volume
51
+ coor_e_y = []
52
+ coor_e_z = []
53
+ for vol_tag in tags_for_normals_in:
54
+ all_surf_tags = gmsh.model.getAdjacencies(3, vol_tag)[1]
55
+ surf_tags = [all_surf_tags[index] for index in surfs_idx]
56
+ norm = []
57
+ node_coord = []
58
+ vol_line_tags = []
59
+ for surf_tag in all_surf_tags:
60
+ line_tags_new = gmsh.model.getAdjacencies(2, surf_tag)[1]
61
+ for line_tag in line_tags_new:
62
+ if line_tag not in vol_line_tags:
63
+ vol_line_tags.append(line_tag)
64
+ point_tags = []
65
+ for line_tag in vol_line_tags:
66
+ point_tags_new = gmsh.model.getAdjacencies(1, line_tag)[1]
67
+ for point_tag in point_tags_new:
68
+ if point_tag not in point_tags:
69
+ point_tags.append(int(point_tag))
70
+ for surf_i, surf_tag, scale in zip(surfs_idx, surf_tags, surfs_scale):
71
+ p_idx = v_to_suf[surf_i]
72
+ s_node_coord = []
73
+ for p_i in p_idx:
74
+ xmin, ymin, zmin, xmax, ymax, zmax = gmsh.model.occ.getBoundingBox(0, point_tags[p_i])
75
+ s_node_coord.append((xmin + xmax) / 2)
76
+ s_node_coord.append((ymin + ymax) / 2)
77
+ s_node_coord.append((zmin + zmax) / 2)
78
+ parametricCoord = gmsh.model.getParametrization(2, surf_tag, s_node_coord)
79
+ s_norm = gmsh.model.getNormal(surf_tag, parametricCoord)
80
+ norm.extend(scale*s_norm)
81
+ node_coord.extend(s_node_coord)
82
+ coor_s_x = [] # coordinates surface x
83
+ coor_s_y = []
84
+ coor_s_z = []
85
+ norm_s_x = [] # normals surface x
86
+ norm_s_y = []
87
+ norm_s_z = []
88
+
89
+ for i in range(0, len(node_coord), 3):
90
+ coor_s_x.append(node_coord[i])
91
+ coor_s_y.append(node_coord[i+1])
92
+ coor_s_z.append(node_coord[i+2])
93
+ norm_s_x.append(norm[i])
94
+ norm_s_y.append(norm[i+1])
95
+ norm_s_z.append(norm[i+2])
96
+
97
+ coor_e_x.append(np.mean(coor_s_x))
98
+ coor_e_y.append(np.mean(coor_s_y))
99
+ coor_e_z.append(np.mean(coor_s_z))
100
+ # norm_e_x.append(np.mean(norm_s_x))
101
+ # norm_e_y.append(np.mean(norm_s_y))
102
+ # norm_e_z.append(np.mean(norm_s_z))
103
+
104
+ # norm_e_x.append(np.sqrt(np.sum(np.square(norm_s_x)))/(2*np.sqrt(2)))
105
+ # norm_e_y.append(np.sqrt(np.sum(np.square(norm_s_y)))/(2*np.sqrt(2)))
106
+ # norm_e_z.append(np.sqrt(np.sum(np.square(norm_s_z)))/(2*np.sqrt(2)))
107
+ v_x = np.sum(norm_s_x)
108
+ v_y = np.sum(norm_s_y)
109
+ v_z = np.sum(norm_s_z)
110
+ ampl = math.sqrt(v_x**2 + v_y**2 + v_z**2)
111
+
112
+ norm_e_x.append(v_x/ampl)
113
+ norm_e_y.append(v_y/ampl)
114
+ norm_e_z.append(v_z/ampl)
115
+
116
+ for i in range(len(coor_e_x)):
117
+ normals_view.append(coor_e_x[i])
118
+ normals_view.append(coor_e_y[i])
119
+ normals_view.append(coor_e_z[i])
120
+ normals_view.append(norm_e_x[i])
121
+ normals_view.append(norm_e_y[i])
122
+ normals_view.append(norm_e_z[i])
123
+ norm_dict['x'] = coor_e_x
124
+ norm_dict['y'] = coor_e_y
125
+ norm_dict['z'] = coor_e_z
126
+ norm_dict['n_x'] = norm_e_x
127
+ norm_dict['n_y'] = norm_e_y
128
+ norm_dict['n_z'] = norm_e_z
129
+ return norm_dict, normals_view
130
+ """
131
+ This is helper function called in a loop below.
132
+ """
133
+ max_tag = 0
134
+ for f_name in self.cctwi.w_names+self.cctwi.f_names:
135
+ vol_tags = json.load(open(os.path.join(self.model_folder, f'{f_name}.vi')))
136
+ export_tags = vol_tags['export']
137
+ tags_for_normals = [e + max_tag for e in export_tags]
138
+ max_tag = np.max(vol_tags['all']) + max_tag
139
+ surfs_idx_l = [0, 2] # along length of the former groove
140
+ if f_name in self.cctwi.w_names:
141
+ surfs_scale_l = [1, 1]
142
+ elif f_name in self.cctwi.f_names:
143
+ surfs_scale_l = [1, -1] # change direction for fqpl
144
+ norm_l, norm_view_l = _calc_normals_dir(tags_for_normals, surfs_idx_l, surfs_scale_l)
145
+ surfs_idx_h = [1, 3] # along height of the former groove
146
+ surfs_scale_h = [1, -1]
147
+ norm_h, norm_view_h = _calc_normals_dir(tags_for_normals, surfs_idx_h, surfs_scale_h)
148
+ surfs_idx_w = [4, 5] # along width of the former groove
149
+ surfs_scale_w = [1, -1]
150
+ norm_w, norm_view_w = _calc_normals_dir(tags_for_normals, surfs_idx_w, surfs_scale_w)
151
+ normals_dict = {'normals_l': norm_l, 'normals_h': norm_h, 'normals_w': norm_w}
152
+ json.dump(normals_dict, open(f"{os.path.join(self.model_folder, f_name)}.normals", 'w'))
153
+ if gui:
154
+ normals_all = [norm_view_l, norm_view_h, norm_view_w]
155
+ self.__add_normals_view(f_name, normals_all)
156
+ if self.verbose:
157
+ print(f'Calculating Normals Took {timeit.default_timer() - start_time:.2f} s')
158
+ if gui:
159
+ self.gu.launch_interactive_GUI()
160
+
161
+ @staticmethod
162
+ def __add_normals_view(name, normals_all, norm_list=[0, 1, 2]):
163
+ """
164
+ THis adds new view in gmsh.
165
+ :param name: name of view
166
+ :param normals_all: dictionary with normals
167
+ :param norm_list: which normals to plot. Default is: [0, 1, 2] corresponds to [n_l, n_h, n_w]. If this array is shorter the corresponding normals are skipped in views.
168
+ :return:
169
+ """
170
+ norm_names_all = [f"{name}_n_l", f"{name}_n_h", f"{name}_n_w"]
171
+ norm_names = [norm_names_all[index] for index in norm_list]
172
+ normals = [normals_all[index] for index in norm_list]
173
+ for view_name, view_data in zip(norm_names, normals):
174
+ gmsh.view.addListData(gmsh.view.add(view_name), "VP", len(view_data) // 6, view_data)
175
+ gmsh.model.occ.synchronize()
@@ -1,6 +1,7 @@
1
1
  from fiqus.pro_templates import combined
2
2
  from jinja2 import Environment, FileSystemLoader
3
3
  import numpy as np
4
+ import os
4
5
 
5
6
 
6
7
  class ASS_PRO:
@@ -16,26 +17,33 @@ class ASS_PRO:
16
17
  else:
17
18
  self.naming_conv = naming_conv
18
19
 
19
- def assemble_combined_pro(self, template, rm, dm, rc=None, mf=None, ps=None, ed=None, mp=None, BH_curves_path: str = ''):
20
+ def assemble_combined_pro(self, template, dm, rm=None, mf=None, ps=None, ed=None, mp=None, rm_EM=None, rm_TH=None, rc=None,
21
+ BH_curves_path: str = '', external_templates_paths: list = None):
20
22
  """
21
23
  Generates model .pro file from .pro template and regions model (rm)
24
+ :param external_templates_paths: list of paths to external templates directories
22
25
  :param BH_curves_path: path of the BH curves pro file
23
26
  :param template: .pro template file name
24
27
  :param rm: regions model data structure (yaml loaded to regions data model)
28
+ :param rm_EM: regions model data structure for electromagnetics (yaml loaded to regions data model)
29
+ :param rm_TH: regions model data structure for thermal (yaml loaded to regions data model)
25
30
  :param rc: regions coordinates data structure
26
31
  :param dm: data model structure
27
32
  :param mf: full path to mesh file to be used in solution
28
33
  :param ps: previous solution folder (this is used by CWS for co-simulation run)
29
34
  :param ed: excitation dictionary with lists (e.g. times and currents) to be used in a pro file (e.g. transient simulation)
30
- :param mp: material properties data structure (for CAC with Geometry YAML)
35
+ :param mp: material properties data structure
31
36
  :return: None. Generates .pro file and saves it on disk in the model folder under model_name.pro
32
37
  """
33
- loader = FileSystemLoader(combined.__path__)
38
+ external_templates_paths = external_templates_paths if external_templates_paths else []
39
+ loader = FileSystemLoader([os.path.dirname(combined.__file__)] + external_templates_paths)
34
40
  env = Environment(loader=loader, variable_start_string='<<', variable_end_string='>>',
35
- trim_blocks=True, lstrip_blocks=True)
36
- env.globals.update(set=set, str=str, int=int, float=float, zip=zip, enumerate=enumerate, list=list, len=len, isinstance=isinstance, arange=np.arange, Pi=np.pi) # this is to pass python zip function to the template, as normally it is not available. It should work for passing any python function that is not available in .pro template.
41
+ trim_blocks=True, lstrip_blocks=True, extensions=['jinja2.ext.do'])
42
+ env.globals.update(set=set, str=str, int=int, float=float, zip=zip, enumerate=enumerate, list=list,
43
+ len=len, isinstance=isinstance, arange=np.arange, Pi=np.pi) # this is to pass python zip function to the template, as normally it is not available. It should work for passing any python function that is not available in .pro template.
37
44
  pro_template = env.get_template(template)
38
- output_from_parsed_template = pro_template.render(BHcurves=BH_curves_path, rm=rm, rc=rc, dm=dm, mf=mf, nc=self.naming_conv, ps=ps, ed=ed, mp=mp)
45
+ output_from_parsed_template = pro_template.render(BHcurves=BH_curves_path, dm=dm, rm=rm, mf=mf, nc=self.naming_conv,
46
+ ps=ps, ed=ed, mp=mp, rm_EM=rm_EM, rm_TH=rm_TH, rc=rc)
39
47
  with open(f"{self.file_base_path}.pro", "w") as tf:
40
48
  tf.write(output_from_parsed_template)
41
49