gmshairfoil2d 0.2__py3-none-any.whl → 0.2.2__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.
- gmshairfoil2d/airfoil_func.py +12 -2
- {gmshairfoil2d-0.2.dist-info → gmshairfoil2d-0.2.2.dist-info}/METADATA +6 -3
- gmshairfoil2d-0.2.2.dist-info/RECORD +13 -0
- {gmshairfoil2d-0.2.dist-info → gmshairfoil2d-0.2.2.dist-info}/top_level.txt +1 -0
- tests/__init__.py +0 -0
- tests/test_airfoil_func.py +77 -0
- tests/test_geometry_def.py +41 -0
- gmshairfoil2d-0.2.dist-info/RECORD +0 -10
- {gmshairfoil2d-0.2.dist-info → gmshairfoil2d-0.2.2.dist-info}/WHEEL +0 -0
- {gmshairfoil2d-0.2.dist-info → gmshairfoil2d-0.2.2.dist-info}/entry_points.txt +0 -0
- {gmshairfoil2d-0.2.dist-info → gmshairfoil2d-0.2.2.dist-info}/licenses/LICENSE +0 -0
gmshairfoil2d/airfoil_func.py
CHANGED
|
@@ -2,6 +2,7 @@ from pathlib import Path
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import requests
|
|
5
|
+
import sys
|
|
5
6
|
|
|
6
7
|
import gmshairfoil2d.__init__
|
|
7
8
|
|
|
@@ -49,8 +50,17 @@ def get_airfoil_file(airfoil_name):
|
|
|
49
50
|
|
|
50
51
|
r = requests.get(url)
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
try:
|
|
54
|
+
r = requests.get(url, timeout=10) # Aggiungi sempre un timeout
|
|
55
|
+
if r.status_code != 200:
|
|
56
|
+
# Invece di raise Exception, print e exit pulito
|
|
57
|
+
print(f"❌ Error: Could not find airfoil '{airfoil_name}' on UIUC database.")
|
|
58
|
+
import sys
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
except requests.exceptions.RequestException as e:
|
|
61
|
+
print(f"❌ Network Error: Could not connect to the database. Check your internet.")
|
|
62
|
+
import sys
|
|
63
|
+
sys.exit(1)
|
|
54
64
|
|
|
55
65
|
file_path = Path(database_dir, f"{airfoil_name}.dat")
|
|
56
66
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gmshairfoil2d
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Python tool to generate 2D mesh around an airfoil
|
|
5
5
|
Home-page: https://github.com/cfsengineering/GMSH-Airfoil-2D
|
|
6
6
|
Author: Giacomo Benedetti
|
|
7
7
|
Author-email: giacomo.benedetti@cfse.ch
|
|
8
|
-
License: Apache License 2.0
|
|
9
8
|
Keywords: airfoil,2D,mesh,cfd,gmsh
|
|
10
9
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
10
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -14,6 +13,10 @@ Classifier: Intended Audience :: Developers
|
|
|
14
13
|
Requires-Python: >=3.11.0
|
|
15
14
|
Description-Content-Type: text/markdown
|
|
16
15
|
License-File: LICENSE
|
|
16
|
+
Requires-Dist: gmsh>=4.14
|
|
17
|
+
Requires-Dist: numpy>=1.20.3
|
|
18
|
+
Requires-Dist: pytest==7.1.3
|
|
19
|
+
Requires-Dist: requests==2.26.0
|
|
17
20
|
Dynamic: author
|
|
18
21
|
Dynamic: author-email
|
|
19
22
|
Dynamic: classifier
|
|
@@ -21,8 +24,8 @@ Dynamic: description
|
|
|
21
24
|
Dynamic: description-content-type
|
|
22
25
|
Dynamic: home-page
|
|
23
26
|
Dynamic: keywords
|
|
24
|
-
Dynamic: license
|
|
25
27
|
Dynamic: license-file
|
|
28
|
+
Dynamic: requires-dist
|
|
26
29
|
Dynamic: requires-python
|
|
27
30
|
Dynamic: summary
|
|
28
31
|
|
|
@@ -0,0 +1,13 @@
|
|
|
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,,
|
tests/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import pickle
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from unittest.mock import patch, Mock
|
|
4
|
+
|
|
5
|
+
import gmshairfoil2d.__init__
|
|
6
|
+
from gmshairfoil2d.airfoil_func import (NACA_4_digit_geom, get_airfoil_file,
|
|
7
|
+
get_all_available_airfoil_names)
|
|
8
|
+
from pytest import approx
|
|
9
|
+
|
|
10
|
+
LIB_DIR = Path(gmshairfoil2d.__init__.__file__).parents[1]
|
|
11
|
+
|
|
12
|
+
database_dir = Path(LIB_DIR, "database")
|
|
13
|
+
test_data_dir = Path(LIB_DIR, "tests", "test_data")
|
|
14
|
+
|
|
15
|
+
def test_get_all_available_airfoil_names(monkeypatch):
|
|
16
|
+
class MockResponse:
|
|
17
|
+
def __init__(self):
|
|
18
|
+
self.status_code = 200
|
|
19
|
+
self.text = (
|
|
20
|
+
'<html>'
|
|
21
|
+
'<a href="coord/naca0010.dat">naca0010</a>'
|
|
22
|
+
'<a href="coord/naca0018.dat">naca0018</a>'
|
|
23
|
+
'<a href="coord/falcon.dat">falcon</a>'
|
|
24
|
+
'<a href="coord/goe510.dat">goe510</a>'
|
|
25
|
+
'<a href="coord/e1210.dat">e1210</a>'
|
|
26
|
+
'</html>'
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
monkeypatch.setattr("gmshairfoil2d.airfoil_func.requests.get", lambda *args, **kwargs: MockResponse())
|
|
30
|
+
|
|
31
|
+
current_airfoil_list = get_all_available_airfoil_names()
|
|
32
|
+
|
|
33
|
+
expected_airfoil = ["naca0010", "naca0018", "falcon", "goe510", "e1210"]
|
|
34
|
+
for foil in expected_airfoil:
|
|
35
|
+
assert foil in current_airfoil_list
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_get_airfoil_file(monkeypatch, tmp_path):
|
|
39
|
+
|
|
40
|
+
fake_text = "0.0 0.0\n0.5 0.1\n1.0 0.0"
|
|
41
|
+
|
|
42
|
+
class MockResponse:
|
|
43
|
+
def __init__(self):
|
|
44
|
+
self.status_code = 200
|
|
45
|
+
self.text = fake_text
|
|
46
|
+
self.content = fake_text.encode('utf-8')
|
|
47
|
+
|
|
48
|
+
monkeypatch.setattr("gmshairfoil2d.airfoil_func.requests.get", lambda *args, **kwargs: MockResponse())
|
|
49
|
+
|
|
50
|
+
monkeypatch.setattr("gmshairfoil2d.airfoil_func.database_dir", tmp_path)
|
|
51
|
+
|
|
52
|
+
profile = "naca0010"
|
|
53
|
+
expected_path = tmp_path / f"{profile}.dat"
|
|
54
|
+
|
|
55
|
+
get_airfoil_file(profile)
|
|
56
|
+
|
|
57
|
+
assert expected_path.exists()
|
|
58
|
+
assert expected_path.read_text() == fake_text
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_NACA_4_digit_geom():
|
|
62
|
+
with open(Path(test_data_dir, "naca0012.txt"), "rb") as f:
|
|
63
|
+
naca0012 = pickle.load(f)
|
|
64
|
+
with open(Path(test_data_dir, "naca4412.txt"), "rb") as f:
|
|
65
|
+
naca4412 = pickle.load(f)
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
Test if the NACA0012 profil and NACA4412 profil are correctly generated
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
assert all(
|
|
72
|
+
[a == approx(b, 1e-3) for a, b in zip(naca0012, NACA_4_digit_geom("0012"))]
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
assert all(
|
|
76
|
+
[a == approx(b, 1e-3) for a, b in zip(naca4412, NACA_4_digit_geom("4412"))]
|
|
77
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import gmsh
|
|
4
|
+
import gmshairfoil2d.__init__
|
|
5
|
+
from gmshairfoil2d.geometry_def import Circle, PlaneSurface, Rectangle
|
|
6
|
+
|
|
7
|
+
LIB_DIR = Path(gmshairfoil2d.__init__.__file__).parents[1]
|
|
8
|
+
test_data_dir = Path(LIB_DIR, "tests", "test_data")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_mesh_rectangle():
|
|
12
|
+
"""
|
|
13
|
+
Test if a simple generated mesh formed of a square domain with a circular
|
|
14
|
+
hole inside is meshed correctly
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# Generate Geometry :
|
|
19
|
+
gmsh.initialize()
|
|
20
|
+
box = Rectangle(0, 0, 0, 1, 1, mesh_size=0.5)
|
|
21
|
+
surface_domain = PlaneSurface([box])
|
|
22
|
+
|
|
23
|
+
gmsh.model.geo.synchronize()
|
|
24
|
+
box.define_bc()
|
|
25
|
+
surface_domain.define_bc()
|
|
26
|
+
|
|
27
|
+
# Generate mesh
|
|
28
|
+
gmsh.model.mesh.generate(2)
|
|
29
|
+
gmsh.write(str(Path(test_data_dir, "mesh_test.su2")))
|
|
30
|
+
gmsh.finalize()
|
|
31
|
+
|
|
32
|
+
# Test if the generated mesh is correct
|
|
33
|
+
with open(Path(test_data_dir, "mesh_test.su2"), "r") as f:
|
|
34
|
+
mesh_test = f.read()
|
|
35
|
+
with open(Path(test_data_dir, "mesh.su2"), "r") as f:
|
|
36
|
+
mesh_origin = f.read()
|
|
37
|
+
|
|
38
|
+
assert mesh_test == mesh_origin
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
test_mesh_rectangle()
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
gmshairfoil2d/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
gmshairfoil2d/airfoil_func.py,sha256=twMt4y9PeMeBSawWv-D5jLzkKMJzEshL-BiG86tSGvk,5275
|
|
3
|
-
gmshairfoil2d/geometry_def.py,sha256=IaJ-5pBAfXHI-fHvCoeIlXmu6kJpKYdEQq_cVdacK9I,44388
|
|
4
|
-
gmshairfoil2d/gmshairfoil2d.py,sha256=9GoKpHDytiUOvM0dX-YNDVb25GxG5KaZjxq5emo-IVw,9998
|
|
5
|
-
gmshairfoil2d-0.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
6
|
-
gmshairfoil2d-0.2.dist-info/METADATA,sha256=ce9uOFmUGWMDKNGbKJekBsepC483oqQTH_GpG8aGuMg,5765
|
|
7
|
-
gmshairfoil2d-0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
gmshairfoil2d-0.2.dist-info/entry_points.txt,sha256=6OBSsEXNhTICrsEGgfg30RGIkKRFXELizYtfZfT1_zk,67
|
|
9
|
-
gmshairfoil2d-0.2.dist-info/top_level.txt,sha256=MhXEKx8aoWrGbkyrGaDGJOCv3GER7nzzSfz0UsvI2NQ,14
|
|
10
|
-
gmshairfoil2d-0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|