gmshairfoil2d 0.2.2__py3-none-any.whl → 0.2.31__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.
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -4,7 +4,7 @@ from unittest.mock import patch, Mock
4
4
 
5
5
  import gmshairfoil2d.__init__
6
6
  from gmshairfoil2d.airfoil_func import (NACA_4_digit_geom, get_airfoil_file,
7
- get_all_available_airfoil_names)
7
+ get_all_available_airfoil_names, read_airfoil_from_file)
8
8
  from pytest import approx
9
9
 
10
10
  LIB_DIR = Path(gmshairfoil2d.__init__.__file__).parents[1]
@@ -75,3 +75,54 @@ def test_NACA_4_digit_geom():
75
75
  assert all(
76
76
  [a == approx(b, 1e-3) for a, b in zip(naca4412, NACA_4_digit_geom("4412"))]
77
77
  )
78
+
79
+ def test_read_airfoil_from_file(tmp_path):
80
+ """
81
+ Test reading airfoil coordinates from a .dat file
82
+ """
83
+ # Create a simple test airfoil file
84
+ airfoil_content = """NACA 0012 Test Airfoil
85
+ 100 100
86
+ 1.000000 0.000000
87
+ 0.975000 0.003000
88
+ 0.900000 0.008000
89
+ 0.500000 0.012000
90
+ 0.100000 0.008000
91
+ 0.025000 0.003000
92
+ 0.000000 0.000000
93
+ 0.025000 -0.003000
94
+ 0.100000 -0.008000
95
+ 0.500000 -0.012000
96
+ 0.900000 -0.008000
97
+ 0.975000 -0.003000
98
+ """
99
+
100
+ test_file = tmp_path / "test_airfoil.dat"
101
+ test_file.write_text(airfoil_content)
102
+
103
+ # Read the airfoil
104
+ points = read_airfoil_from_file(str(test_file))
105
+
106
+ # Check that points were read
107
+ assert len(points) > 0
108
+
109
+ # Check that points are tuples with 3 coordinates (x, y, 0)
110
+ for point in points:
111
+ assert len(point) == 3
112
+ assert point[2] == 0 # z coordinate should be 0
113
+
114
+ # Check that we have some leading edge points (x near 0)
115
+ x_coords = [p[0] for p in points]
116
+ assert any(x < 0.05 for x in x_coords)
117
+
118
+ # Check that we have trailing edge points (x near 1)
119
+ assert any(x > 0.95 for x in x_coords)
120
+
121
+
122
+ def test_read_airfoil_from_file_not_found():
123
+ """
124
+ Test that FileNotFoundError is raised for non-existent files
125
+ """
126
+ import pytest
127
+ with pytest.raises(FileNotFoundError):
128
+ read_airfoil_from_file("/non/existent/path/airfoil.dat")
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ Tests for the configuration file handler
6
+ """
7
+
8
+ import pytest
9
+ from pathlib import Path
10
+ from gmshairfoil2d.config_handler import read_config, write_config, merge_config_with_args
11
+ import argparse
12
+
13
+
14
+ def test_read_config_basic(tmp_path):
15
+ """
16
+ Test reading basic configuration from file
17
+ """
18
+ config_content = """# Test configuration file
19
+ naca= 0012
20
+ aoa= 5.0
21
+ farfield= 10
22
+ format= su2
23
+ """
24
+
25
+ config_file = tmp_path / "test_config.cfg"
26
+ config_file.write_text(config_content)
27
+
28
+ config = read_config(str(config_file))
29
+
30
+ assert config['naca'] == '0012'
31
+ assert config['aoa'] == 5.0
32
+ assert config['farfield'] == 10
33
+ assert config['format'] == 'su2'
34
+
35
+
36
+ def test_read_config_empty_values(tmp_path):
37
+ """
38
+ Test that empty values are skipped
39
+ """
40
+ config_content = """naca= 0012
41
+ airfoil=
42
+ aoa= 5.0
43
+ output=
44
+ format= su2
45
+ """
46
+
47
+ config_file = tmp_path / "test_config.cfg"
48
+ config_file.write_text(config_content)
49
+
50
+ config = read_config(str(config_file))
51
+
52
+ # Should have the parameters with values
53
+ assert 'naca' in config
54
+ assert 'aoa' in config
55
+ assert 'format' in config
56
+
57
+ # Should NOT have the empty parameters
58
+ assert 'airfoil' not in config
59
+ assert 'output' not in config
60
+
61
+
62
+ def test_read_config_boolean_values(tmp_path):
63
+ """
64
+ Test that boolean values are correctly converted
65
+ """
66
+ config_content = """no_bl= False
67
+ structured= True
68
+ ui= false
69
+ """
70
+
71
+ config_file = tmp_path / "test_config.cfg"
72
+ config_file.write_text(config_content)
73
+
74
+ config = read_config(str(config_file))
75
+
76
+ assert config['no_bl'] is False
77
+ assert config['structured'] is True
78
+ assert config['ui'] is False
79
+
80
+
81
+ def test_read_config_numeric_conversion(tmp_path):
82
+ """
83
+ Test that numeric values are correctly converted to float/int
84
+ """
85
+ config_content = """nb_layers= 35
86
+ aoa= 5.5
87
+ first_layer= 3e-05
88
+ ratio= 1.2
89
+ """
90
+
91
+ config_file = tmp_path / "test_config.cfg"
92
+ config_file.write_text(config_content)
93
+
94
+ config = read_config(str(config_file))
95
+
96
+ assert config['nb_layers'] == 35
97
+ assert isinstance(config['nb_layers'], int)
98
+ assert config['aoa'] == 5.5
99
+ assert isinstance(config['aoa'], float)
100
+ assert config['first_layer'] == 3e-05
101
+ assert isinstance(config['first_layer'], float)
102
+ assert config['ratio'] == 1.2
103
+ assert isinstance(config['ratio'], float)
104
+
105
+
106
+ def test_read_config_comments_ignored(tmp_path):
107
+ """
108
+ Test that comment lines are ignored
109
+ """
110
+ config_content = """# This is a comment
111
+ naca= 0012
112
+ # Another comment
113
+ aoa= 5.0
114
+ # Even more comments here
115
+ """
116
+
117
+ config_file = tmp_path / "test_config.cfg"
118
+ config_file.write_text(config_content)
119
+
120
+ config = read_config(str(config_file))
121
+
122
+ assert len(config) == 2
123
+ assert config['naca'] == '0012'
124
+ assert config['aoa'] == 5.0
125
+
126
+
127
+ def test_read_config_file_not_found():
128
+ """
129
+ Test that FileNotFoundError is raised for non-existent files
130
+ """
131
+ with pytest.raises(FileNotFoundError):
132
+ read_config("/non/existent/config.cfg")
133
+
134
+
135
+ def test_write_config(tmp_path):
136
+ """
137
+ Test writing configuration to file
138
+ """
139
+ config_dict = {
140
+ 'naca': '0012',
141
+ 'aoa': 5.0,
142
+ 'farfield': 10,
143
+ 'format': 'su2',
144
+ 'structured': False
145
+ }
146
+
147
+ output_file = tmp_path / "output_config.cfg"
148
+ write_config(config_dict, str(output_file))
149
+
150
+ # Verify file was created
151
+ assert output_file.exists()
152
+
153
+ # Read back and verify
154
+ content = output_file.read_text()
155
+ assert 'naca= 0012' in content
156
+ assert 'aoa= 5.0' in content
157
+ assert 'farfield= 10' in content
158
+ assert 'format= su2' in content
159
+
160
+
161
+ def test_write_config_with_none_values(tmp_path):
162
+ """
163
+ Test writing configuration with None values
164
+ """
165
+ config_dict = {
166
+ 'naca': '0012',
167
+ 'airfoil': None,
168
+ 'aoa': 5.0
169
+ }
170
+
171
+ output_file = tmp_path / "output_config.cfg"
172
+ write_config(config_dict, str(output_file))
173
+
174
+ content = output_file.read_text()
175
+ assert 'airfoil=' in content
176
+
177
+
178
+ def test_merge_config_with_args():
179
+ """
180
+ Test merging configuration with command-line arguments
181
+ """
182
+ config_dict = {
183
+ 'naca': '0012',
184
+ 'aoa': 5.0,
185
+ 'farfield': 10,
186
+ 'format': 'su2'
187
+ }
188
+
189
+ # Create mock args with defaults
190
+ parser = argparse.ArgumentParser()
191
+ parser.add_argument('--naca', default=None)
192
+ parser.add_argument('--aoa', type=float, default=None)
193
+ parser.add_argument('--farfield', type=float, default=10)
194
+ parser.add_argument('--format', default=None)
195
+ parser.add_argument('--output', default='.')
196
+
197
+ args = parser.parse_args([])
198
+
199
+ # Merge config into args
200
+ merged_args = merge_config_with_args(config_dict, args)
201
+
202
+ assert merged_args.naca == '0012'
203
+ assert merged_args.aoa == 5.0
204
+ assert merged_args.format == 'su2'
205
+ assert merged_args.output == '.' # Default not overridden
206
+
207
+
208
+ def test_merge_config_cli_precedence():
209
+ """
210
+ Test that CLI arguments take precedence over config file
211
+ """
212
+ config_dict = {
213
+ 'naca': '0012',
214
+ 'aoa': 5.0,
215
+ 'format': 'su2'
216
+ }
217
+
218
+ parser = argparse.ArgumentParser()
219
+ parser.add_argument('--naca', default=None)
220
+ parser.add_argument('--aoa', type=float, default=None)
221
+ parser.add_argument('--format', default=None)
222
+
223
+ # Simulate CLI providing aoa explicitly
224
+ args = parser.parse_args(['--aoa', '10.0'])
225
+
226
+ merged_args = merge_config_with_args(config_dict, args)
227
+
228
+ # Config values applied
229
+ assert merged_args.naca == '0012'
230
+ assert merged_args.format == 'su2'
231
+
232
+ # CLI value takes precedence
233
+ assert merged_args.aoa == 10.0
234
+
235
+
236
+ def test_read_write_roundtrip(tmp_path):
237
+ """
238
+ Test that writing and reading back produces the same config
239
+ """
240
+ original_config = {
241
+ 'naca': '2412',
242
+ 'aoa': 3.5,
243
+ 'farfield': 15,
244
+ 'format': 'cgns',
245
+ 'nb_layers': 50,
246
+ 'first_layer': 1e-04
247
+ }
248
+
249
+ config_file = tmp_path / "roundtrip_config.cfg"
250
+
251
+ # Write
252
+ write_config(original_config, str(config_file))
253
+
254
+ # Read back
255
+ read_back_config = read_config(str(config_file))
256
+
257
+ # Verify all values match
258
+ for key, value in original_config.items():
259
+ assert key in read_back_config
260
+ assert read_back_config[key] == value
@@ -29,13 +29,17 @@ def test_mesh_rectangle():
29
29
  gmsh.write(str(Path(test_data_dir, "mesh_test.su2")))
30
30
  gmsh.finalize()
31
31
 
32
- # Test if the generated mesh is correct
32
+ # Test if the generated mesh is correct by checking key properties
33
+ # (exact floating point comparison varies with GMSH version)
33
34
  with open(Path(test_data_dir, "mesh_test.su2"), "r") as f:
34
35
  mesh_test = f.read()
35
- with open(Path(test_data_dir, "mesh.su2"), "r") as f:
36
- mesh_origin = f.read()
36
+
37
+ # Verify mesh structure is created correctly
38
+ assert "NDIME= 2" in mesh_test
39
+ assert "NELEM= 14" in mesh_test
40
+ assert "NPOIN= 12" in mesh_test
41
+ assert "NMARK= 3" in mesh_test
42
+ assert "MARKER_TAG= inlet" in mesh_test
43
+ assert "MARKER_TAG= outlet" in mesh_test
44
+ assert "MARKER_TAG= wall" in mesh_test
37
45
 
38
- assert mesh_test == mesh_origin
39
-
40
-
41
- test_mesh_rectangle()
@@ -1,13 +0,0 @@
1
- gmshairfoil2d/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- gmshairfoil2d/airfoil_func.py,sha256=6DJTp4uwLL_9_75weVFw69lHZYmVsa-FY2916iBAuXU,5694
3
- gmshairfoil2d/geometry_def.py,sha256=IaJ-5pBAfXHI-fHvCoeIlXmu6kJpKYdEQq_cVdacK9I,44388
4
- gmshairfoil2d/gmshairfoil2d.py,sha256=9GoKpHDytiUOvM0dX-YNDVb25GxG5KaZjxq5emo-IVw,9998
5
- gmshairfoil2d-0.2.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
6
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- tests/test_airfoil_func.py,sha256=s6byg1p66I79PhFK-r9Ke4KcI_XaTNqIYKB3K1ZjQEc,2465
8
- tests/test_geometry_def.py,sha256=ogy8YmigkwQ118duDXXGRZPZb_DS9qnkTuzzaF5jmb8,1054
9
- gmshairfoil2d-0.2.2.dist-info/METADATA,sha256=t5AtDapRtaMv-zLgvarUxEUHzQ9HnRk11U_OkUfONZk,5861
10
- gmshairfoil2d-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
- gmshairfoil2d-0.2.2.dist-info/entry_points.txt,sha256=6OBSsEXNhTICrsEGgfg30RGIkKRFXELizYtfZfT1_zk,67
12
- gmshairfoil2d-0.2.2.dist-info/top_level.txt,sha256=OUzQHTQIzJHlW1k6tm_9PLfE4eEWkwH0oOYNUuUXekw,20
13
- gmshairfoil2d-0.2.2.dist-info/RECORD,,