py_windblade_opa 0.6.6__tar.gz
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.
- py_windblade_opa-0.6.6/.gitignore +93 -0
- py_windblade_opa-0.6.6/.python-version +1 -0
- py_windblade_opa-0.6.6/CHANGELOG.md +18 -0
- py_windblade_opa-0.6.6/History.md +47 -0
- py_windblade_opa-0.6.6/LICENSE +21 -0
- py_windblade_opa-0.6.6/PKG-INFO +135 -0
- py_windblade_opa-0.6.6/README.md +108 -0
- py_windblade_opa-0.6.6/design/.gitkeep +1 -0
- py_windblade_opa-0.6.6/design/TODOs-NOTE.md +79 -0
- py_windblade_opa-0.6.6/design/architecture.md +390 -0
- py_windblade_opa-0.6.6/design/archive/PerformancePostProcessor-and-MDReport.md +313 -0
- py_windblade_opa-0.6.6/design/archive/Stage1-OrchestratorFixUpdatingAndUT.md +784 -0
- py_windblade_opa-0.6.6/design/next_refactor/Stage3-AirfoilProvider.md +265 -0
- py_windblade_opa-0.6.6/design/next_refactor/Stage4-RotorAssembly.md +285 -0
- py_windblade_opa-0.6.6/design/ongoing/IMPLEMENTATION-STATUS.md +119 -0
- py_windblade_opa-0.6.6/design/ongoing/Stage2-AddingGeometryV2.md +491 -0
- py_windblade_opa-0.6.6/docs/Makefile +21 -0
- py_windblade_opa-0.6.6/docs/make.bat +35 -0
- py_windblade_opa-0.6.6/docs/source/_static/.gitkeep +0 -0
- py_windblade_opa-0.6.6/docs/source/api/airfoils.md +19 -0
- py_windblade_opa-0.6.6/docs/source/api/bem_hansen.md +37 -0
- py_windblade_opa-0.6.6/docs/source/api/blade_designer.md +16 -0
- py_windblade_opa-0.6.6/docs/source/api/blade_geometry.md +21 -0
- py_windblade_opa-0.6.6/docs/source/api/deol_orch.md +53 -0
- py_windblade_opa-0.6.6/docs/source/api/index.md +13 -0
- py_windblade_opa-0.6.6/docs/source/api/support.md +14 -0
- py_windblade_opa-0.6.6/docs/source/api/utils.md +8 -0
- py_windblade_opa-0.6.6/docs/source/conf.py +65 -0
- py_windblade_opa-0.6.6/docs/source/examples/bem_workflow.md +189 -0
- py_windblade_opa-0.6.6/docs/source/examples/deol_workflow.md +194 -0
- py_windblade_opa-0.6.6/docs/source/examples/index.md +10 -0
- py_windblade_opa-0.6.6/docs/source/examples/sample_performance_report.md +35 -0
- py_windblade_opa-0.6.6/docs/source/index.md +51 -0
- py_windblade_opa-0.6.6/docs/source/installation.md +54 -0
- py_windblade_opa-0.6.6/docs/source/quickstart.md +112 -0
- py_windblade_opa-0.6.6/docs/source/theory/bem.md +131 -0
- py_windblade_opa-0.6.6/docs/source/theory/blade_design.md +119 -0
- py_windblade_opa-0.6.6/docs/source/theory/deol.md +178 -0
- py_windblade_opa-0.6.6/docs/source/theory/index.md +39 -0
- py_windblade_opa-0.6.6/examples/_data/FFA-W3-CL_CD_CM_long.xlsx +0 -0
- py_windblade_opa-0.6.6/examples/_data/bladedata.txt +18 -0
- py_windblade_opa-0.6.6/examples/airfoils/plot_cl_cd.py +46 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/bem_hansen_geom2_poc.py +95 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/bem_hansen_v18_poc.py +185 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/data/FFA-W3-CL_CD_CM_long.xlsx +0 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/data/bladedata.txt +18 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/data/v18_ut_res/v1_8_T7P3df10_py.csv +11 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/example_v18_contour_plots.py +220 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/example_v18_cp_vs_ws.py +202 -0
- py_windblade_opa-0.6.6/examples/bem_hansen/hansen_markdown.md +85 -0
- py_windblade_opa-0.6.6/examples/deol_orch/blade_geom1.json +41 -0
- py_windblade_opa-0.6.6/examples/deol_orch/diag_deol_attack_angle_range.py +78 -0
- py_windblade_opa-0.6.6/examples/deol_orch/e105-blade_withgenerator/blade_geom1.json +41 -0
- py_windblade_opa-0.6.6/examples/deol_orch/e105-blade_withgenerator/example105-bladeGenerator.py +106 -0
- py_windblade_opa-0.6.6/examples/deol_orch/e106-pitch_variation/blade_geom1.json +41 -0
- py_windblade_opa-0.6.6/examples/deol_orch/e106-pitch_variation/example106-pitchvariation.py +85 -0
- py_windblade_opa-0.6.6/examples/deol_orch/e107-tests_confg/example107-test_config.py +134 -0
- py_windblade_opa-0.6.6/examples/deol_orch/example101.py +45 -0
- py_windblade_opa-0.6.6/examples/deol_orch/example102-bladeGeom.py +121 -0
- py_windblade_opa-0.6.6/examples/deol_orch/example103-benchmarking.py +28 -0
- py_windblade_opa-0.6.6/examples/energies-2999366/bg_koumgioutzoglou.json +43 -0
- py_windblade_opa-0.6.6/examples/energies-2999366/calcs-2999366.py +87 -0
- py_windblade_opa-0.6.6/examples/naca4415-blade1/bem_v18_blade1.py +196 -0
- py_windblade_opa-0.6.6/examples/naca4415-blade1/blade1_geom.json +43 -0
- py_windblade_opa-0.6.6/examples/naca4415-blade1/deol_blade1.py +180 -0
- py_windblade_opa-0.6.6/examples/naca4415-blade1/results/blade1_performance_data.csv +1201 -0
- py_windblade_opa-0.6.6/examples/naca4415-blade1/results/blade1_performance_data.xlsx +0 -0
- py_windblade_opa-0.6.6/examples/naca4415-blade1/results/cp_vs_lambda.csv +22 -0
- py_windblade_opa-0.6.6/justfile +40 -0
- py_windblade_opa-0.6.6/pyproject.toml +63 -0
- py_windblade_opa-0.6.6/reference/articles/36900.pdf +0 -0
- py_windblade_opa-0.6.6/reference/articles/Blade calculation.pdf +0 -0
- py_windblade_opa-0.6.6/reference/articles/Blade design.pdf +0 -0
- py_windblade_opa-0.6.6/reference/articles/blade.pdf +0 -0
- py_windblade_opa-0.6.6/reference/mermaid/Blade_Refactored.md +50 -0
- py_windblade_opa-0.6.6/reference/mermaid/Quantities.xlsx +0 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/BladeClass.md +345 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/s1_main_calculation.md +196 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/s2_calculate_i_flow.md +115 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/step3_eleven_coeffs.md +180 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/step4_coeffs_collection.md +93 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/step5_rpm_power.md +94 -0
- py_windblade_opa-0.6.6/reference/mermaid/all_in_one/step6_torque_calcs.md +94 -0
- py_windblade_opa-0.6.6/reference/mermaid/refactored/Calculate_Cf_Cm_L0.md +77 -0
- py_windblade_opa-0.6.6/reference/mermaid/refactored/blade_calc.docx +0 -0
- py_windblade_opa-0.6.6/reference/mermaid/refactored/blade_calc.md +309 -0
- py_windblade_opa-0.6.6/reference/mermaid/refactored/calc_Alternate.md +153 -0
- py_windblade_opa-0.6.6/reference/notes/airloils_reasoning.md +75 -0
- py_windblade_opa-0.6.6/reference/notes/flow_angles.md +55 -0
- py_windblade_opa-0.6.6/reference/notes/flow_angles.pdf +0 -0
- py_windblade_opa-0.6.6/reference/notes/images/energies-16-00945-g002.png +0 -0
- py_windblade_opa-0.6.6/reference/notes/readme.txt +1 -0
- py_windblade_opa-0.6.6/reference/wind_opa.docx +0 -0
- py_windblade_opa-0.6.6/reference/wind_opa.md +635 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/__init__.py +19 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/airfoils/__init__.py +1 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/airfoils/af_naca4415.py +75 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/airfoils/af_naca4415_test.py +78 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/airfoils/airfoil_abstract.py +48 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/airfoils/obsolete_cl.py +24 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/bem_hansen/__init__.py +5 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/bem_hansen/aero_coefficient_interpolator.py +219 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/bem_hansen/blade_aux_functions.py +257 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/bem_hansen/blade_performance_calculator.py +253 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/bem_hansen/data_models.py +25 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/bem_hansen/support_functions.py +16 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/blade_geometry.py +122 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/blade_geometry_v2.py +268 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/blade_plotter.py +146 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/__init__.py +0 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/_common.py +72 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/_components_array.py +63 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/_components_loop.py +127 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/blade_calc_orchestrator.py +249 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/data_models.py +35 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/deol_orch/refactoring.md +158 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/performance/__init__.py +12 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/performance/curve_data.py +30 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/performance/formulas.py +82 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/performance/post_processor.py +127 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/performance/report.py +94 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/support.py +79 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/utils.py +66 -0
- py_windblade_opa-0.6.6/src/py_windblade_opa/wel_blade_designer.py +177 -0
- py_windblade_opa-0.6.6/tests/airfoils/test_airfoils.py +23 -0
- py_windblade_opa-0.6.6/tests/bem_hansen/conftest.py +59 -0
- py_windblade_opa-0.6.6/tests/bem_hansen/test_aero_coefficient_interpolator.py +99 -0
- py_windblade_opa-0.6.6/tests/bem_hansen/test_blade_aux_functions.py +62 -0
- py_windblade_opa-0.6.6/tests/bem_hansen/test_blade_perofrmance_calculator.py +45 -0
- py_windblade_opa-0.6.6/tests/bem_hansen/test_performance_postprocessor.py +63 -0
- py_windblade_opa-0.6.6/tests/bem_hansen/test_support_functions.py +17 -0
- py_windblade_opa-0.6.6/tests/deol/conftest.py +46 -0
- py_windblade_opa-0.6.6/tests/deol/flow_components/test_flow_component.py +86 -0
- py_windblade_opa-0.6.6/tests/deol/test_blade_calc_L4.py +70 -0
- py_windblade_opa-0.6.6/tests/deol/test_blade_calc_l0.py +29 -0
- py_windblade_opa-0.6.6/tests/deol/test_blade_calc_l5_df_long.py +101 -0
- py_windblade_opa-0.6.6/tests/deol/test_blade_calc_uLCpNP.py +95 -0
- py_windblade_opa-0.6.6/tests/deol/test_blade_energy_yield.py +126 -0
- py_windblade_opa-0.6.6/tests/deol/test_blade_geometry.py +64 -0
- py_windblade_opa-0.6.6/tests/deol/test_cp_vs_lambda.py +87 -0
- py_windblade_opa-0.6.6/tests/deol/test_orchestrator_equivalence.py +221 -0
- py_windblade_opa-0.6.6/tests/deol/test_wel_designer.py +66 -0
- py_windblade_opa-0.6.6/tests/performance/test_report.py +52 -0
- py_windblade_opa-0.6.6/tests/test_blade_geometry_v2.py +95 -0
- py_windblade_opa-0.6.6/tests/test_support_classes.py +61 -0
- py_windblade_opa-0.6.6/uv.lock +4057 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# --- Core Python ---
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
.installed.cfg
|
|
8
|
+
*.egg
|
|
9
|
+
*.manifest
|
|
10
|
+
*.spec
|
|
11
|
+
|
|
12
|
+
# --- Distribution / Packaging ---
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# --- Installer Logs ---
|
|
30
|
+
pip-log.txt
|
|
31
|
+
pip-delete-this-directory.txt
|
|
32
|
+
|
|
33
|
+
# --- Testing & Code Quality ---
|
|
34
|
+
htmlcov/
|
|
35
|
+
.tox/
|
|
36
|
+
.nox/
|
|
37
|
+
.coverage
|
|
38
|
+
.coverage.*
|
|
39
|
+
.cache
|
|
40
|
+
nosetests.xml
|
|
41
|
+
coverage.xml
|
|
42
|
+
*.cover
|
|
43
|
+
*.py,cover
|
|
44
|
+
.hypothesis/
|
|
45
|
+
.pytest_cache/
|
|
46
|
+
cover/
|
|
47
|
+
|
|
48
|
+
# --- Modern Tooling (2026 Standards) ---
|
|
49
|
+
# Ruff (Linter/Formatter cache)
|
|
50
|
+
.ruff_cache/
|
|
51
|
+
|
|
52
|
+
# MyPy (Type checking cache)
|
|
53
|
+
.mypy_cache/
|
|
54
|
+
.dmypy.json
|
|
55
|
+
dmypy.json
|
|
56
|
+
|
|
57
|
+
# Hatch (Build artifacts)
|
|
58
|
+
.hatch/
|
|
59
|
+
|
|
60
|
+
# --- Documentation ---
|
|
61
|
+
# Sphinx
|
|
62
|
+
docs/_build/
|
|
63
|
+
# MkDocs
|
|
64
|
+
/site
|
|
65
|
+
|
|
66
|
+
# --- Jupyter Notebooks ---
|
|
67
|
+
.ipynb_checkpoints
|
|
68
|
+
profile_default/
|
|
69
|
+
ipython_config.py
|
|
70
|
+
|
|
71
|
+
# --- Environments ---
|
|
72
|
+
# Note: We do NOT ignore uv.lock. Commit it!
|
|
73
|
+
.env
|
|
74
|
+
.venv
|
|
75
|
+
env/
|
|
76
|
+
venv/
|
|
77
|
+
ENV/
|
|
78
|
+
|
|
79
|
+
# --- IDEs & Editors ---
|
|
80
|
+
# VS Code (User settings)
|
|
81
|
+
.vscode/
|
|
82
|
+
# PyCharm
|
|
83
|
+
.idea/
|
|
84
|
+
# Spyder
|
|
85
|
+
.spyderproject
|
|
86
|
+
.spyproject
|
|
87
|
+
# Rope
|
|
88
|
+
.ropeproject
|
|
89
|
+
|
|
90
|
+
# --- OS Generated Files (Windows/Mac) ---
|
|
91
|
+
Thumbs.db
|
|
92
|
+
Desktop.ini
|
|
93
|
+
.DS_Store
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Work in progress
|
|
2
|
+
|
|
3
|
+
- [x] replace logging with the recommended logger pattern in all src
|
|
4
|
+
|
|
5
|
+
# v0.6.5
|
|
6
|
+
|
|
7
|
+
**MAIN CHANGES:**:
|
|
8
|
+
|
|
9
|
+
- [x] Add a functionality that export into an md file the results of the analysis for the deol and the bem hansen
|
|
10
|
+
- [x] Streamlined the deol_orch and bem_hansen to use the new PerformanceCurve contract and remove the clean_data param from the PerformancePostProcessor. See design/ongoing/PerformancePostProcessor-and-MDReport.md §5.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# v0.6.1
|
|
15
|
+
|
|
16
|
+
**Main changes:**
|
|
17
|
+
|
|
18
|
+
- refactor: Cleaning up the deol code, to use the orchestrator version which is cleaner and more maintanable.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# History/TODO
|
|
2
|
+
|
|
3
|
+
# TODO
|
|
4
|
+
|
|
5
|
+
- [ ] BladeGeometry v2
|
|
6
|
+
- Create a class method for reading from json file
|
|
7
|
+
- Create Save to json method.
|
|
8
|
+
- Modifyt BladeAuxFunction class to have (composition) a BladeGeometryContainer instance.
|
|
9
|
+
- Decide whether this class will only hold geometry data or if it will alos provide convenience methods (that the BladeAuxFunction class currently implements)
|
|
10
|
+
- modify the deol code to use the BladeGeometryContainer class (instead of the previous implementation.)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
- [ ] FEAT: add airfoils in geometry JSON (Use Airfoil Factory)
|
|
14
|
+
- [ ] REF: merge steps 2 and 3 (create a single method for the calculation of the Cf, Cm and lambda0_final parametes)
|
|
15
|
+
- [ ] REF: merge steps 4,5
|
|
16
|
+
- [ ] FEAT: Save data to file in a useful way
|
|
17
|
+
- [ ] xlsx or csv
|
|
18
|
+
- [ ] decide if wide or long format is better (maybe provie both options?)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## DONE:
|
|
23
|
+
- Blade Geometry Container class
|
|
24
|
+
- Refactored BladeCalc Class
|
|
25
|
+
- [x] REF: merge steps 5,6 (create a single method for the all curves)
|
|
26
|
+
|
|
27
|
+
Testing:
|
|
28
|
+
- [x] TEST: test the curves_df method (brutal)
|
|
29
|
+
- [x] TEST: test the curves_df method (clean)
|
|
30
|
+
- [x] FEAT: add option for cleaning the data
|
|
31
|
+
- [x] TEST: Test option for cleaning the data (step5_curves_to_df)
|
|
32
|
+
- [x] FEAT: Added a state machine that will allow software to automatically collect only the curves_df data that have a physical meaning
|
|
33
|
+
- [x] FEAT: add an argument that enables or disables the state machine (Defaults to true)
|
|
34
|
+
- [x] FEAT: USE_LOOPS attribute inside class to allow quicker change
|
|
35
|
+
- [x] TEST: Added tests of LOOPS and ARRAY versions of code
|
|
36
|
+
- [x] TEST: use @pytest.mark.parametrize to reduce repetition in the tests (the loops and arrays methods should yield the same results)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## 0.1 (2024/07/03)
|
|
40
|
+
|
|
41
|
+
Released v0.1 which:
|
|
42
|
+
- has a Separate Blade Geometry Container class which is separate from the BladeCalc class
|
|
43
|
+
- Refactored BladeCalc Class to be more readble
|
|
44
|
+
- Different airfoils for a specific $\lambda_0$ are permitted (in the loops version - not yet in the arrays)
|
|
45
|
+
- Added an option for Using the different versions (arrays or loops) in the as aa module constant.
|
|
46
|
+
- Have enough tests
|
|
47
|
+
- Added several mermaid flowcharts for the main calculation steps (for the original and refactored)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Nikolaos Papadakis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py_windblade_opa
|
|
3
|
+
Version: 0.6.6
|
|
4
|
+
Summary: A package for the performance analysis and optimisation of wind turbine blades performance
|
|
5
|
+
Project-URL: Documentation, https://npapnet.github.io/py_windblade_opa/
|
|
6
|
+
Project-URL: Source, https://github.com/npapnet/py_windblade_opa
|
|
7
|
+
Author-email: "N. Papadakis" <npapnet@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Requires-Dist: matplotlib
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: openpyxl
|
|
17
|
+
Requires-Dist: pandas
|
|
18
|
+
Requires-Dist: plotnine>=0.15.2
|
|
19
|
+
Requires-Dist: scipy
|
|
20
|
+
Provides-Extra: docs
|
|
21
|
+
Requires-Dist: furo; extra == 'docs'
|
|
22
|
+
Requires-Dist: myst-parser; extra == 'docs'
|
|
23
|
+
Requires-Dist: sphinx-autobuild; extra == 'docs'
|
|
24
|
+
Requires-Dist: sphinx>=7.0; extra == 'docs'
|
|
25
|
+
Requires-Dist: sphinxcontrib-mermaid; extra == 'docs'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# py_windblade_opa
|
|
29
|
+
|
|
30
|
+
A python package for Windblade Optimization and Performance Assessment
|
|
31
|
+
|
|
32
|
+
Author: [N. Papadakis](https://github.com/npapnet).
|
|
33
|
+
|
|
34
|
+
## Scope
|
|
35
|
+
|
|
36
|
+
This package is intended to provide a set of tools for the optimization and performance assessment of wind turbine blades.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
## For Users
|
|
41
|
+
If you just want to use py_windblade_opa in your own projects, install the latest stable version from PyPI:
|
|
42
|
+
|
|
43
|
+
> pip install py-windblade-opa
|
|
44
|
+
|
|
45
|
+
## For Developers and Contributors
|
|
46
|
+
|
|
47
|
+
We offer two ways to set up the development environment. We strongly recommend using uv (the modern method) as it guarantees you are using the exact same dependencies and Python version as the maintainers.
|
|
48
|
+
|
|
49
|
+
### Option A: Using uv (Recommended)
|
|
50
|
+
|
|
51
|
+
This method automatically handles Python version management and dependency locking.
|
|
52
|
+
|
|
53
|
+
1. **Clone the repository**:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/npapnet/py_windblade_opa.git
|
|
57
|
+
cd py_windblade_opa
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
2. **Sync the environment**: This command creates the virtual environment, installs the specific Python version required, and sets up the package in editable mode, installing also all the development dependencies.
|
|
61
|
+
|
|
62
|
+
```Bash
|
|
63
|
+
uv sync --extra dev
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
3. **Run tests or scripts**: You can run commands inside the environment using `uv run`:
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
```Bash
|
|
70
|
+
# Run the test suite
|
|
71
|
+
uv run pytest
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# Run a script
|
|
75
|
+
uv run python examples/my_script.py
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Option B: Using Conda (Legacy)
|
|
79
|
+
If you prefer managing your own environments with Conda, you can install the package in "editable" mode using standard pip.
|
|
80
|
+
|
|
81
|
+
1. Clone the repository:
|
|
82
|
+
|
|
83
|
+
```Bash
|
|
84
|
+
git clone https://github.com/npapnet/py_windblade_opa.git
|
|
85
|
+
cd py_windblade_opa
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
2. Create and activate your Conda environment:
|
|
89
|
+
|
|
90
|
+
```Bash
|
|
91
|
+
conda create -n windblade python=3.13
|
|
92
|
+
conda activate windblade
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Install in editable mode: Note: You must use the [dev] flag to get testing tools like pytest and ruff.
|
|
96
|
+
|
|
97
|
+
```Bash
|
|
98
|
+
pip install -e .[dev]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Verify Installation
|
|
102
|
+
To confirm everything is working, run the following command (works for both methods):
|
|
103
|
+
|
|
104
|
+
```cmd
|
|
105
|
+
python -c "import py_windblade_opa; print(f'Successfully installed version {py_windblade_opa.__version__}')"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Usage
|
|
109
|
+
|
|
110
|
+
The package is still under development. The following is an example of how to use the package:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import py_windblade_opa as wbo
|
|
114
|
+
|
|
115
|
+
power = 1000
|
|
116
|
+
Cp = 0.45
|
|
117
|
+
n_elec = 0.95
|
|
118
|
+
v_nom = 10
|
|
119
|
+
reqs = Reqs(power_w=power, n_elec=n_elec, v_nom=v_nom, Cp=Cp)
|
|
120
|
+
|
|
121
|
+
constants = .wbo.Constants()
|
|
122
|
+
config = wbo.Config(lambda0=4.8, no_blades=3, pitch=0)
|
|
123
|
+
r_m = wbo.reqs.estimate_blade_r()
|
|
124
|
+
blade = wbo.Blade(r_m=r_m, wt_config=config)
|
|
125
|
+
blade_calc = wbo.BladeCalc(blade=blade)
|
|
126
|
+
|
|
127
|
+
blade.main_calculation()
|
|
128
|
+
blade_calc.calculate_i_flow(verbosePlot=False)
|
|
129
|
+
blade_calc.step3_eleven_coeffs(verbosePlot=False)
|
|
130
|
+
blade_calc.step4_coeffs_collection()
|
|
131
|
+
blade_calc.step5_rpm_power(verbosePlot=False)
|
|
132
|
+
blade_calc.step6_torque_calcs(verbosePlot=True)
|
|
133
|
+
|
|
134
|
+
plt.show()
|
|
135
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# py_windblade_opa
|
|
2
|
+
|
|
3
|
+
A python package for Windblade Optimization and Performance Assessment
|
|
4
|
+
|
|
5
|
+
Author: [N. Papadakis](https://github.com/npapnet).
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
|
|
9
|
+
This package is intended to provide a set of tools for the optimization and performance assessment of wind turbine blades.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
## For Users
|
|
14
|
+
If you just want to use py_windblade_opa in your own projects, install the latest stable version from PyPI:
|
|
15
|
+
|
|
16
|
+
> pip install py-windblade-opa
|
|
17
|
+
|
|
18
|
+
## For Developers and Contributors
|
|
19
|
+
|
|
20
|
+
We offer two ways to set up the development environment. We strongly recommend using uv (the modern method) as it guarantees you are using the exact same dependencies and Python version as the maintainers.
|
|
21
|
+
|
|
22
|
+
### Option A: Using uv (Recommended)
|
|
23
|
+
|
|
24
|
+
This method automatically handles Python version management and dependency locking.
|
|
25
|
+
|
|
26
|
+
1. **Clone the repository**:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/npapnet/py_windblade_opa.git
|
|
30
|
+
cd py_windblade_opa
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. **Sync the environment**: This command creates the virtual environment, installs the specific Python version required, and sets up the package in editable mode, installing also all the development dependencies.
|
|
34
|
+
|
|
35
|
+
```Bash
|
|
36
|
+
uv sync --extra dev
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
3. **Run tests or scripts**: You can run commands inside the environment using `uv run`:
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
```Bash
|
|
43
|
+
# Run the test suite
|
|
44
|
+
uv run pytest
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Run a script
|
|
48
|
+
uv run python examples/my_script.py
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Option B: Using Conda (Legacy)
|
|
52
|
+
If you prefer managing your own environments with Conda, you can install the package in "editable" mode using standard pip.
|
|
53
|
+
|
|
54
|
+
1. Clone the repository:
|
|
55
|
+
|
|
56
|
+
```Bash
|
|
57
|
+
git clone https://github.com/npapnet/py_windblade_opa.git
|
|
58
|
+
cd py_windblade_opa
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
2. Create and activate your Conda environment:
|
|
62
|
+
|
|
63
|
+
```Bash
|
|
64
|
+
conda create -n windblade python=3.13
|
|
65
|
+
conda activate windblade
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Install in editable mode: Note: You must use the [dev] flag to get testing tools like pytest and ruff.
|
|
69
|
+
|
|
70
|
+
```Bash
|
|
71
|
+
pip install -e .[dev]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Verify Installation
|
|
75
|
+
To confirm everything is working, run the following command (works for both methods):
|
|
76
|
+
|
|
77
|
+
```cmd
|
|
78
|
+
python -c "import py_windblade_opa; print(f'Successfully installed version {py_windblade_opa.__version__}')"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Usage
|
|
82
|
+
|
|
83
|
+
The package is still under development. The following is an example of how to use the package:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import py_windblade_opa as wbo
|
|
87
|
+
|
|
88
|
+
power = 1000
|
|
89
|
+
Cp = 0.45
|
|
90
|
+
n_elec = 0.95
|
|
91
|
+
v_nom = 10
|
|
92
|
+
reqs = Reqs(power_w=power, n_elec=n_elec, v_nom=v_nom, Cp=Cp)
|
|
93
|
+
|
|
94
|
+
constants = .wbo.Constants()
|
|
95
|
+
config = wbo.Config(lambda0=4.8, no_blades=3, pitch=0)
|
|
96
|
+
r_m = wbo.reqs.estimate_blade_r()
|
|
97
|
+
blade = wbo.Blade(r_m=r_m, wt_config=config)
|
|
98
|
+
blade_calc = wbo.BladeCalc(blade=blade)
|
|
99
|
+
|
|
100
|
+
blade.main_calculation()
|
|
101
|
+
blade_calc.calculate_i_flow(verbosePlot=False)
|
|
102
|
+
blade_calc.step3_eleven_coeffs(verbosePlot=False)
|
|
103
|
+
blade_calc.step4_coeffs_collection()
|
|
104
|
+
blade_calc.step5_rpm_power(verbosePlot=False)
|
|
105
|
+
blade_calc.step6_torque_calcs(verbosePlot=True)
|
|
106
|
+
|
|
107
|
+
plt.show()
|
|
108
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Design Vision
|
|
2
|
+
|
|
3
|
+
- I am inclined to move away from delegating to the engine the job of getting the
|
|
4
|
+
power curve. As this project pans out it makes more sense to have an overall object
|
|
5
|
+
that **HAS-A** geometry, an engine that consumes that geometry, and a post-processor
|
|
6
|
+
that consumes the output from the engine's contract. That will require reworking the
|
|
7
|
+
examples, so it might make sense to delegate that elsewhere. Develop contracts for
|
|
8
|
+
the geometry, engine, and post-processor.
|
|
9
|
+
- The current architecture, contracts, and the rule that **pitch and airfoil are not
|
|
10
|
+
part of geometry** are written up in [architecture.md](architecture.md). Keep it
|
|
11
|
+
current.
|
|
12
|
+
|
|
13
|
+
# Roadmap
|
|
14
|
+
|
|
15
|
+
**New session? Start with
|
|
16
|
+
[next_refactor/IMPLEMENTATION-STATUS.md](next_refactor/IMPLEMENTATION-STATUS.md)**
|
|
17
|
+
(status, house rules, decision log). Full rationale: [architecture.md](architecture.md)
|
|
18
|
+
§6. Four staged plans, 0.6.5 → 0.10.0:
|
|
19
|
+
|
|
20
|
+
- **Stage 2** — geometry V2 + pitch decoupling →
|
|
21
|
+
[next_refactor/Stage2-AddingGeometryV2.md](next_refactor/Stage2-AddingGeometryV2.md)
|
|
22
|
+
- **Stage 3** — airfoil abstraction (`AirfoilPolar` / `AirfoilProvider`; single +
|
|
23
|
+
family + custom data) →
|
|
24
|
+
[next_refactor/Stage3-AirfoilProvider.md](next_refactor/Stage3-AirfoilProvider.md)
|
|
25
|
+
- **Stage 4** — `Blade`/`Rotor` assembly + declarative definition →
|
|
26
|
+
[next_refactor/Stage4-RotorAssembly.md](next_refactor/Stage4-RotorAssembly.md)
|
|
27
|
+
- **Stage 5 / future** — top-level analysis object.
|
|
28
|
+
|
|
29
|
+
# Tasks
|
|
30
|
+
|
|
31
|
+
[x] Create an architecture.md describing the overall architecture → `design/architecture.md`.
|
|
32
|
+
|
|
33
|
+
[ ] **Stage 2** — geometry unification + pitch/airfoil decoupling (see doc; 0.6.5 → 0.8.0):
|
|
34
|
+
[ ] `BladeGeometryContainer` accepts scalar / `None` tcratio + extrapolating interpolators (`fix` 0.6.6).
|
|
35
|
+
[ ] Remove `pitch_deg` from geometry; designer twist is pitch-free; pitch applied once at the engine (`fix` 0.6.6).
|
|
36
|
+
[ ] `WELBladeDesigner.main_calculation()` returns `BladeGeometrySpec` with `to_v1()` / `to_v2()` (`feat` 0.6.7).
|
|
37
|
+
[ ] D1: add `NACA4415poly` (poly-sampled table), delete `NACAtest`; DEOL airfoil re-baseline on V1 (breaking minor 0.7.0).
|
|
38
|
+
[ ] D2: DEOL `BladeCalcOrchestrator` consumes V2 geometry; airfoil a separate (single) arg; `delta_r`/`np.trapz` grid re-baseline (breaking minor 0.8.0).
|
|
39
|
+
[ ] Update deol tests, fixtures, examples, docs.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
[ ] **Stage 3** — airfoil abstraction (see doc; 0.8.0 → 0.9.0):
|
|
44
|
+
[ ] R1 `feat` 0.8.1 — `AirfoilPolar` + `AirfoilProvider` + `UniformAirfoil` + `ThicknessInterpolatedFamily` + custom-data loaders (CSV/arrays/df/files); equivalence-gated vs `NACA4415` / `NACA4415poly` / `AeroCoefficientInterpolator`.
|
|
45
|
+
[ ] R2 `feat` 0.8.2 — engines + designer consume the provider; `t/c`→fraction normalization (BEM Cp–λ unchanged); WEL schedule isolated; DEOL family path enabled.
|
|
46
|
+
[ ] R3 minor 0.9.0 — retire V1 `BladeGeometry` (value-neutral, breaking API).
|
|
47
|
+
|
|
48
|
+
[ ] **Stage 4** — Blade/Rotor assembly + declarative definition (see doc; 0.9.0 → 0.10.0):
|
|
49
|
+
[ ] R1 `feat` 0.9.1 — `Blade`, `Rotor`, `OperatingPoint` (additive) + `Rotor.from_definition`/`to_definition` schema; `from_dtu`/`from_json` become adapters.
|
|
50
|
+
[ ] R2 minor 0.10.0 — engines adopt `analyze(rotor, op)`; `B`/set-pitch relocated to `Rotor`; geometry becomes single-blade; values unchanged vs 0.9.0.
|
|
51
|
+
[x] Naming review: `Blade` kept (decided 2026-06-19). `Rotor`/`OperatingPoint` names still open for Stage 4.
|
|
52
|
+
|
|
53
|
+
[ ] **Stage 5 / Future** — top-level analysis object (`RotorAnalysis`, name TBD) that
|
|
54
|
+
HAS-A {rotor, engine, post-processor}; reworks examples to one high-level API.
|
|
55
|
+
Formalize the GeometryProvider / AirfoilProvider / Engine→PerformanceCurve contracts.
|
|
56
|
+
|
|
57
|
+
# Chores
|
|
58
|
+
|
|
59
|
+
# Agent behaviour
|
|
60
|
+
|
|
61
|
+
- [x] make sure that the agent **recommends** freely a rename of the classes when a clearer name is available, and that it **does not** freely rename. The agent should be able to explain why a rename is recommended or not. *(Recorded as policy in architecture.md §7.)*
|
|
62
|
+
|
|
63
|
+
# REVISIT
|
|
64
|
+
|
|
65
|
+
[ ] **REVISIT (post Stage 2): fixed assembly-time pitch in `WELBladeDesigner`.**
|
|
66
|
+
Phase B made the designer twist pitch-free and moved pitch to a *runtime* engine
|
|
67
|
+
condition (removing the DEOL double-count). But `WELBladeDesigner` was intended for
|
|
68
|
+
**fixed-pitch blades**, where a `pitch` argument is meaningful: a fixed build/mounting
|
|
69
|
+
pitch baked into the *manufactured* twist, so `bl_a_i = bl_IiFlow - bl_ir - pitch` is
|
|
70
|
+
the as-built installed twist. The original term is preserved (commented, with a term
|
|
71
|
+
explanation) at `wel_blade_designer.py` `bl_a_i`. Decide later whether the designer
|
|
72
|
+
should expose an explicit *assembly-time* pitch (distinct from the engine's runtime
|
|
73
|
+
pitch) — likely settles alongside Stage 4 `Rotor`/`OperatingPoint` (where pitch lives).
|
|
74
|
+
Raised by N. Papadakis 2026-06-20.
|
|
75
|
+
|
|
76
|
+
# Private notes — (agent: do not modify this section and below without explicit instruction)
|
|
77
|
+
|
|
78
|
+
- scrub abandoned contracts, classes, and methods from the documents. e.g. cl_approx or cl_model in the airfoil context, after verifying the abandoment.
|
|
79
|
+
- consolidate the design notes to remove duplication, redudancy, and outdated information. Ensure that the design notes reflect the current architecture and decisions made. check numbering consistency, etc.
|