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
@@ -1,16 +1,16 @@
1
- import pandas as pd
2
-
3
-
4
- class ParserDAT:
5
-
6
- def __init__(self, dat_file_path):
7
- """
8
- Read dat file and returns its content as object attribute .pqv (postprocessed quantity value) that is a float
9
- :param dat_file_path: Full path to .pos file, including file name and extension.
10
- :return: nothing, keeps attribute pqv (postprocessed quantity value)
11
- """
12
- pqn = 'pqn' # postprocessed quantity name
13
- delimiter = ' '
14
- columns = ['NaN', pqn]
15
- df = pd.read_csv(dat_file_path, delimiter=delimiter, header=None, engine='python', names=columns, skipinitialspace=True)
16
- self.pqv = float(df[pqn][0])
1
+ import pandas as pd
2
+
3
+
4
+ class ParserDAT:
5
+
6
+ def __init__(self, dat_file_path):
7
+ """
8
+ Read dat file and returns its content as object attribute .pqv (postprocessed quantity value) that is a float
9
+ :param dat_file_path: Full path to .pos file, including file name and extension.
10
+ :return: nothing, keeps attribute pqv (postprocessed quantity value)
11
+ """
12
+ pqn = 'pqn' # postprocessed quantity name
13
+ delimiter = ' '
14
+ columns = ['NaN', pqn]
15
+ df = pd.read_csv(dat_file_path, delimiter=delimiter, header=None, engine='python', names=columns, skipinitialspace=True)
16
+ self.pqv = float(df[pqn][0])
@@ -1,212 +1,212 @@
1
- import numpy as np
2
-
3
- import re
4
- import math
5
- from typing import Literal
6
-
7
-
8
- class ParserGetDPOnSection:
9
- """
10
- This class parses GetDP's TimeTable format output files.
11
- """
12
-
13
- def __init__(self, filePath, data_type: Literal["scalar", "vector"], depth):
14
- self.time_values = []
15
- self.data_type = data_type
16
- self.depth = depth
17
-
18
- if self.depth not in [0, 1]:
19
- raise NotImplementedError("Only depth = 0 and depth = 1 is implemented.")
20
-
21
- # Check GMSH documentation for object types:
22
- if self.depth == 0:
23
- if self.data_type == "scalar":
24
- lineName = "SP" # scalar point
25
- elif self.data_type == "vector":
26
- lineName = "VP" # vector point
27
- elif self.depth == 1:
28
- if self.data_type == "scalar":
29
- lineName = "ST"
30
- elif self.data_type == "vector":
31
- lineName = "VT"
32
-
33
- # Parse data:
34
- with open(filePath) as file:
35
- data = file.read()
36
-
37
- time_values_line = re.search(r"TIME\{(.*)\}", data)[0]
38
- time_values = re.findall(r"TIME\{(.*)\}", time_values_line)
39
- self.time_values = [
40
- float(time_value) for time_value in time_values[0].split(",")
41
- ]
42
- data = data.replace(time_values_line, "")
43
-
44
- points = re.findall(lineName + r"\((.*)\){.*\..*}", data)
45
- points = [point.split(",") for point in points]
46
- self.points = np.array(points, dtype=float)
47
-
48
- if self.depth == 1:
49
- length = np.shape(self.points)[1]
50
- step = int(length / 3)
51
- self.points = (
52
- self.points[:, 0:step]
53
- + self.points[:, step : 2 * step]
54
- + self.points[:, 2 * step : 3 * step]
55
- ) / 3
56
-
57
- values = re.findall(lineName + r"\(.*\){(.*\..*)}", data)
58
- values = [value.split(",") for value in values]
59
- self.values = np.array(values, dtype=float)
60
-
61
- if self.depth == 1:
62
- length = np.shape(self.values)[1]
63
- step = int(length / 3)
64
- self.values = (
65
- self.values[:, 0:step]
66
- + self.values[:, step : 2 * step]
67
- + self.values[:, 2 * step : 3 * step]
68
- ) / 3
69
-
70
- # Somehow, even with depth 0, we get duplicate magnitudes for different points.
71
- # We need to remove them for better plotting:
72
- _, unique_indices = np.unique(
73
- self.values[:, np.shape(self.values)[1] // 2], return_index=True
74
- )
75
- self.values = self.values[unique_indices, :]
76
- self.points = self.points[unique_indices, :]
77
-
78
- def get_values_at_time(self, time):
79
- """
80
- Returns the values at the specified time.
81
- """
82
- if self.points.shape[1] != 2:
83
- raise ValueError(
84
- "Use project_values_on_a_plane() before calling get_values_at_time()!"
85
- )
86
-
87
- for index, time_value in enumerate(self.time_values):
88
- if math.isclose(float(time_value), float(time), abs_tol=1e-10):
89
- return self.values[:, index]
90
-
91
- def get_values_at_time_step(self, time_step):
92
- """
93
- Returns the values at the specified time step.
94
- """
95
- if self.points.shape[1] != 2:
96
- raise ValueError(
97
- "Use project_values_on_a_plane() before calling get_values_at_time()!"
98
- )
99
-
100
- if self.data_type == "scalar":
101
- return self.values[:, time_step]
102
- elif self.data_type == "vector":
103
- return self.values[:, time_step * 2 : time_step * 2 + 2]
104
-
105
- def project_values_on_a_plane(self, plane_normal, plane_x_axis_unit_vector):
106
- """ """
107
-
108
- class unitVector:
109
- def __init__(self, u, v, w) -> None:
110
- length = math.sqrt(u**2 + v**2 + w**2)
111
- self.u = u / length
112
- self.v = v / length
113
- self.w = w / length
114
-
115
- def rotate(self, theta, withRespectTo):
116
- # Rotate with respect to the withRespectTo vector by theta degrees:
117
- # https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
118
- a = withRespectTo.u
119
- b = withRespectTo.v
120
- c = withRespectTo.w
121
-
122
- rotationMatrix = np.array(
123
- [
124
- [
125
- math.cos(theta) + a**2 * (1 - math.cos(theta)),
126
- a * b * (1 - math.cos(theta)) - c * math.sin(theta),
127
- a * c * (1 - math.cos(theta)) + b * math.sin(theta),
128
- ],
129
- [
130
- b * a * (1 - math.cos(theta)) + c * math.sin(theta),
131
- math.cos(theta) + b**2 * (1 - math.cos(theta)),
132
- b * c * (1 - math.cos(theta)) - a * math.sin(theta),
133
- ],
134
- [
135
- c * a * (1 - math.cos(theta)) - b * math.sin(theta),
136
- c * b * (1 - math.cos(theta)) + a * math.sin(theta),
137
- math.cos(theta) + c**2 * (1 - math.cos(theta)),
138
- ],
139
- ]
140
- )
141
- vector = np.array([[self.u], [self.v], [self.w]])
142
- rotatedVector = rotationMatrix @ vector
143
- return unitVector(
144
- rotatedVector[0][0],
145
- rotatedVector[1][0],
146
- rotatedVector[2][0],
147
- )
148
-
149
- def __pow__(self, otherUnitVector):
150
- # Cross product:
151
- u = self.v * otherUnitVector.w - self.w * otherUnitVector.v
152
- v = self.w * otherUnitVector.u - self.u * otherUnitVector.w
153
- w = self.u * otherUnitVector.v - self.v * otherUnitVector.u
154
- return unitVector(u, v, w)
155
-
156
- def __mul__(self, otherUnitVector) -> float:
157
- # Dot product:
158
- return (
159
- self.u * otherUnitVector.u
160
- + self.v * otherUnitVector.v
161
- + self.w * otherUnitVector.w
162
- )
163
-
164
- if len(plane_normal) != 3:
165
- raise ValueError(
166
- "planeNormal for magneticFieldOnCutPlane must be a list of"
167
- " three numbers!"
168
- )
169
-
170
- if len(plane_x_axis_unit_vector) != 3:
171
- raise ValueError(
172
- "planeXAxis for magneticFieldOnCutPlane must be a list of"
173
- " three numbers!"
174
- )
175
-
176
- plane_normal = unitVector(plane_normal[0], plane_normal[1], plane_normal[2])
177
- plane_x_axis = unitVector(
178
- plane_x_axis_unit_vector[0],
179
- plane_x_axis_unit_vector[1],
180
- plane_x_axis_unit_vector[2],
181
- )
182
-
183
- # Rotate perperndicular vector with respect to the plane's normal vector
184
- # by 90 degrees to find the second perpendicular vector:
185
- plane_y_axis = plane_x_axis.rotate(math.pi / 2, plane_normal)
186
-
187
- # Build the transformation matrix to change from the global coordinate
188
- # system to the plane's coordinate system:
189
- transformationMatrix = np.array(
190
- [
191
- [plane_x_axis.u, plane_x_axis.v, plane_x_axis.w],
192
- [plane_y_axis.u, plane_y_axis.v, plane_y_axis.w],
193
- [plane_normal.u, plane_normal.v, plane_normal.w],
194
- ]
195
- )
196
- points = self.points.transpose()
197
- new_points = transformationMatrix @ points
198
- new_points = new_points.transpose()
199
- self.points = new_points[:, 0:2]
200
-
201
- if self.data_type == "vector":
202
- reshaped_values = self.values
203
- reshaped_values = reshaped_values.reshape(
204
- (len(self.values) * len(self.time_values), 3)
205
- )
206
- reshaped_values = reshaped_values.transpose()
207
- new_values = transformationMatrix @ reshaped_values
208
- new_values = new_values.transpose()
209
- new_values = new_values[:, 0:2]
210
- self.values = new_values.reshape(
211
- np.shape(self.values)[0], int(np.shape(self.values)[1] / 3 * 2)
212
- )
1
+ import numpy as np
2
+
3
+ import re
4
+ import math
5
+ from typing import Literal
6
+
7
+
8
+ class ParserGetDPOnSection:
9
+ """
10
+ This class parses GetDP's TimeTable format output files.
11
+ """
12
+
13
+ def __init__(self, filePath, data_type: Literal["scalar", "vector"], depth):
14
+ self.time_values = []
15
+ self.data_type = data_type
16
+ self.depth = depth
17
+
18
+ if self.depth not in [0, 1]:
19
+ raise NotImplementedError("Only depth = 0 and depth = 1 is implemented.")
20
+
21
+ # Check GMSH documentation for object types:
22
+ if self.depth == 0:
23
+ if self.data_type == "scalar":
24
+ lineName = "SP" # scalar point
25
+ elif self.data_type == "vector":
26
+ lineName = "VP" # vector point
27
+ elif self.depth == 1:
28
+ if self.data_type == "scalar":
29
+ lineName = "ST"
30
+ elif self.data_type == "vector":
31
+ lineName = "VT"
32
+
33
+ # Parse data:
34
+ with open(filePath) as file:
35
+ data = file.read()
36
+
37
+ time_values_line = re.search(r"TIME\{(.*)\}", data)[0]
38
+ time_values = re.findall(r"TIME\{(.*)\}", time_values_line)
39
+ self.time_values = [
40
+ float(time_value) for time_value in time_values[0].split(",")
41
+ ]
42
+ data = data.replace(time_values_line, "")
43
+
44
+ points = re.findall(lineName + r"\((.*)\){.*\..*}", data)
45
+ points = [point.split(",") for point in points]
46
+ self.points = np.array(points, dtype=float)
47
+
48
+ if self.depth == 1:
49
+ length = np.shape(self.points)[1]
50
+ step = int(length / 3)
51
+ self.points = (
52
+ self.points[:, 0:step]
53
+ + self.points[:, step : 2 * step]
54
+ + self.points[:, 2 * step : 3 * step]
55
+ ) / 3
56
+
57
+ values = re.findall(lineName + r"\(.*\){(.*\..*)}", data)
58
+ values = [value.split(",") for value in values]
59
+ self.values = np.array(values, dtype=float)
60
+
61
+ if self.depth == 1:
62
+ length = np.shape(self.values)[1]
63
+ step = int(length / 3)
64
+ self.values = (
65
+ self.values[:, 0:step]
66
+ + self.values[:, step : 2 * step]
67
+ + self.values[:, 2 * step : 3 * step]
68
+ ) / 3
69
+
70
+ # Somehow, even with depth 0, we get duplicate magnitudes for different points.
71
+ # We need to remove them for better plotting:
72
+ _, unique_indices = np.unique(
73
+ self.values[:, np.shape(self.values)[1] // 2], return_index=True
74
+ )
75
+ self.values = self.values[unique_indices, :]
76
+ self.points = self.points[unique_indices, :]
77
+
78
+ def get_values_at_time(self, time):
79
+ """
80
+ Returns the values at the specified time.
81
+ """
82
+ if self.points.shape[1] != 2:
83
+ raise ValueError(
84
+ "Use project_values_on_a_plane() before calling get_values_at_time()!"
85
+ )
86
+
87
+ for index, time_value in enumerate(self.time_values):
88
+ if math.isclose(float(time_value), float(time), abs_tol=1e-10):
89
+ return self.values[:, index]
90
+
91
+ def get_values_at_time_step(self, time_step):
92
+ """
93
+ Returns the values at the specified time step.
94
+ """
95
+ if self.points.shape[1] != 2:
96
+ raise ValueError(
97
+ "Use project_values_on_a_plane() before calling get_values_at_time()!"
98
+ )
99
+
100
+ if self.data_type == "scalar":
101
+ return self.values[:, time_step]
102
+ elif self.data_type == "vector":
103
+ return self.values[:, time_step * 2 : time_step * 2 + 2]
104
+
105
+ def project_values_on_a_plane(self, plane_normal, plane_x_axis_unit_vector):
106
+ """ """
107
+
108
+ class unitVector:
109
+ def __init__(self, u, v, w) -> None:
110
+ length = math.sqrt(u**2 + v**2 + w**2)
111
+ self.u = u / length
112
+ self.v = v / length
113
+ self.w = w / length
114
+
115
+ def rotate(self, theta, withRespectTo):
116
+ # Rotate with respect to the withRespectTo vector by theta degrees:
117
+ # https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
118
+ a = withRespectTo.u
119
+ b = withRespectTo.v
120
+ c = withRespectTo.w
121
+
122
+ rotationMatrix = np.array(
123
+ [
124
+ [
125
+ math.cos(theta) + a**2 * (1 - math.cos(theta)),
126
+ a * b * (1 - math.cos(theta)) - c * math.sin(theta),
127
+ a * c * (1 - math.cos(theta)) + b * math.sin(theta),
128
+ ],
129
+ [
130
+ b * a * (1 - math.cos(theta)) + c * math.sin(theta),
131
+ math.cos(theta) + b**2 * (1 - math.cos(theta)),
132
+ b * c * (1 - math.cos(theta)) - a * math.sin(theta),
133
+ ],
134
+ [
135
+ c * a * (1 - math.cos(theta)) - b * math.sin(theta),
136
+ c * b * (1 - math.cos(theta)) + a * math.sin(theta),
137
+ math.cos(theta) + c**2 * (1 - math.cos(theta)),
138
+ ],
139
+ ]
140
+ )
141
+ vector = np.array([[self.u], [self.v], [self.w]])
142
+ rotatedVector = rotationMatrix @ vector
143
+ return unitVector(
144
+ rotatedVector[0][0],
145
+ rotatedVector[1][0],
146
+ rotatedVector[2][0],
147
+ )
148
+
149
+ def __pow__(self, otherUnitVector):
150
+ # Cross product:
151
+ u = self.v * otherUnitVector.w - self.w * otherUnitVector.v
152
+ v = self.w * otherUnitVector.u - self.u * otherUnitVector.w
153
+ w = self.u * otherUnitVector.v - self.v * otherUnitVector.u
154
+ return unitVector(u, v, w)
155
+
156
+ def __mul__(self, otherUnitVector) -> float:
157
+ # Dot product:
158
+ return (
159
+ self.u * otherUnitVector.u
160
+ + self.v * otherUnitVector.v
161
+ + self.w * otherUnitVector.w
162
+ )
163
+
164
+ if len(plane_normal) != 3:
165
+ raise ValueError(
166
+ "planeNormal for magneticFieldOnCutPlane must be a list of"
167
+ " three numbers!"
168
+ )
169
+
170
+ if len(plane_x_axis_unit_vector) != 3:
171
+ raise ValueError(
172
+ "planeXAxis for magneticFieldOnCutPlane must be a list of"
173
+ " three numbers!"
174
+ )
175
+
176
+ plane_normal = unitVector(plane_normal[0], plane_normal[1], plane_normal[2])
177
+ plane_x_axis = unitVector(
178
+ plane_x_axis_unit_vector[0],
179
+ plane_x_axis_unit_vector[1],
180
+ plane_x_axis_unit_vector[2],
181
+ )
182
+
183
+ # Rotate perperndicular vector with respect to the plane's normal vector
184
+ # by 90 degrees to find the second perpendicular vector:
185
+ plane_y_axis = plane_x_axis.rotate(math.pi / 2, plane_normal)
186
+
187
+ # Build the transformation matrix to change from the global coordinate
188
+ # system to the plane's coordinate system:
189
+ transformationMatrix = np.array(
190
+ [
191
+ [plane_x_axis.u, plane_x_axis.v, plane_x_axis.w],
192
+ [plane_y_axis.u, plane_y_axis.v, plane_y_axis.w],
193
+ [plane_normal.u, plane_normal.v, plane_normal.w],
194
+ ]
195
+ )
196
+ points = self.points.transpose()
197
+ new_points = transformationMatrix @ points
198
+ new_points = new_points.transpose()
199
+ self.points = new_points[:, 0:2]
200
+
201
+ if self.data_type == "vector":
202
+ reshaped_values = self.values
203
+ reshaped_values = reshaped_values.reshape(
204
+ (len(self.values) * len(self.time_values), 3)
205
+ )
206
+ reshaped_values = reshaped_values.transpose()
207
+ new_values = transformationMatrix @ reshaped_values
208
+ new_values = new_values.transpose()
209
+ new_values = new_values[:, 0:2]
210
+ self.values = new_values.reshape(
211
+ np.shape(self.values)[0], int(np.shape(self.values)[1] / 3 * 2)
212
+ )