fiqus 2024.5.2__py3-none-any.whl → 2024.6.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.
- fiqus/MainFiQuS.py +15 -5
- fiqus/data/DataConductor.py +301 -0
- fiqus/data/DataFiQuS.py +5 -2
- fiqus/data/DataFiQuSConductor.py +84 -0
- fiqus/data/DataFiQuSConductorAC_Strand.py +565 -0
- fiqus/data/DataFiQuSPancake3D.py +149 -39
- fiqus/data/RegionsModelFiQuS.py +4 -2
- fiqus/geom_generators/GeometryCCT.py +19 -17
- fiqus/geom_generators/GeometryConductorAC_Strand.py +1391 -0
- fiqus/getdp_runners/RunGetdpConductorAC_Strand.py +202 -0
- fiqus/getdp_runners/RunGetdpMultipole.py +4 -4
- fiqus/mains/MainConductorAC_Strand.py +133 -0
- fiqus/mesh_generators/MeshCCT.py +8 -8
- fiqus/mesh_generators/MeshConductorAC_Strand.py +657 -0
- fiqus/mesh_generators/MeshMultipole.py +11 -8
- fiqus/mesh_generators/MeshPancake3D.py +20 -18
- fiqus/plotters/PlotPythonConductorAC.py +840 -0
- fiqus/post_processors/PostProcessConductorAC.py +49 -0
- fiqus/pro_assemblers/ProAssembler.py +4 -3
- fiqus/pro_templates/combined/CCT_template.pro +25 -25
- fiqus/pro_templates/combined/ConductorAC_template.pro +1025 -0
- fiqus/pro_templates/combined/Multipole_template.pro +5 -5
- fiqus/pro_templates/combined/Pancake3D_template.pro +131 -46
- fiqus/pro_templates/combined/materials.pro +13 -9
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/METADATA +2 -1
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/RECORD +34 -22
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/WHEEL +1 -1
- tests/test_geometry_generators.py +41 -0
- tests/test_mesh_generators.py +45 -0
- tests/test_solvers.py +52 -0
- tests/utils/fiqus_test_classes.py +42 -6
- tests/utils/generate_reference_files_ConductorAC.py +57 -0
- tests/utils/generate_reference_files_Pancake3D.py +92 -0
- {fiqus-2024.5.2.dist-info → fiqus-2024.6.0.dist-info}/top_level.txt +0 -0
tests/test_mesh_generators.py
CHANGED
|
@@ -49,6 +49,51 @@ class TestMeshGenerators(FiQuSMeshTests):
|
|
|
49
49
|
)
|
|
50
50
|
self.compare_json_or_yaml_files(regions_file, reference_regions_file)
|
|
51
51
|
|
|
52
|
+
def test_ConductorAC_Strand(self):
|
|
53
|
+
"""
|
|
54
|
+
Checks if ConductorAC geometry generators work correctly by comparing the number
|
|
55
|
+
of entities in the generated geometry file to the reference file that was
|
|
56
|
+
checked manually.
|
|
57
|
+
"""
|
|
58
|
+
model_names = [
|
|
59
|
+
"TEST_CAC_Strand_adaptiveMesh",
|
|
60
|
+
"TEST_CAC_Strand_hexFilaments",
|
|
61
|
+
"TEST_CAC_wireInChannel",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
for model_name in model_names:
|
|
65
|
+
with self.subTest(model_name=model_name):
|
|
66
|
+
data_model = self.get_data_model(model_name)
|
|
67
|
+
|
|
68
|
+
# data_model can be modified here if necessary
|
|
69
|
+
# Example:
|
|
70
|
+
|
|
71
|
+
# data_model.magnet.mesh.wi.axne = 30
|
|
72
|
+
|
|
73
|
+
self.generate_mesh(data_model, model_name)
|
|
74
|
+
|
|
75
|
+
# Compare the number of entities with the reference file:
|
|
76
|
+
mesh_file = self.get_path_to_generated_file(
|
|
77
|
+
data_model=data_model, file_name=model_name, file_extension="msh"
|
|
78
|
+
)
|
|
79
|
+
reference_file = self.get_path_to_reference_file(
|
|
80
|
+
data_model=data_model, file_name=model_name, file_extension="msh"
|
|
81
|
+
)
|
|
82
|
+
self.compare_mesh_qualities(mesh_file, reference_file)
|
|
83
|
+
|
|
84
|
+
# Compare the regions files:
|
|
85
|
+
regions_file = self.get_path_to_generated_file(
|
|
86
|
+
data_model=data_model,
|
|
87
|
+
file_name=model_name,
|
|
88
|
+
file_extension="regions",
|
|
89
|
+
)
|
|
90
|
+
reference_regions_file = self.get_path_to_reference_file(
|
|
91
|
+
data_model=data_model,
|
|
92
|
+
file_name=model_name,
|
|
93
|
+
file_extension="regions",
|
|
94
|
+
)
|
|
95
|
+
self.compare_json_or_yaml_files(regions_file, reference_regions_file)
|
|
96
|
+
|
|
52
97
|
|
|
53
98
|
if __name__ == "__main__":
|
|
54
99
|
unittest.main()
|
tests/test_solvers.py
CHANGED
|
@@ -90,7 +90,59 @@ class TestSolvers(FiQuSSolverTests):
|
|
|
90
90
|
)
|
|
91
91
|
self.compare_pos_files(pos_file, reference_pos_file)
|
|
92
92
|
|
|
93
|
+
def test_ConductorAC_Strand(self):
|
|
94
|
+
"""
|
|
95
|
+
Checks if ConductorAC_Strand solvers work correctly by comparing the results to the
|
|
96
|
+
reference results that were checked manually.
|
|
97
|
+
"""
|
|
98
|
+
model_names = [
|
|
99
|
+
"TEST_CAC_Strand_hexFilaments",
|
|
100
|
+
"TEST_CAC_wireInChannel",
|
|
101
|
+
]
|
|
102
|
+
for model_name in model_names:
|
|
103
|
+
with self.subTest(model_name=model_name):
|
|
104
|
+
data_model: FDM = self.get_data_model(model_name)
|
|
105
|
+
|
|
106
|
+
self.solve(data_model, model_name)
|
|
107
|
+
|
|
108
|
+
# Compare the pro files:
|
|
109
|
+
pro_file = self.get_path_to_generated_file(
|
|
110
|
+
data_model=data_model,
|
|
111
|
+
file_name=model_name,
|
|
112
|
+
file_extension="pro",
|
|
113
|
+
)
|
|
114
|
+
reference_pro_file = self.get_path_to_reference_file(
|
|
115
|
+
data_model=data_model,
|
|
116
|
+
file_name=model_name,
|
|
117
|
+
file_extension="pro",
|
|
118
|
+
)
|
|
119
|
+
self.compare_text_files(pro_file, reference_pro_file)
|
|
120
|
+
|
|
121
|
+
# Compare the magnetic flux density files:
|
|
122
|
+
pos_file = self.get_path_to_generated_file(
|
|
123
|
+
data_model=data_model,
|
|
124
|
+
file_name="b",
|
|
125
|
+
file_extension="pos",
|
|
126
|
+
)
|
|
127
|
+
reference_pos_file = self.get_path_to_reference_file(
|
|
128
|
+
data_model=data_model,
|
|
129
|
+
file_name="b",
|
|
130
|
+
file_extension="pos",
|
|
131
|
+
)
|
|
132
|
+
self.compare_pos_files(pos_file, reference_pos_file)
|
|
93
133
|
|
|
134
|
+
# Compare the current density files:
|
|
135
|
+
pos_file = self.get_path_to_generated_file(
|
|
136
|
+
data_model=data_model,
|
|
137
|
+
file_name="j",
|
|
138
|
+
file_extension="pos",
|
|
139
|
+
)
|
|
140
|
+
reference_pos_file = self.get_path_to_reference_file(
|
|
141
|
+
data_model=data_model,
|
|
142
|
+
file_name="j",
|
|
143
|
+
file_extension="pos",
|
|
144
|
+
)
|
|
145
|
+
self.compare_pos_files(pos_file, reference_pos_file)
|
|
94
146
|
|
|
95
147
|
if __name__ == "__main__":
|
|
96
148
|
unittest.main()
|
|
@@ -414,7 +414,7 @@ class BaseClassesForTests(unittest.TestCase):
|
|
|
414
414
|
|
|
415
415
|
return reference_file
|
|
416
416
|
|
|
417
|
-
def compare_json_or_yaml_files(self, file_1, file_2):
|
|
417
|
+
def compare_json_or_yaml_files(self, file_1, file_2, tolerance=0):
|
|
418
418
|
"""
|
|
419
419
|
This method compares the contents of two JSON or YAML files. It is used to
|
|
420
420
|
check that the generated files are the same as the reference.
|
|
@@ -436,11 +436,47 @@ class BaseClassesForTests(unittest.TestCase):
|
|
|
436
436
|
raise ValueError("The files must be JSON or YAML files!")
|
|
437
437
|
|
|
438
438
|
# Compare the dictionaries:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
439
|
+
if tolerance == 0:
|
|
440
|
+
self.assertDictEqual(
|
|
441
|
+
file_1_dictionary,
|
|
442
|
+
file_2_dictionary,
|
|
443
|
+
msg=f"{file_1} did not match {file_2}!",
|
|
444
|
+
)
|
|
445
|
+
else:
|
|
446
|
+
self.compare_dicts(file_1_dictionary, file_2_dictionary, tolerance)
|
|
447
|
+
|
|
448
|
+
def compare_dicts(self, dict1, dict2, tolerance):
|
|
449
|
+
"""
|
|
450
|
+
This method compares the contents of two dictionaries, taking into account
|
|
451
|
+
floating point precision issues.
|
|
452
|
+
|
|
453
|
+
:param dict1: first dictionary to compare
|
|
454
|
+
:type dict1: dict
|
|
455
|
+
:param dict2: second dictionary to compare
|
|
456
|
+
:type dict2: dict
|
|
457
|
+
:param tolerance: tolerance for comparing floating point numbers
|
|
458
|
+
:type tolerance: float
|
|
459
|
+
"""
|
|
460
|
+
for key in dict1.keys():
|
|
461
|
+
if key not in dict2:
|
|
462
|
+
self.fail(f'Key "{key}" not in both {dict1} and {dict2}')
|
|
463
|
+
if isinstance(dict1[key], dict):
|
|
464
|
+
self.compare_dicts(dict1[key], dict2[key], tolerance)
|
|
465
|
+
elif isinstance(dict1[key], float): # To handle precision errors in floats
|
|
466
|
+
if not np.isclose(dict1[key], dict2[key], atol=tolerance):
|
|
467
|
+
self.fail(f'Values for key {key} are not close: {dict1[key]} vs {dict2[key]}')
|
|
468
|
+
elif isinstance(dict1[key], list): # To handle precision errors in lists of floats
|
|
469
|
+
if len(dict1[key]) != len(dict2[key]):
|
|
470
|
+
self.fail(f'Lists for key {key} are not the same length')
|
|
471
|
+
for i in range(len(dict1[key])):
|
|
472
|
+
if isinstance(dict1[key][i], float):
|
|
473
|
+
if not np.isclose(dict1[key][i], dict2[key][i], atol=tolerance):
|
|
474
|
+
self.fail(f'Values at index {i} for key {key} are not close: {dict1[key][i]} vs {dict2[key][i]}')
|
|
475
|
+
elif dict1[key][i] != dict2[key][i]:
|
|
476
|
+
self.fail(f'Values at index {i} for key {key} are not equal: {dict1[key][i]} vs {dict2[key][i]}')
|
|
477
|
+
else:
|
|
478
|
+
if dict1[key] != dict2[key]:
|
|
479
|
+
self.fail(f'Values for key {key} are not equal: {dict1[key]} vs {dict2[key]}')
|
|
444
480
|
|
|
445
481
|
def compare_pkl_files(self, file_1, file_2):
|
|
446
482
|
"""
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import sys
|
|
4
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../'))) # Add the path to the fiqus package to the system path
|
|
5
|
+
from fiqus.data.DataFiQuS import FDM
|
|
6
|
+
from fiqus.utils.Utils import FilesAndFolders as Util
|
|
7
|
+
from fiqus import MainFiQuS as mf
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Generate reference files for the models below:
|
|
11
|
+
model_names = [
|
|
12
|
+
"TEST_CAC_Strand_adaptiveMesh",
|
|
13
|
+
"TEST_CAC_Strand_hexFilaments",
|
|
14
|
+
"TEST_CAC_wireInChannel",
|
|
15
|
+
]
|
|
16
|
+
# The run types for the models above:
|
|
17
|
+
run_types = [
|
|
18
|
+
'geometry_and_mesh',
|
|
19
|
+
'start_from_yaml',
|
|
20
|
+
'start_from_yaml',
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
for model_name, run_type in zip(model_names, run_types):
|
|
24
|
+
# get path to the input file:
|
|
25
|
+
input_file = os.path.join(
|
|
26
|
+
os.path.dirname(os.path.dirname(__file__)),
|
|
27
|
+
"_inputs",
|
|
28
|
+
model_name,
|
|
29
|
+
f"{model_name}.yaml",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# select _references folder as the output folder:
|
|
33
|
+
output_folder = os.path.join(
|
|
34
|
+
os.path.dirname(os.path.dirname(__file__)), "_references", model_name
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# if the output folder exists, remove it:
|
|
38
|
+
if os.path.exists(output_folder):
|
|
39
|
+
shutil.rmtree(output_folder)
|
|
40
|
+
|
|
41
|
+
# Create the output folder:
|
|
42
|
+
os.makedirs(output_folder)
|
|
43
|
+
|
|
44
|
+
# Cast input yaml file to FDM
|
|
45
|
+
data_model: FDM = Util.read_data_from_yaml(input_file, FDM)
|
|
46
|
+
|
|
47
|
+
data_model.run.overwrite = True
|
|
48
|
+
|
|
49
|
+
# Make the run type start_from_yaml:
|
|
50
|
+
data_model.run.type = run_type
|
|
51
|
+
|
|
52
|
+
fiqus_instance = mf.MainFiQuS(
|
|
53
|
+
fdm=data_model, model_folder=output_folder, input_file_path=input_file
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# remove fiqus_instance to avoid memory issues:
|
|
57
|
+
del fiqus_instance
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import sys
|
|
4
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../'))) # Add the path to the fiqus package to the system path
|
|
5
|
+
import fiqus.data.DataFiQuSPancake3D as Pancake3D
|
|
6
|
+
from fiqus.data.DataFiQuS import FDM
|
|
7
|
+
from fiqus.utils.Utils import FilesAndFolders as Util
|
|
8
|
+
from fiqus import MainFiQuS as mf
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Generate reference files for the models below:
|
|
12
|
+
model_names = [
|
|
13
|
+
"TEST_Pancake3D_REF",
|
|
14
|
+
"TEST_Pancake3D_REFStructured",
|
|
15
|
+
"TEST_Pancake3D_TSA",
|
|
16
|
+
"TEST_Pancake3D_TSAStructured",
|
|
17
|
+
"TEST_Pancake3D_TSAInsulating"
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
for model_name in model_names:
|
|
21
|
+
input_file = os.path.join(
|
|
22
|
+
os.path.dirname(os.path.dirname(__file__)),
|
|
23
|
+
"_inputs",
|
|
24
|
+
model_name,
|
|
25
|
+
f"{model_name}.yaml",
|
|
26
|
+
)
|
|
27
|
+
# select _references folder as the output folder:
|
|
28
|
+
output_folder = os.path.join(
|
|
29
|
+
os.path.dirname(os.path.dirname(__file__)), "_references", model_name
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Cast input yaml file to FDM
|
|
33
|
+
data_model: FDM = Util.read_data_from_yaml(input_file, FDM)
|
|
34
|
+
data_model.magnet.postproc = Pancake3D.Pancake3DPostprocess()
|
|
35
|
+
data_model.run.overwrite = True
|
|
36
|
+
data_model.run.launch_gui = False
|
|
37
|
+
|
|
38
|
+
# if the output folder exists, remove it and create a new one:
|
|
39
|
+
if os.path.exists(output_folder):
|
|
40
|
+
shutil.rmtree(output_folder)
|
|
41
|
+
# Create the output folder:
|
|
42
|
+
os.makedirs(output_folder)
|
|
43
|
+
|
|
44
|
+
# Solve the same model three times with different solve types:
|
|
45
|
+
solve_types = [
|
|
46
|
+
"weaklyCoupled",
|
|
47
|
+
"stronglyCoupled",
|
|
48
|
+
"electromagnetic",
|
|
49
|
+
]
|
|
50
|
+
for i, solve_type in enumerate(solve_types):
|
|
51
|
+
if i == 0:
|
|
52
|
+
# Make the run type start_from_yaml:
|
|
53
|
+
data_model.run.type = "start_from_yaml"
|
|
54
|
+
else:
|
|
55
|
+
# Make the run type solve_only:
|
|
56
|
+
data_model.run.type = "solve_only"
|
|
57
|
+
|
|
58
|
+
# data_model.run.type = "post_process"
|
|
59
|
+
# data_model.run.type = "solve_only"
|
|
60
|
+
|
|
61
|
+
data_model.magnet.solve.type = solve_type
|
|
62
|
+
data_model.run.solution = solve_type
|
|
63
|
+
if solve_type in ["weaklyCoupled", "stronglyCoupled"]:
|
|
64
|
+
data_model.magnet.solve.save = [
|
|
65
|
+
Pancake3D.Pancake3DSolveSaveQuantity(
|
|
66
|
+
quantity="magneticField",
|
|
67
|
+
),
|
|
68
|
+
Pancake3D.Pancake3DSolveSaveQuantity(
|
|
69
|
+
quantity="currentDensity",
|
|
70
|
+
),
|
|
71
|
+
Pancake3D.Pancake3DSolveSaveQuantity(
|
|
72
|
+
quantity="temperature",
|
|
73
|
+
),
|
|
74
|
+
]
|
|
75
|
+
elif solve_type == "electromagnetic":
|
|
76
|
+
data_model.magnet.solve.save = [
|
|
77
|
+
Pancake3D.Pancake3DSolveSaveQuantity(
|
|
78
|
+
quantity="magneticField",
|
|
79
|
+
),
|
|
80
|
+
Pancake3D.Pancake3DSolveSaveQuantity(
|
|
81
|
+
quantity="currentDensity",
|
|
82
|
+
),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
fiqus_instance = mf.MainFiQuS(fdm=data_model, model_folder=output_folder)
|
|
86
|
+
|
|
87
|
+
# remove fiqus_instance to avoid memory issues:
|
|
88
|
+
del fiqus_instance
|
|
89
|
+
|
|
90
|
+
# # remove logs directory and run_log.csv inside the output folder:
|
|
91
|
+
# shutil.rmtree(os.path.join(output_folder, "logs"))
|
|
92
|
+
# os.remove(os.path.join(output_folder, "run_log.csv"))
|
|
File without changes
|