From b63fe05e4ed62836654c674b30af6b0599a1e769 Mon Sep 17 00:00:00 2001 From: kbonney Date: Thu, 27 Jul 2023 11:11:16 -0400 Subject: [PATCH] Overhauling docs. Cleaned up errors. Updated some paragraphs. --- docs/apidoc/pynumad.objects.rst | 1 + docs/apidoc/pynumad.utils.rst | 5 - docs/citation.rst | 12 +- docs/conf.py | 75 +---- docs/contributing.rst | 296 ++++++++++++-------- docs/getting-started.rst | 26 ++ docs/index.rst | 53 ++-- docs/installation.rst | 29 +- docs/overview.rst | 14 +- docs/publications.rst | 3 +- docs/refs/{userGuide.bib => conclusion.bib} | 0 docs/{ => refs}/publications.bib | 0 docs/release-notes.rst | 26 +- src/pynumad/io/excel_to_blade.py | 15 +- src/pynumad/io/yaml_to_blade.py | 32 ++- src/pynumad/objects/Airfoil.py | 61 ++-- src/pynumad/objects/Blade.py | 83 +++--- src/pynumad/objects/Material.py | 56 ++-- src/pynumad/utils/interpolation.py | 99 ++++--- 19 files changed, 443 insertions(+), 443 deletions(-) create mode 100644 docs/getting-started.rst rename docs/refs/{userGuide.bib => conclusion.bib} (100%) rename docs/{ => refs}/publications.bib (100%) diff --git a/docs/apidoc/pynumad.objects.rst b/docs/apidoc/pynumad.objects.rst index 97c521e..0d116cb 100644 --- a/docs/apidoc/pynumad.objects.rst +++ b/docs/apidoc/pynumad.objects.rst @@ -10,6 +10,7 @@ Submodules ---------- .. toctree:: + :maxdepth: 1 pynumad.objects.Airfoil pynumad.objects.Blade diff --git a/docs/apidoc/pynumad.utils.rst b/docs/apidoc/pynumad.utils.rst index 9874302..0881da9 100644 --- a/docs/apidoc/pynumad.utils.rst +++ b/docs/apidoc/pynumad.utils.rst @@ -11,11 +11,6 @@ pynumad.utils module :no-undoc-members: :show-inheritance: -.. automodule:: pynumad.utils.mesh_utils - :members: - :no-undoc-members: - :show-inheritance: - .. automodule:: pynumad.utils.misc_utils :members: :no-undoc-members: diff --git a/docs/citation.rst b/docs/citation.rst index 0ecb9cb..fbb4e11 100644 --- a/docs/citation.rst +++ b/docs/citation.rst @@ -5,10 +5,10 @@ Citing NuMAD To cite NuMAD v3.0, please utilize the reference below. +[1] Camarena, E., Anderson, E., Paquette, J., Bortolotti, P., Feil, R., +& Johnson, N. (2021). Land-based wind turbines with flexible rail +transportable blades–Part II: 3D FEM design optimization of the rotor +blades. Wind Energy Science Discussions, 1-28. -[1] Camarena, E., Anderson, E., Paquette, J., Bortolotti, P., Feil, R., & Johnson, N. (2021). Land-based wind turbines with flexible rail transportable blades–Part II: 3D FEM design optimization of the rotor blades. Wind Energy Science Discussions, 1-28. - - -.. Kelley: replace with DOI citation once release is tagged - - +.. + Kelley: replace with DOI citation once release is tagged diff --git a/docs/conf.py b/docs/conf.py index 7b10916..9233d87 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,19 +2,14 @@ # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- -import os -import sys # -- Project information ----------------------------------------------------- - project = 'PyNuMAD' copyright = '2023, Kirk Bonney' author = 'Kirk Bonney' - version = '1.0' release = '1.0' - # -- General configuration --------------------------------------------------- extensions = [ @@ -34,13 +29,9 @@ autodoc_member_order = 'bysource' autoclass_content = 'both' bibtex_bibfiles = ['refs/publications.bib','refs/conclusion.bib'] - templates_path = ['_templates'] - source_suffix = '.rst' - master_doc = 'index' - language = "en" # List of patterns, relative to source directory, that match files and @@ -55,7 +46,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -# + html_theme = 'sphinx_rtd_theme' # Add any paths that contain custom static files (such as style sheets) here, @@ -67,66 +58,4 @@ # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'PyNuMADdoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'PyNuMAD.tex', 'PyNuMAD Documentation', - 'Kirk Bonney', 'manual'), -] - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'pynumad', 'PyNuMAD Documentation', - [author], 1) -] - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'PyNuMAD', 'PyNuMAD Documentation', - author, 'PyNuMAD', 'One line description of project.', - 'Miscellaneous'), -] - - -# -- Extension configuration ------------------------------------------------- - -# -- Options for intersphinx extension --------------------------------------- - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} - -# -- Options for todo extension ---------------------------------------------- - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True \ No newline at end of file +htmlhelp_basename = 'PyNuMADdoc' \ No newline at end of file diff --git a/docs/contributing.rst b/docs/contributing.rst index b941b90..e96f5f7 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -4,187 +4,253 @@ Contributing ============ -Thank you for considering contributing to pyNuMAD. -We welcome contributions from the community in the form of bug fixes, feature -enhancements, documentation updates, etc. All contributions are processed -through pull-requests or issues on GitHub. Please follow these guidelines for contributing. +Thank you for considering contributing to pyNuMAD. We welcome +contributions from the community in the form of bug fixes, feature +enhancements, documentation updates, etc. All contributions are +processed through pull-requests or issues on GitHub. Please follow these +guidelines for contributing. + Reporting issues and bugs ------------------------- -This section guides you through the process of submitting an issue for pyNuMAD. -To report issues or bugs please `create a new -issue `_ on GitHub. - +This section guides you through the process of submitting an issue for +pyNuMAD. To report issues or bugs please `create a new issue +`_ on GitHub. + Following these guidelines will help maintainers understand your issue, -reproduce the behavior, and develop a fix in an expedient fashion. Before -submitting your bug report, please perform a cursory -search to see if the problem has been already reported. If it has been reported, and the -issue is still open, add a comment to the existing issue instead of opening a -new issue. +reproduce the behavior, and develop a fix in an expedient fashion. +Before submitting your bug report, please perform a cursory search to +see if the problem has been already reported. If it has been reported, +and the issue is still open, add a comment to the existing issue instead +of opening a new issue. Tips for effective bug reporting ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Use a clear descriptive title for the issue - -- Describe the steps to reproduce the problem, the behavior you observed after - following the steps, and the expected behavior - -- Provide the SHA ID of the git commit that you are using - -- For runtime errors, provide a function call stack - +- Use a clear descriptive title for the issue +- Describe the steps to reproduce the problem, the behavior you + observed after following the steps, and the expected behavior +- Provide the SHA ID of the git commit that you are using +- For runtime errors, provide a function call stack Submitting pull-requests ^^^^^^^^^^^^^^^^^^^^^^^^ Contributions can take the form of bug fixes, feature enhancements, -documentation updates. All updates to the repository are managed via `pull -requests `_. -One of the easiest ways to get started is by looking at `open -issues `_ and contributing fixes, -enhancements that address those issues. If your code contribution involves large -changes or additions to the codebase, we recommend opening an issue first and -discussing your proposed changes with the core development team to ensure that -your efforts are well directed, and so that your submission can be reviewed and -merged seamlessly by the maintenance team. +documentation updates. All updates to the repository are managed via +`pull requests +`_. +One of the easiest ways to get started is by looking at `open issues +`_ and contributing fixes, +enhancements that address those issues. If your code contribution +involves large changes or additions to the codebase, we recommend +opening an issue first and discussing your proposed changes with the +core development team to ensure that your efforts are well directed, and +so that your submission can be reviewed and merged seamlessly by the +maintenance team. Guidelines for preparing and submitting pull-requests ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Use a clear descriptive title for your pull-requests - -- Describe if your submission is a bugfix, documentation update, or a feature - enhancement. Provide a concise description of your proposed changes. - -- Provide references to open issues, if applicable, to provide the necessary - context to understand your pull request - -- Make sure that your pull-request merges cleanly with the `main` branch of - pyNuMAD. When working on a feature, always create your feature branch off of - the latest `main` commit - -- Ensure that the code compiles without warnings, (leave for later? the unit tests and regression - tests all pass without errors, and the documentation builds properly with your - modifications) - -- New physics models and code enhancements should be accompanied with relevant - updates to the documentation, supported by necessary verification and - validation, as well as unit tests and regression tests - - -Once a pull-request is submitted you will iterate with pyNuMAD maintainers -until your changes are in an acceptable state and can be merged in. You can push -addditional commits to the branch used to create the pull-request to reflect the -feedback from maintainers and users of the code. - - -Coding conventions -^^^^^^^^^^^^^^^^^^ - -These are the conventions we require. Note that these have not necessarily been followed in the past but moving forward the will: - -- We indent using four spaces (soft tabs) -- Moving forward we ALWAYS put spaces after list items and method parameters (`[1, 2, 3]`, not `[1,2,3]`), around operators (`x = 1`, not `x=1`), and around hash arrows. -- We use camelCase when naming functions and variables -- This is open source software. Consider the people who will read your code, and make it look nice for them. +- Use a clear descriptive title for your pull-requests + +- Describe if your submission is a bugfix, documentation update, or a + feature enhancement. Provide a concise description of your proposed + changes. + +- Provide references to open issues, if applicable, to provide the + necessary context to understand your pull request + +- Make sure that your pull-request merges cleanly with the `main` + branch of pyNuMAD. When working on a feature, always create your + feature branch off of the latest `main` commit +- Ensure that the code compiles without warnings, (leave for later? the + unit tests and regression tests all pass without errors, and the + documentation builds properly with your modifications) +- New physics models and code enhancements should be accompanied with + relevant updates to the documentation, supported by necessary + verification and validation, as well as unit tests and regression + tests + +Once a pull-request is submitted you will iterate with pyNuMAD +maintainers until your changes are in an acceptable state and can be +merged in. You can push addditional commits to the branch used to create +the pull-request to reflect the feedback from maintainers and users of +the code. + +Stylistic conventions +^^^^^^^^^^^^^^^^^^^^^ + +- Please `black `__ your code. + This enforces a standard style across the project with minimal + thought and effort + +- Please use `snake case `__ + for function and variable names. Developer Installation ---------------------- -To maintain a local installation, developers should use the following commands:: - - git clone https://github.com/sandialabs/pyNuMAD - cd pynumad - pip install -e . +To maintain a local installation, developers should use the following +commands: + +.. code:: + + git clone https://github.com/sandialabs/pyNuMAD + cd pynumad + pip install -e . Running Common Developer Tasks ------------------------------ -Many common developer tasks have been implemented through nox for convenient and consistent -results. The following subsections describe the various tasks available through nox. +Many common developer tasks have been implemented through nox for +convenient and consistent results. The following subsections describe +the various tasks available through the `nox `__ task-runner. Testing ^^^^^^^ -To run tests locally, run:: - nox -s tests +To run tests locally, run: + +.. code:: -at the root of the repository. Note that this requires the installation -of nox. + nox -s tests + +at the root of the repository. Formatting ^^^^^^^^^^ -To check if your code complies to the repositories standards run:: - nox -s style +To check if your code complies to the black style run: + +.. code:: + nox -s check_style -Black +at the root of the repository. If you find it does not, please run: + +.. code:: + + nox -s enforce_style Building Docs ^^^^^^^^^^^^^ -To build docs locally, navigate to ``pynumad/docs`` and run:: +To build docs locally, navigate to ``pynumad/docs`` and run: + +.. code:: - nox docs + nox -s docs After building, the static html files can be found in ``_build/html``. Serving Docs ^^^^^^^^^^^^ +To view the docs locally, navigate to ``pynumad/docs`` and run: + +.. code:: + + nox -s serve + Documentation ------------- -Conventions -^^^^^^^^^^^ - Docstrings ^^^^^^^^^^ -The documentation for pyNuMAD adheres to NumPy style docstrings. Not only does this -help to keep a consistent style, but it is also necessary for the API documentation -to be parsed and displayed correctly. For an example of what this should look like:: +The documentation for pyNuMAD adheres to NumPy style docstrings. Not +only does this help to keep a consistent style, but it is also necessary +for the API documentation to be parsed and displayed correctly. For an +example of what this should look like: + +.. code:: + + def func(arg1, arg2): + """Summary line. + + Extended description of function. + + Parameters + ---------- + arg1 : int + Description of arg1 + arg2 : str + Description of arg2 + + Returns + ------- + bool + Description of return value + + """ + return True + +Additional examples can be found in the `napoleon documentation +`_. +The following boilerplate can be copy-pasted into the top of a function +definition to help get things started: + +.. code:: + + """Summary line. + + Extended description of function. + + Parameters + ---------- - def func(arg1, arg2): - """Summary line. + Returns + ------- - Extended description of function. + """ - Parameters - ---------- - arg1 : int - Description of arg1 - arg2 : str - Description of arg2 +Extending PyNuMAD +----------------- - Returns - ------- - bool - Description of return value +Below we explain what to do when adding a top level directory +in the pyNuMAD source called ``new_mod/`` which contains a submodule called +``new_file.py``. - """ - return True +Exposing New Functionality to Users +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, any functions in ``new_file.py`` would not be automatically +available to users operating outside of the source directory. This is +to enforce a distinction between internal and external functionality. +Any functionality you wish to be accessed externally needs to be imported +inside the appropriate ``__init__.py`` file. For example, the ``__init__.py`` +file inside of ``new_mod/`` might look like:: -Additional examples can be found in the -`napoleon documentation `_. -The following boilerplate can be copy-pasted into the top of a function definition -to help get things started:: + from new_file import new_function - """Summary line. +and the ``__init__.py`` inside of ``src/`` might look like:: - Extended description of function. + import new_mod - Parameters - ---------- +This would allow a user to access the functionality by importing ``pynumad`` +and then running ``pynumad.new_mod.new_function``. If you wanted the call +to be accessed with ``pynumad.new_mod.new_file.new_function``, you would +replace ``from new_file import new_function`` with ``import new_file``. If +you are extending an already existing module, please follow the +existing convention within the corresponding ``__init__.py``. - Returns - ------- +Expanding the API Documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +New functionality for pyNuMAD should be properly documented +in the API documentation. A new folder-level module named ``new_mod/`` would +require the creation of the file ``docs/apidoc/pynumad.new_mod`` with +the contents recording any submodules that should be captured by the +API documentation. A new file named ``new_file.py`` added to an existing folder would +need the following code to capture its functionality in the auto api documentation:: + + .. automodule:: pynumad.new_mod.new_file + :members: + :no-undoc-members: + :show-inheritance: - """ +This will automatically capture all functions (internal and external) in ``new_file.py``. \ No newline at end of file diff --git a/docs/getting-started.rst b/docs/getting-started.rst new file mode 100644 index 0000000..baad8dd --- /dev/null +++ b/docs/getting-started.rst @@ -0,0 +1,26 @@ +.. _getting-started: + +Getting Started +=============== + +Initializing a blade object +--------------------------- + +After a successful installation, pyNuMAD can be imported in a python +session in the usual way:: + + import pynumad + +Next, to initialize an empty blade object run:: + + blade = pynumad.Blade() + +To populate the blade with a yaml or excel file you can run:: + + blade.load_yaml("path/to/yaml") + blade.load_excel("path/to/excel") + +or initialize the blade with the path:: + + blade = pynumad.Blade("path/to/yaml") + blade = pynumad.Blade("path/to/excel") \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 63d37f5..d980e89 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,10 +3,8 @@ .. figure:: /_static/images/NuMAD-header.png :target: https://github.com/sandialabs/NuMAD - -################################################################################## Numerical Manufacturing And Design (NuMAD) Tool for Wind Turbine Blades -################################################################################## +======================================================================= .. toctree:: :maxdepth: 2 @@ -14,40 +12,26 @@ Numerical Manufacturing And Design (NuMAD) Tool for Wind Turbine Blades installation overview + getting-started release-notes - contributing.rst + contributing apidoc/pynumad publications citation license - -.. include:: ../README.md - - The structural design and optimization of wind turbine blades is a complex task. In many cases it is difficult to find the optimal design of a turbine blade by hand, or by trial and error, and the software tools used for such designs are most effective when integrated into automated optimization and analysis algorithms. A new version of the -software tool `NuMAD (Numerical Manufacturing And Design) `_ for the design +software tool `pyNuMAD (Numerical Manufacturing And Design) `_ for the design and modeling of wind turbine blades is developed and described. -Newly released :ref:`NuMADv3` is structured to be run from a scripting environment -and easily called by optimization processes. -The previous release, :ref:`NuMADv2`, relied on the use of a graphical -user interface. Modifications were made to the MATLAB-based source code -to decouple the internal functions from the graphical user interface, -and additional functionality was added for convenience in performing -high-fidelity finite element analysis. NuMAD 3.0 has been successfully -implemented for optimization of large, flexible rotor blades, and is -suitable to be made available for public use. - - .. _developers: -NuMAD Developers +pyNuMAD Developers ===================== NuMAD has been developed by `Sandia National Laboratories @@ -57,27 +41,28 @@ funded by the U.S. Department of Energy’s Wind Energy Technologies Technologie Current members of the development team include: -* Joshua Paquette (“Josh”) (Sandia - PI) -* Evan Anderson (Sandia) -* Ernesto Camarena (Sandia) -* Ryan James Clarke (Sandia) -* Kirk Bonney (Sandia) +- Joshua Paquette (“Josh”) (Sandia - PI) +- Evan Anderson (Sandia) +- Ernesto Camarena (Sandia) +- Ryan James Clarke (Sandia) +- Kirk Bonney (Sandia) Former members of the development team include: -* Jonathan Charles Berg -* Brian Resor -* Daniel Laird -* Kelley Ruehl (Sandia) -* Christopher Lee Kelley (Sandia) -* Brandon Lee Ennis (Sandia) +- Jonathan Charles Berg +- Brian Resor +- Daniel Laird +- Kelley Ruehl (Sandia) +- Christopher Lee Kelley (Sandia) +- Brandon Lee Ennis (Sandia) Funding ======= Development and maintenance of the NuMAD code is funded by the U.S. Department of Energy’s Wind Energy Technologies Office. - -Sandia National Laboratories is a multi-mission laboratory managed and operated by National Technology and Engineering Solutions of Sandia, LLC., a wholly owned subsidiary of Honeywell International, Inc., for the U.S. Department of Energy’s National Nuclear Security Administration under contract DE-NA0003525. +Sandia National Laboratories is a multi-mission laboratory managed and operated by National Technology and Engineering Solutions +of Sandia, LLC., a wholly owned subsidiary of Honeywell International, Inc., for the U.S. Department of Energy’s +National Nuclear Security Administration under contract DE-NA0003525. Indices and tables ================== diff --git a/docs/installation.rst b/docs/installation.rst index f63f8ff..4023b19 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -16,12 +16,7 @@ These updates may improve the code's speed, accuracy and add additional function To download pyNuMAD using `git `_, type the following in a git interface:: - git clone https://cee-gitlab.sandia.gov/ecamare/pyNuMAD.git - -The local copy of pyNuMAD can easily be updated to the latest version of the -code hosted on the GitHub repository by using the pull command:: - - git pull + git clone https://github.com/sandialabs/pyNuMAD Installation ------------ @@ -33,25 +28,3 @@ the following command in the root of the repository:: Developers are recommended to install using the instructions on :ref:`contributing` page. - -Initializing a blade object ---------------------------- - -After a successful installation, pyNuMAD can be imported in a python -session in the usual way:: - - import pynumad - -Next, to initialize an empty blade object run:: - - blade = pynumad.Blade() - -To populate the blade with a yaml or excel file you can run:: - - blade.load_yaml("path/to/yaml") - blade.load_excel("path/to/excel") - -or initialize the blade with the path:: - - blade = pynumad.Blade("path/to/yaml") - blade = pynumad.Blade("path/to/excel") diff --git a/docs/overview.rst b/docs/overview.rst index 2e23ec3..de09e8c 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -3,25 +3,23 @@ Overview ======================= -`NuMAD (Numerical Manufacturing And Design) `_ is an +`pyNuMAD (Python Numerical Manufacturing And Design) `_ is an open-source software program written in -`MATLAB `__ which simplifies the process of +`Python `__ which simplifies the process of creating a three-dimensional model of a wind turbine blade. The tool manages all blade information including aerodynamic, and material properties as well as, material placement. The blade information can be -modified by a structural-optimizer in NuMAD or it can be used to run the +modified by a structural-optimizer in pyNuMAD or it can be used to run the other tools below in a stand-alone mode: - The `ANSYS® `__ commercial finite element package -- The NWTC codes PreComp, - `BModes `__, and - `FAST `__, +- `Abaqus `__ -- PLOT3D file format for CFD mesh building +- `Cubit `__ -When used in conjunction with these other tools, NuMAD provides +When used in conjunction with these other tools, pyNuMAD provides computation of blade cross section properties, various structural analyses, and estimation of blade aeroelastic instability. diff --git a/docs/publications.rst b/docs/publications.rst index 45c6c2f..7820b5e 100644 --- a/docs/publications.rst +++ b/docs/publications.rst @@ -6,4 +6,5 @@ Publications Here is a list of publications regarding NuMAD. The list includes publications written by the NuMAD team about the development and application of NuMAD as well as publications written by users of the NuMAD code outside of the NuMAD development team. -.. bibliography:: ../refs/publications.bib +.. bibliography:: refs/publications.bib + :all: \ No newline at end of file diff --git a/docs/refs/userGuide.bib b/docs/refs/conclusion.bib similarity index 100% rename from docs/refs/userGuide.bib rename to docs/refs/conclusion.bib diff --git a/docs/publications.bib b/docs/refs/publications.bib similarity index 100% rename from docs/publications.bib rename to docs/refs/publications.bib diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 61086bf..7531f4e 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -3,11 +3,33 @@ Release Notes ============= +.. _pyNuMADv0x: + +pyNuMAD 0.X +----------- + +Core functionality from previous incarnations of the NuMAD software +framework have been translated to the Python programming language +under the name PyNuMAD. Following the changes made in NuMAD 3.0, +PyNuMAD focuses on an object-oriented approach to blade design. + +Below is a summary of key features currently available: + +- Reading in blade definitions from YAML and Excel files to a Blade object. +- Creation of FEA mesh for use in analytical tools such as Abaqus or Cubit. +- Limited visualization tools for exploring a blade object's attributes. + +A stable version of PyNuMAD is still in development. Future goals include: + +- Expanding the YAML reading functionality to handle a wider variety of inputs. +- Driver codes for connecting PyNuMAD directly to other design softwares. +- Optimization tools for blade design. + .. _NuMADv3: NuMAD v3.0 ---------------- -The current release now incorporates structural optimization, associated +This previous MATLAB release incorporates structural optimization, associated structural analyses, and the move to object-oriented data structures. The exclusive use of the GUI in prior versions prevented automation in optimizations. Thus, moving to these data structures enabled @@ -38,8 +60,8 @@ analyses, and the object-oriented data structures. blades”. - Click `here `_ for NuMAD v3.0 -.. Kelley: add DOI +.. Kelley: add DOI .. _FutureDev: diff --git a/src/pynumad/io/excel_to_blade.py b/src/pynumad/io/excel_to_blade.py index ab69299..fddfcb6 100644 --- a/src/pynumad/io/excel_to_blade.py +++ b/src/pynumad/io/excel_to_blade.py @@ -1,5 +1,7 @@ import numpy as np import pandas as pd +import os + from pynumad.objects.Component import Component from pynumad.objects.Material import Material from pynumad.utils.interpolation import interpolator_wrap @@ -7,7 +9,7 @@ data_dir = DATA_PATH -def excel_to_blade(blade, filename = None): +def excel_to_blade(blade, filename): """ xlsBlade Construct BladeDef object with inputs from spreadsheet. @@ -23,15 +25,10 @@ def excel_to_blade(blade, filename = None): Example ------- - blade = xlsBlade(FILENAME); - - See also BladeDef - if not ('filename' is not None) or len(filename)==0: - raise Exception('xlsBlade:NoInput','No input file specified.') - - if not os.path.exist(str(filename)) : - raise Exception('xlsBlade:FileNotFound','File {} not found.'.format(filename)) + blade = xlsBlade(FILENAME) """ + if not os.path.exist(filename): + raise FileNotFoundError MPa_to_Pa = 1000000.0 # Dictionary containing column indices diff --git a/src/pynumad/io/yaml_to_blade.py b/src/pynumad/io/yaml_to_blade.py index 47808c4..30d936c 100644 --- a/src/pynumad/io/yaml_to_blade.py +++ b/src/pynumad/io/yaml_to_blade.py @@ -452,27 +452,29 @@ def _add_components(blade, blade_internal_structure, spar_hp, spar_lp): return -def writeNuMADAirfoil(coords, reftext, fname): - """ - WriteNuMADAirfoil Write NuMAD airfoil files - ********************************************************************** - * Part of the SNL NuMAD Toolbox * - * Developed by Sandia National Laboratories Wind Energy Technologies * - * See license.txt for disclaimer information * - ********************************************************************** - WriteNuMADAirfoil(coords,reftext,fname) - - fname - full filename, incl extension, of NuMAD airfoil file to write - coords - Nx2 array of airfoil coordinate data. First column contains +def writeNuMADAirfoil(coords, reftext, fname): + """WriteNuMADAirfoil Write NuMAD airfoil files + + Parameters + ---------- + coords : array + Nx2 array of airfoil coordinate data. First column contains x-values, second column contains y-values. Airfoil coordinates are in order as specified by NuMAD (i.e. trailing edge = (1,0) and leading edge = (0,0) - reftext = string representing reference text + reftext : string + string representing reference text + fname : string + full filename, incl extension, of NuMAD airfoil file to write + + Returns + ------- + None """ with open(fname,'wt') as fid: fid.write('\n%s\n' % (reftext)) fid.write('\n' % ()) for i in range(coords.shape[0]): fid.write('%8.12f\t%8.12f\n' % tuple(coords[i,:])) - - fid.write('' % ()) \ No newline at end of file + fid.write('' % ()) + return \ No newline at end of file diff --git a/src/pynumad/objects/Airfoil.py b/src/pynumad/objects/Airfoil.py index e201d27..1e2ef68 100644 --- a/src/pynumad/objects/Airfoil.py +++ b/src/pynumad/objects/Airfoil.py @@ -1,12 +1,8 @@ -######################################################################## -# Part of the SNL NuMAD Toolbox # -# Developed by Sandia National Laboratories Wind Energy Technologies # -# See license.txt for disclaimer information # -######################################################################## - import re import numpy as np +from typing import Self + import os import matplotlib.pyplot as plt import warnings @@ -42,11 +38,11 @@ class Airfoil(): camber : array Camber line as a function of x. Distance in percent chord between LP and HP curves. - Computed by NuAMD. + Computed by pyNuMAD. thickness : float Relative thickness as a function of the x coordinate. Values between 0 and 1, where 1 corresponds to maximum thickness. - Computed by NuAMD. + Computed by pyNuMAD. percentthick : float Maximum airfoil thickness as a percentage of chord length [#] maxthick : float @@ -142,7 +138,7 @@ def read_xml(self, filename): return self - def manageTE(self) -> None: + def manageTE(self) -> Self: """TODO docstring Parameters @@ -173,28 +169,32 @@ def manageTE(self) -> None: ### Geometry - def resample(self,n_samples: int = 150,spacing: str = 'cosine') -> None: - """TODO docstring + def resample(self,n_samples: int = 150,spacing: str = 'cosine') -> Self: + """Resample airfoil coordinates Parameters ---------- - + n_samples : int + Defaults to 150 + spacing : str + spacing method for new samples + spacing = 'auto' | 'half-cosine' | 'cosine' + Returns ------- - + None + Example ------- AirfoilDef.resample af.resample(n_samples,spacing) - spacing = 'auto' | 'half-cosine' | 'cosine' - af.resample(200,'half-cosine'); """ af_out = resampleAirfoil(self.coordinates,n_samples,spacing) xcoord = af_out[:,0] ycoord = af_out[:,1] # self(k).percentthick = (max(ycoord) - min(ycoord))*100; - self.c,self.camber,self.thickness = computeCamberAndThickness(xcoord,ycoord) + self.c, self.camber, self.thickness = computeCamberAndThickness(xcoord,ycoord) m = np.max(self.thickness) i = np.argmax(self.thickness) self.percentthick = m * 100 @@ -204,16 +204,23 @@ def resample(self,n_samples: int = 150,spacing: str = 'cosine') -> None: self.TEtype = 'sharp' else: self.TEtype = 'flatback' - return self + return Self #currently unused - def adjustTE(self, tet, tes, onset) -> None: + def adjustTE(self, tet, tes, onset) -> Self: """TODO docstring Parameters ---------- - + tet : + the amount of TE thickness to add + tes : + the slope of the added thickness profile at TE, + defaults to 5/3 * TE_thick + onset : + the chord fraction where adjustment begins, + defaults to location of max thickness Returns ------- @@ -221,15 +228,9 @@ def adjustTE(self, tet, tes, onset) -> None: ------- AirfoilDef.adjustTE af.adjustTE(TE_thick,[TE_slope],[onset]) - TE_thick is the amount of TE thickness to add - TE_slope is the slope of the added thickness profile at TE, - defaults to 5/3 * TE_thick - onset is the chord fraction where adjustment begins, - defaults to location of max thickness - - af.adjustTE(0.02); - af.adjustTE(0.02,0); - af.adjustTE(0.02,[],0.8); + af.adjustTE(0.02) + af.adjustTE(0.02,0) + af.adjustTE(0.02,[],0.8) """ if not tes: @@ -250,7 +251,7 @@ def adjustTE(self, tet, tes, onset) -> None: mc = np.amax((self.c - onset) / (1 - onset),0) temod = np.array([mc ** 3,mc ** 4,mc ** 5,mc ** 6]) * p self.thickness = self.thickness + temod - pass + return self ### Plotting @@ -273,7 +274,7 @@ def plotAirfoil(self): ### Helper functions -def resampleAirfoil(af_in, n_samples, spacing): +def resampleAirfoil(af_in, n_samples, spacing) -> Self: """Resample airfoil coordinates Parameters diff --git a/src/pynumad/objects/Blade.py b/src/pynumad/objects/Blade.py index 0b2706f..0d6576f 100644 --- a/src/pynumad/objects/Blade.py +++ b/src/pynumad/objects/Blade.py @@ -1,9 +1,3 @@ -######################################################################## -# Part of the SNL NuMAD Toolbox # -# Developed by Sandia National Laboratories Wind Energy Technologies # -# See license.txt for disclaimer information # -######################################################################## - import re, warnings import numpy as np from copy import copy @@ -22,10 +16,10 @@ class Blade(): """BladeDef A class definition for wind & water turbine blades. - + Parameters ---------- - file : string + filename : string Attributes ---------- @@ -36,62 +30,62 @@ class Blade(): chordoffset : array Chordwise offset (in addition to natural offset) components : list - Blade components such as spar, panels, etc., refer to ``ComponentDef`` + Blade components such as spar, panels, etc., refer to ``ComponentDef`` degreestwist : array - Twist distribution [degrees] + Twist distribution [degrees] ispan : array - Spanwise locations of interpolated output + Spanwise locations of interpolated output leband : float - Location of keypoint a + Location of keypoint a materials : list - Material properties, refer to ``MaterialDef`` + Material properties, refer to ``MaterialDef`` mesh : float - Approximate element edge size for FE model [m] + Approximate element edge size for FE model [m] percentthick : array - Percent thickness of airfoil [%] + Percent thickness of airfoil [%] prebend : array - Blade prebend, reference axis location along x2 [m] + Blade prebend, reference axis location along x2 [m] span : array - Spanwise location of distributed properties [m] + Spanwise location of distributed properties [m] sparcapoffset : array - (Does Nothing) + (Does Nothing) sparcapwidth : array - Locations of keypoints b & c, defines distance + Locations of keypoints b & c, defines distance between keypoints b & c [mm]. First entry is the HP spar cap. Second entry is the LP spar cap stations : list - Blade Stations, define the camber and thickness along the blade, + Blade Stations, define the camber and thickness along the blade, refer to ``StationDef`` sweep : array - Blade Sweep, Reference axis location along x1 [m] - self.teband + Blade Sweep, Reference axis location along x1 [m] + self.teband : float idegreestwist : array - interpolated twist + interpolated twist ichord : array - interpolated chord + interpolated chord ipercentthick : array - interpolated thickness - self.ic = array - self.icamber = array - self.ithickness = array + interpolated thickness + self.ic : array + self.icamber : array + self.ithickness : array ichordoffset : array - interpolated offset + interpolated offset iaerocenter : array - interpolated aerocenter + interpolated aerocenter isweep : array - interpolated sweep + interpolated sweep iprebend : array - interpolated prebend + interpolated prebend xoffset : array - natural offset + natural offset profiles : array - normalized airfoil profiles + normalized airfoil profiles geometry : array - actual x,y,z geometry + actual x,y,z geometry arclength : array - surface distance from L.E. + surface distance from L.E. cpos : array - chordwise position + chordwise position LEindex : int HParcx0 : array LParcx0 : array @@ -112,13 +106,13 @@ class Blade(): bom : dict bomIndices : dict stacks : array - array of StackDef + array of StackDef swstacks : list - contains StackDefs + contains StackDefs matdb : dict - Composite definition for each region at each station + Composite definition for each region at each station TEtype : list - trailing edge type; assigned in updateKeypoints + trailing edge type; assigned in updateKeypoints shearweb : list bomPlot : dict hgGeometry : list @@ -128,15 +122,14 @@ class Blade(): ansys : dict generate ANSYS settings write_airfoils : bool + Example ------- - ``blade = BladeDef();`` - - See also ``BladeDef_to_NuMADfile``, ``xlsBlade``, ``AirfoilDef``, - ``StationDef``, ``ComponentDef``, ``StackDef`` + blade = BladeDef() """ def __init__(self, filename: str = None): + self.aerocenter : ndarray = None self.chord : ndarray = None self.chordoffset : ndarray = None diff --git a/src/pynumad/objects/Material.py b/src/pynumad/objects/Material.py index 58da3c9..2e0a78e 100644 --- a/src/pynumad/objects/Material.py +++ b/src/pynumad/objects/Material.py @@ -10,73 +10,71 @@ class Material(): Parameters ---------- - + Attributes ---------- name : str - User selected name of the material + User selected name of the material type : str - Two options: isotropic or orthotropic + Two options: isotropic or orthotropic layerthickness : float - Layer thickness [mm] + Layer thickness [mm] ex : float - Longitudinal elastic modulus [Pa] + Longitudinal elastic modulus [Pa] ey : float - Transverse elastic modulus [Pa] + Transverse elastic modulus [Pa] ez : float Through-the-thickness elastic modulus in the - principal material coordinates [Pa] + principal material coordinates [Pa] gxy : float - In-plane shear modulus [Pa] + In-plane shear modulus [Pa] gyz : float - Transverse shear modulus [Pa] + Transverse shear modulus [Pa] gxz : float - Transverse shear modulus [Pa] + Transverse shear modulus [Pa] prxy : float - In-plane Poisson ratio [ ] + In-plane Poisson ratio [ ] pryz : float - Transverse Poisson ratio [ ] + Transverse Poisson ratio [ ] prxz : float - Transverse Poisson ratio [ ] + Transverse Poisson ratio [ ] density : float - Cured mass density [kg/m2] + Cured mass density [kg/m2] drydensity : float - Density of fabric + Density of fabric uts : float 1 x 3 array of ultimate tensile strength design values. Sequence: SL , ST, Sz, 1 x 1 for isotropic. ucs : float 1 x 3 array of ultimate compressive strength design values. - Sequence: SL , ST, Sz, 1 x 1 for isotropic. + Sequence: SL , ST, Sz, 1 x 1 for isotropic. uss : float 1 x 3 array of ultimate shear strength design values. Sequence: SLT , STz, SLz, 1 x 1 for isotropic. xzit : float - Lz tensile inclination parameter for Puck failure index + Lz tensile inclination parameter for Puck failure index xzic : float - Lz compressive inclination parameter for Puck failure index + Lz compressive inclination parameter for Puck failure index yzit : float - Tz tensile inclination parameter for Puck failure index + Tz tensile inclination parameter for Puck failure index yzic : float - Tz compressive inclination parameter for Puck failure index + Tz compressive inclination parameter for Puck failure index g1g2 : float - Fracture toughness ratio between GI (mode I) and GII (mode II) [ ] + Fracture toughness ratio between GI (mode I) and GII (mode II) [ ] alp0 : float - Fracture angle under pure transverse compression [degrees] + Fracture angle under pure transverse compression [degrees] etat : float - Transverse friction coefficient for Larc [ ] + Transverse friction coefficient for Larc [ ] etal : float - Longitudinal friction coefficient for Larc [ ] + Longitudinal friction coefficient for Larc [ ] m : list - Fatigue slope exponent [ ] + Fatigue slope exponent [ ] gamma_mf : list - from DNL-GL standard, fatigue strength reduction factor + from DNL-GL standard, fatigue strength reduction factor gamma_ms : list - from DNV-GL standard, short term strength reduction factor + from DNV-GL standard, short term strength reduction factor reference : str = None - Examples - -------- """ def __init__(self): self.name: str = None # User selected name of the material diff --git a/src/pynumad/utils/interpolation.py b/src/pynumad/utils/interpolation.py index 08ad8f7..1e9d027 100644 --- a/src/pynumad/utils/interpolation.py +++ b/src/pynumad/utils/interpolation.py @@ -4,64 +4,77 @@ PPoly, CubicSpline -def interpolator_wrap(x,v,xq,method = 'linear',axis = 0, extrapolation = None): +def interpolator_wrap(x, v, xq, method = 'linear', axis = 0, extrapolation = None): """This function is designed to emulate the arg structure and output of matlabs interp1d function. + + Parameters + ---------- + x : array + v : array + xq : array + method : str + Defaults to 'linear'. + axis : int + Defaults to 0. + extrapolation :bool + Defaults to None. + + Returns: + array : """ if method == 'linear': interpolator = interp1d(x,v,'linear', axis,bounds_error=False, fill_value= 'extrapolate') vq = interpolator(xq) - return vq - if method == 'pchip': + elif method == 'pchip': interpolator = PchipInterpolator(x,v,axis,extrapolate=True) vq = interpolator(xq) - return vq - if method == 'spline': + elif method == 'spline': interpolator = interp1d(x,v,'cubic', axis,bounds_error=False,fill_value='extrapolate') vq = interpolator(xq) - return vq - if method == 'pp': - pass - if method == 'v5cubic': - raise Exception("Method error for interpolator_wrap. 'v5cubic' not implemented") - if method == 'makima': - raise Exception("Method error for interpolator_wrap. 'makima' not implemented") - if method == 'nearest': - raise Exception("Method error for interpolator_wrap. 'nearest' not implemented") - if method == 'next': - raise Exception("Method error for interpolator_wrap. 'next' not implemented") - if method == 'previous': - raise Exception("Method error for interpolator_wrap. 'previous' not implemented") + return vq + # if method == 'pp': + # pass + # if method == 'v5cubic': + # raise Exception("Method error for interpolator_wrap. 'v5cubic' not implemented") + # if method == 'makima': + # raise Exception("Method error for interpolator_wrap. 'makima' not implemented") + # if method == 'nearest': + # raise Exception("Method error for interpolator_wrap. 'nearest' not implemented") + # if method == 'next': + # raise Exception("Method error for interpolator_wrap. 'next' not implemented") + # if method == 'previous': + # raise Exception("Method error for interpolator_wrap. 'previous' not implemented") def calcGenLinePP(blade_struct: dict): - """Calculate blade reference line piecewise polynomials - blade_struct = calcGenLinePP(blade_struct) updates the piecewise - polynomial representation of the blade's Presweep and Precurve - reference lines. This function is called by NuMAD_genline. + # TODO: docstring + # Calculate blade reference line piecewise polynomials + # blade_struct = calcGenLinePP(blade_struct) updates the piecewise + # polynomial representation of the blade's Presweep and Precurve + # reference lines. This function is called by NuMAD_genline. - The fields PresweepRef and PrecurveRef are required in blade_struct. - Each of these fields has the following data structure: - method: 'normal' | 'shear' - This field is not used by calcGenLinePP. - table: N-by-3 matrix with columns span,offset,slope - This table provides the offset and slope constraints of the - reference line at specific spanwise locations along the - blade. NaN may be used wherever a constraint is not - desired. - pptype: 'poly' | 'spline' | 'pchip' | 'linear' | 'disabled' - This field selects the interpolation method to use to - create the piecewise polynomial - poly = minimum order polynomial which satisfies all constraints - spline = cubic spline (offset constraints only) - pchip = shape-preserving cubic spline (offset constraints only) - linear = linear interpolation (offset constraints only) - disabled = returns straight line - pp: piecewise polynomial data created by this function - dpp: piecewise polynomial data of reference line's derivative + # The fields PresweepRef and PrecurveRef are required in blade_struct. + # Each of these fields has the following data structure: + # method: 'normal' | 'shear' + # This field is not used by calcGenLinePP. + # table: N-by-3 matrix with columns span,offset,slope + # This table provides the offset and slope constraints of the + # reference line at specific spanwise locations along the + # blade. NaN may be used wherever a constraint is not + # desired. + # pptype: 'poly' | 'spline' | 'pchip' | 'linear' | 'disabled' + # This field selects the interpolation method to use to + # create the piecewise polynomial + # poly = minimum order polynomial which satisfies all constraints + # spline = cubic spline (offset constraints only) + # pchip = shape-preserving cubic spline (offset constraints only) + # linear = linear interpolation (offset constraints only) + # disabled = returns straight line + # pp: piecewise polynomial data created by this function + # dpp: piecewise polynomial data of reference line's derivative - See also NuMAD_genline, PPoly, interp1. - """ + # See also NuMAD_genline, PPoly, interp1. # PresweepRef spline_type = blade_struct["PresweepRef"]["pptype"]