diff --git a/docs/apidoc/pynumad.analysis.ansys.rst b/docs/apidoc/pynumad.analysis.ansys.rst index 8c5e07d..5bf710f 100644 --- a/docs/apidoc/pynumad.analysis.ansys.rst +++ b/docs/apidoc/pynumad.analysis.ansys.rst @@ -1,7 +1,42 @@ Ansys Analysis ============== -.. automodule:: pynumad.analysis.ansys +main_ansys_analysis +------------------- + +.. automodule:: pynumad.analysis.ansys.main_ansys_analysis + :members: + :no-undoc-members: + :show-inheritance: + +read +---- + +.. automodule:: pynumad.analysis.ansys.read + :members: + :no-undoc-members: + :show-inheritance: + +run +--- + +.. automodule:: pynumad.analysis.ansys.run + :members: + :no-undoc-members: + :show-inheritance: + +utility +------- + +.. automodule:: pynumad.analysis.ansys.utility + :members: + :no-undoc-members: + :show-inheritance: + +write +------- + +.. automodule:: pynumad.analysis.ansys.write :members: :no-undoc-members: :show-inheritance: \ No newline at end of file diff --git a/docs/apidoc/pynumad.analysis.cubit.rst b/docs/apidoc/pynumad.analysis.cubit.rst index 42596bb..9b4e7c3 100644 --- a/docs/apidoc/pynumad.analysis.cubit.rst +++ b/docs/apidoc/pynumad.analysis.cubit.rst @@ -1,16 +1,26 @@ Cubit Meshing ============== -.. automodule:: pynumad.analysis.cubit +make_blade +---------- + +.. automodule:: pynumad.analysis.cubit.make_blade :members: :no-undoc-members: :show-inheritance: +connect_cross_sections +---------------------- -Submodules ----------- +.. automodule:: pynumad.analysis.cubit.connect_cross_sections + :members: + :no-undoc-members: + :show-inheritance: + +make_cross_sections +------------------- -.. toctree:: - :maxdepth: 1 - - pynumad.analysis.cubit.make_blade \ No newline at end of file +.. automodule:: pynumad.analysis.cubit.make_cross_sections + :members: + :no-undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/docs/apidoc/pynumad.rst b/docs/apidoc/pynumad.rst index 398f80c..5f3941b 100644 --- a/docs/apidoc/pynumad.rst +++ b/docs/apidoc/pynumad.rst @@ -17,6 +17,6 @@ Subpackages pynumad.objects pynumad.utils pynumad.io + pynumad.graphics pynumad.analysis.cubit - - + pynumad.analysis.ansys diff --git a/docs/citation.rst b/docs/citation.rst deleted file mode 100644 index f561ddd..0000000 --- a/docs/citation.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _intro-citation: - -Citing NuMAD -=============== - -To cite pyNuMAD v0.1, 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. - -.. - Kelley: replace with DOI citation once release is tagged diff --git a/docs/conf.py b/docs/conf.py index c35a941..77c7a11 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,14 +1,12 @@ -# -*- coding: utf-8 -*- -# http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- +from pynumad import __version__ # -- Project information ----------------------------------------------------- -project = 'pyNuMAD' -copyright = '2023, Kirk Bonney' -author = 'Kirk Bonney' -version = '1.0' -release = '1.0' +project = u'pyNuMAD' +copyright = u'2023 National Technology & Engineering Solutions of Sandia, LLC (NTESS)' +author = u'pyNuMAD Developers' + +version = __version__ +release = __version__ # -- General configuration --------------------------------------------------- @@ -48,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' +html_theme = 'pydata_sphinx_theme' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/index.rst b/docs/index.rst index 83d17b8..ec35758 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,37 +3,44 @@ .. figure:: /_static/images/NuMAD-header.png :target: https://github.com/sandialabs/NuMAD -Numerical Manufacturing And Design (NuMAD) Tool for Wind Turbine Blades -======================================================================= +pyNuMAD +======== + +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 `pyNuMAD (Python Numerical Manufacturing And Design) `_ for the design +and modeling of wind turbine blades is developed and described. .. toctree:: :maxdepth: 2 :hidden: - installation - overview - getting-started user-guide/index - release-notes - meshing - beam_models - shell_models - solid_models - apidoc/pynumad contributing + apidoc/pynumad reference + release-notes publications - citation license +.. _intro-citation: + +Citing NuMAD +=============== + +To cite pyNuMAD v0.1, 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. + +.. + Kelley: replace with DOI citation once release is tagged -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 `pyNuMAD (Numerical Manufacturing And Design) `_ for the design -and modeling of wind turbine blades is developed and described. .. _developers: diff --git a/docs/reference.rst b/docs/reference.rst index 028abe1..6f1cff5 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -11,19 +11,37 @@ Terminology ----------- -Profile/Airfoil: A 2D "slice" of an airfoil. In pyNuMAD, these terms -are used interchangeably. +Airfoil: A unitless (0-1) 2D outline of the desired aerodynamic shape (i.e., NACA-63-214, DU99-W-405, etc). +These are defined at every span location (different from ispan). -Station: A station is an airfoil at a specified span location +Profiles: Usually there are not enough airfoils defined along the span to create a smooth 3D blade geometry. +Profiles are unitless airfoil geometries at each blade interpolated span (ispan) location. + +Station: A station is an airfoil object at a specified span location. Stack: A stack of material plys specified by types and thicknesses. -Ply: A ply material layer. +Ply: A layer of material with defined properties, layup angle, and thickness. + +Camber: A 2D collection of points midway between the HP curve and LP curve of an airfoil or profile. + +Keypoint: Specified locations along the profile circumference used to define where there is a change in stack definition. + +Component: TODO + +Shearweb: TODO + +Span: TODO + +Chord: TODO + +Twist: TODO -Camber: +Prebend: TODO -Keypoints: +Sweep: TODO +TE Type: TODO Abbreviations diff --git a/docs/beam_models.rst b/docs/user-guide/beam_models.rst similarity index 100% rename from docs/beam_models.rst rename to docs/user-guide/beam_models.rst diff --git a/docs/user-guide/blade_definition.rst b/docs/user-guide/blade_definition.rst index ab0d9a4..1d7cbd0 100644 --- a/docs/user-guide/blade_definition.rst +++ b/docs/user-guide/blade_definition.rst @@ -18,10 +18,12 @@ to generate geometry, keypoints, bill of material, and material database. Dependency tree for blade subobjects + Definition (blade.definition) ----------------------------- -A Definition object provides attributes for the basic design +A :py:class:`~pynumad.objects.definition.Definition` +object provides attributes for the basic design of a wind turbine blade - i.e. where the blade is *defined*. Typically this is populated by a yaml file or an excel file, however it is possible to build a blade @@ -34,20 +36,24 @@ generating downstream data. Many of the attributes in Definition are parameterized by spanwise location. For example, *stations* are airfoils at specified span locations. Other airfoil properties and external blade shape data are -defined with the ``Airfoil`` -class and the ``Station`` object respectively, and are stored in ``definition.stations``. +defined with the :py:class:`~pynumad.objects.airfoil.Airfoil` +class and the :py:class:`~pynumad.objects.station.Station` object respectively, and are stored in ``definition.stations``. Material properties, layup information, and thicknesses and widths are -defined in the ``Material`` and ``Component`` classes +defined in the :py:class:`~pynumad.objects.material.Material` and :py:class:`~pynumad.objects.component.Component` classes and stored in ``blade.materials`` and ``blade.components``. + Geometry (blade.geometry) --------------------------- Typically, the blade definition does not contain high enough fidelity data for creating a mesh, so pyNuMAD performs additional interpolation to -create a more detailed geometry. The Geometry class generates -and stores the interpoloated geometry. +create a more detailed geometry. The :py:class:`~pynumad.objects.geometry.Geometry` class generates +and stores the interpoloated geometry. Many of the attributes are named as `iattribute` +where attribute is the name of some attribute in the definition which was interpolated. Additionally +the ``coordinates`` attribute holds the 3D geometry of the interpolated blade. + Keypoints (blade.keypoints) --------------------------- @@ -95,11 +101,17 @@ the high pressure surface verses the low pressure surface. +----------------------------------+-----------------------------------+ - - StackDB (blade.stackdb) ----------------------- -.. TODO +The :py:class:`~pynumad.objects.stackdb.StackDatabase` class serves to assign material +stack information across the blade. The ``stacks`` attribute stores stack information +for the outer blade shape and takes the form of a 2-dimensional array. The first +dimension represents segment (as determined by keypoints) +and the second dimension represents station (index along interpolated +blade span). The ``swstacks`` attribute stores stack information for the shearwebs +and also takes the form of a 2D array, where the first dimension is the shearweb +number, and the second dimension is also the station. + BillOfMaterials (blade.bom) --------------------------- diff --git a/docs/user-guide/conclusion.rst b/docs/user-guide/conclusion.rst deleted file mode 100644 index 7be204e..0000000 --- a/docs/user-guide/conclusion.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. _troubleshooting: - -Troubleshooting -=============== - -NuMAD will repeatedly print a message in the MATLAB command window to the effect of: - -.. code-block:: matlabsession - - ``Waiting for ANSYS to <`do something`>`` - ``Waiting for ANSYS to <`do something`>`` - ``Waiting for ANSYS to <`do something`>`` - -Common things to check are the ANSYS `.err` and `.log` for clues. - -.. _KnownIssues: - -Known Issues -============ - -Trailing Edge Issues - -- There is a need to allow for the existence of a nonzero trailing edge - thickness. The only way to achieve this in the current release is to - specify that the airfoil in question is a flatback. - -- Trailing edge overlap - -.. _TEoverlap: -.. figure:: /_static/images/TEoverlap.png - :width: 5.85771in - :height: 4.10039in - -- Often the element quality is poor at various parts of the trailing - edge. Possible solutions could be: - - - Alter airfoil geometry when reading in to make sharp airfoils for - small trailing edge thicknesses - - - Incorporate solid elements to represent trailing edge adhesive - -Other Issues - -- The placement of the spar cap must never exceed the bounds of the - spar cap keypoints. - -- ``blade.update_bom`` fails for an unknown reason if the layer quantity - increases rather than decreases toward the tip. - - - -.. _References: - -References -========== - -1. Berg, Jonathan, Joshua Paquette, and Brian Resor. "Mapping of 1D beam - loads to the 3D wind blade for buckling analysis." *52nd - AIAA/ASME/ASCE/AHS/ASC Structures, Structural Dynamics and Materials - Conference 19th AIAA/ASME/AHS Adaptive Structures Conference 13t*. - 2011. - -2. Fagerberg, Linus, and Dan Zenkert. "Effects of anisotropy and - multiaxial loading on the wrinkling of sandwich panels." *Journal of - Sandwich Structures & Materials* 7.3 (2005): 177-194. - -3. Berg, Jonathan C., and Brian R. Resor. "Numerical manufacturing and - design tool (NuMAD V2. 0) for wind turbine blades: user's guide." - *Sandia National Laboratories Technical Report, SAND2012-7028* - (2012). - - -.. TODO: use userGuide.bib publications to reference citations - \ No newline at end of file diff --git a/docs/user-guide/fea.rst b/docs/user-guide/fea.rst deleted file mode 100644 index 018c391..0000000 --- a/docs/user-guide/fea.rst +++ /dev/null @@ -1,609 +0,0 @@ -.. _FEAOps: - -Finite Element Analysis Operations -================================== - -.. _meshGen: - -Mesh Generation ---------------- -To generate a shell model without adhesives in ANSYS simply type: - - >> includeAdhesive=0; - >> meshData=blade.generateShellModel('ansys',includeAdhesive) - -The function returns a struct that contains the following feilds: ``nodes``, ``elements``, ``outerShellElSets``, and ``shearWebElSets``. This struct later needs to be input into ``mainAnsysAnalysis``. - -.. _coordinateSystems: - -Coordinate Systems ------------------- - -Loading for the FEA model will typically be derived from FAST or -OpenFAST cross-sectional stress resultant forces and moments at various -spanwise positions. These forces and moments are in coordinate systems -that are aligned with the local principal axes (structural) of the -cross-section in the deformed configuration. Thus, those coordinate -systems change with respect to span. X contrasts the FAST -results coordinate basis vectors, -:math:`v_{i}^{(j)}\ (j = 1,2,3,\ldots,k)`, with those of the NuMAD loads -system, :math:`w_{i}`, and the ANSYS coordinate system, :math:`x_{i}`, -which are invariant. :math:`v_{i}^{(j)}` is the also known as the blade -coordinate system in FAST/OpenFAST. Here and through the rest of this -document, index notation is used with Latin indices assuming 1, 2, and 3 -and Greek indices assuming 1, and 2 (except where explicitly indicated). -Repeated indices are summed over their range (except where explicitly -indicated). - -.. Note:: - The :math:`x_{i}` coordinate system is like the :math:`w_{i}` system - but the first axis, :math:`w_{1}` points toward the leading edge - instead of the flap direction. - -.. _numadFASTcsys: -.. figure:: /_static/images/numadFASTcsys.png - :width: 5.85771in - :height: 4.10039in - - Comparison of the FAST results coordinate system with that of the NuMAD and ANSYS coordinate systems. - -A small angle is assumed to exist between -:math:`v_{3}^{(j)}\ (j = 1,2,3,\ldots,k)` and :math:`w_{3}` and is -unaccounted for in NuMAD. Thus, it is assumed that -:math:`v_{3}^{(j)} = w_{3} = x_{3}`. Thus the :math:`v_{i}^{(j)}` and -the :math:`w_{i}` are related by - -.. math:: w_{i} = {C_{iq}v}_{q}^{(j)} - -where :math:`C_{iq}` are the direction cosines which can be -stored in a matrix as shown below - -.. math:: C = \begin{bmatrix} - \text{cos}(\mu) & \text{sin}(\mu) & 0 \\ - -\text{sin}(\mu) & \text{cos}(\mu) & 0 \\ - 0 & 0 & 1 - \end{bmatrix} - :label: DCM - - -where :math:`\mu` is the so-called structural twist and is illustrated -in :numref:`FASTvsNuMADcsys`. - -.. _FASTvsNuMADcsys: -.. figure:: /_static/images/FASTvsNuMADcsys.png - :width: 3.15956in - :height: 1.77725in - - Time history moment data from the :math:`v_{\alpha}` coordinate system to the :math:`w_{\alpha}` intermediate coordinate system. - -These angles are obtained by `PreComp `__. This coordinate transformation is -implementation in ``loadFASTOutDataGageRot``. - -Before transforming the loads data to the :math:`x_{i}` system, various -data processing operations occur in intermediate coordinate systems as -described in the next section. - -.. _analDir: - -Analysis Directions -------------------- - -Increasing the fidelity from a beam model in FAST/OpenFAST to a shell -model also increases the computational cost. Thus, it would be -cumbersome to conduct a time history structural analyses with a shell -model for each DLC; it would be impracticable on each iteration of an -optimization loop. Therefore, it is necessary to construct a reduced set -of load cases that is representative of the most critical loads in the -time history analysis. - -Two load cases were deemed necessary to properly analyze the most -critical loads; those needed to evaluate the maximum tip deflection and -those needed for evaluating blade failure. Here, blade failure consists -of ultimate failure, buckling, and fatigue failures. Both cases utilize -the FAST/OpenFAST resultant axial forces :math:`F_{3}^{w}`, both bending -moment components :math:`M_{\alpha}^{w}`, and the twisting moment, -:math:`M_{3}^{w}`. The superscript indicates the reference frame. These -will be referred to collectively with :math:`P_{i}\ (i = 1,2,\ldots,4)`, -a generalized load vector, where :math:`P_{i} = \begin{bmatrix} -F_{3}^{w} & M_{1}^{w} & M_{2}^{w} & M_{3}^{w} \\ -\end{bmatrix}^{T}`. - -.. Note:: - Note that :math:`P_{i}` varies with span-wise location and that resultant shear forces were assumed to be negligible for establishing load equivalency for both load cases. - -For the tip deflection case, the time at which the maximum tip deflection from the -beam model, :math:`t^{*}\ `, was determined. Then the :math:`P_{i}`, at -a given cross section was defined by - -.. math:: - - P_{i} = \begin{bmatrix} - F_{3}^{w}(t^{*}) & M_{1}^{w}(t^{*}) & M_{2}^{w}(t^{*}) & M_{3}^{w}(t^{*}) \\ - \end{bmatrix}^{T} - -The components were then transformed to the :math:`x_{i}` system. - -Since IEC allows for lower factors of safety if numerous analysis -directions are considered, :math:`n_{\theta}` analysis directions can be -considered by setting momentMaxRotation to \ :math:`{n}_{\theta}` -in the ``IECInput.inp`` file. - -Thus the loads used to evaluate blade failure are obtained by letting -:math:`\theta`, as defined in :numref:`loadDirections`, vary from 0 to 360 deg. in -increments of :math:`n_{\theta}/360`; yielding :math:`n_{\theta}` FE -load cases. The results for the load directions -0\ :math:`\leq \theta`\ <180 deg. were obtained by - -:math:`P_{i} = \begin{bmatrix} -\text{max}(F_{3}^{w}(t)) \\ -\text{max}(M_{1}^{y}(t))\cos(\theta) \\ -\text{max}(M_{1}^{y}(t))\sin(\theta) \\ -\text{max}(M_{3}^{w}(t)) \\ -\end{bmatrix}` 0\ :math:`\leq \theta`\ <180 - -where - -.. math:: M_{1}^{y} = M_{1}^{w}\left( t,w_{3} \right)\cos(\theta) + M_{2}^{w}(t,w_{3})\sin(\theta) - -Load directions from 180\ :math:`\leq \theta`\ <360 deg. are, however, -obtained by - -:math:`P_{i} = \begin{bmatrix} -\text{max}(F_{3}^{w}(t)) \\ -\text{min}(M_{1}^{y}(t))\cos(\theta) \\ -\text{min}(M_{1}^{y}(t))\sin(\theta) \\ -\text{max}(M_{3}^{w}(t)) \\ -\end{bmatrix}` 0\ :math:`\leq \theta`\ <180 - -.. Note:: - In the above equation, the minimum of :math:`M_{1}^{y}` is found - instead of the maximum but :math:`\theta` still ranges from 0 to 180 deg. - Unlike the resultants used for the deflection analysis which all occurred - at a specific time in the OpenFAST simulations, each of the axial force, - torsion, and bending moment resultants along the span could possibly come - from different times. Thus, it is an artificial distribution suitable for - design use. Also unlike the deflection case, the two bending-moment - components (i.e. flap-wise and edge-wise bending) at a span location - were projected onto 12 directions as defined by :math:`y_{1}` in - :numref:`loadDirections`. All of the :math:`P_{i}\ `\ then transformed - to the :math:`x_{i}` system in ``beamForceToAnsysShell``. - -.. _loadDirections: -.. figure:: /_static/images/loadDirections.png - :width: 3.06468in - :height: 1.72388in - - The definition of the :math:`y_1` axis and the angle :math:`\mathbf{\theta}`. - -.. _applyLoads: - -Loads Application ------------------ - -Blade loads can either come from the cross-sectional stress resultant -time-histories from FAST or user defined. Two load types are supported -for loads coming from a FAST; loads at a particular time and extremum -loads used to evaluate the limit states of the blade. Both account for -all three cross-sectional resultant moments along the span as well as -the resultant axial forces. However, the resultant transverse shear -forces acting on the blade in the FAST model are not transferred the -ANSYS model. Moreover, both create the ``loadsTable`` variable needed by -``mainAnsysAnalysis``, the main FEA script described is subsequent -section. ``getForceDistributionAtTime.m`` handles can be called for the -loads at a given time while ``FastLoads4ansys.m``} builds the ``loadsTable`` for -each analysis direction. The ``loadsTable`` variable -is\ :math:`\ 1 \times n` MATLAB cell array where :math:`n` is -the number of analysis directions. - -.. Note:: - ``getForceDistributionAtTime.m`` will give a :math:`1 \times 1` cell array since the loading is the *actual* loading at a particular time.). - -A user may apply loads other than the loads at particular time or the extremum loads with a user -defined ``loadsTable``. This can be done by creating the structure of the -``loadsTable`` variable manually. - -Example use for ``FastLoads4ansys.m`` is as follows: - -.. literalinclude:: loadsExample.m - :language: matlab - -For bending moments on a blade, ``getForceDistributionAtTime.m`` and -``getForceDistributionAtTime.m`` convert the moment distributions to -transverse force distributions. :numref:`momentsToForces` shows the known spanwise -bending moments, :math:`M_{i}` acting at a distance :math:`z_{i}` from -the blade root and the forces to be solved, :math:`F_{i}` acting at -:math:`{\overline{z}}_{i}`, where -:math:`{\overline{z}}_{i} = 1/2(z_{i} + z_{i + 1})`. - -.. _momentsToForces: -.. figure:: /_static/images/momentsToForces.png - :width: 6.5in - :height: 3.65625in - - Freebody diagram used to determine transverse loads from a given distribution of moments along the blade span. - - -From static equilibrium, the forces to be applied are found by solving -the following linear system of equations for -:math:`F_{i}\ (i = 1,2,3,\ldots,k)` - -.. math:: M_{i} = \sum_{j = i}^{k}{F_{j}({\overline{z}}_{j} - z_{i})} - -where :math:`k` is the number of cross-sections with resultant moment -data. - -The load distributions are then transferred to nodal loads by -``beamForceToAnsysShell.m``. ``beamForceToAnsysShell.m`` generates a text file (usually called forces.src) -containing the APDL commands to apply nodal forces for every node on the -wetted area of the blade. Details of the approach are found in Ref. [1] -but with modifications to add axial loads. - -.. Note:: - The script assumes that the input forces are in the FAST coordinate system, - :math:`w_{i}`, so a conversion is performed in the script to the - ANSYS coordinate system, :math:`x_{i}`. - -A vector, :math:`G_{i}`, such as a force or a -moment, in the :math:`w_{i}` coordinate system is transformed to the -:math:`x_{i}` with - -.. math:: g_{i} = C_{ij}G_{j} - -where :math:`C_{ij}` is defined in Eq. :eq:`DCM` but with setting -:math:`\mu = - 90\ `\ deg. Example usage for the first ``loadsTable`` load -case is as follows - -.. literalinclude:: loadsTableExample.m - :language: matlab - -where maptype is either ``'map2D_fxM0'`` or ``'map3D_fxM0'``. Note that these -steps are not usually required with using ``mainAnsysAnalysis``, the -main analysis script. These instructions are for building the ``loadsTable`` variable -and applying nodal forces to an FE model in a stand-alone manner. - -.. _analysisScript: - -Analysis Script ---------------- - -``mainAnsysAnalysis.m`` is the main analysis script. A user may call -on it to - -- obtain load factors from global instabilities due to linear or - nonlinear buckling - -- obtain load factors from local instabilities due to face-sheet - wrinkling - -- find the maximum value of a failure index - -- stress data required for fatigue analyses - -- cross sectional force and moment results vs spanwise position - -- average cross-sectional rotations and displacements along the span - -- strain along the spar caps vs. spanwise position - -- blade mass - -The required inputs are a blade object, the ``loadsTable``, and the ``config`` -variable. The script knows which analysis types it should run based on -config. See X for the structure and usage of the ``config`` -variable. The ``IECDef`` class defintion is only needed when the fatigue flage is activated. - - -.. _configTable: -.. csv-table:: Structure and usage of the ``config`` variable. - :file: configTable.csv - :widths: 1, 1, 3 - :header-rows: 1 - - -``meshFile`` is the name of the ANSYS model database to begin the analysis -from. It defaults to ``'master'``. analysisFileName is the name of the new -ANSYS model database which will store the analysis results. It defaults -to ``'FEmodel'``. np is the number of processors (CPUs) ANSYS should use for -each solve. It defaults to 1. - -The output and it is a variable length struct. Depending on -which analysis flags are active, results can be accessed with - -.. code-block:: matlabsession - - >> result=layupDesign_ANSYSmesh(blade) - >> result.globalBuckling - >> result.localBuckling - >> result.deflection - >> result.failure - >> result.fatigue - >> result.resultantVSspan - >> result.mass - - -.. _linearFEA: - -Linear-Static Analysis -~~~~~~~~~~~~~~~~~~~~~~ - -A linear-static analysis is defined and solved by default. Since -linear-buckling is a notable advantage of using a shell model for the -blade, prestress is activated in this load step in preparation for a -linear buckling analysis. The effects of inertia are counterbalanced -with inertia relief. - -Depending on the ``config`` flags, a number analysis outputs can be -examined. - -.. _deflectionFEA: - -Deflection -~~~~~~~~~~ - -Setting ``config.deflection = 1`` will cause ``result.deflection`` to -hold the average deflection of each cross-section at every ``blade.ispan`` -location. For example, access results from the second ``loadsTable`` case as - -``result.deflection{2}`` - -The result is a matrix that has as many rows are ``blade.ispan`` and 6 -columns. The first three columns are average cross-sectional -displacements in the :math:`x_{i}` system. Columns 1, 2, and, 3, -correspond to :math:`{\overline{u}}_{1}`, :math:`{\overline{u}}_{2}`, -and :math:`{\overline{u}}_{3}` respectively. Columns 4, 5, and 6 -correspond to :math:`{\overline{\theta}}_{1}`, -:math:`{\overline{\theta}}_{2}`, and :math:`{\overline{\theta}}_{3}`, -respectively. - -.. _failureFEA: - -Failure -~~~~~~~ - -If material failure is being considered in an analysis, set -``config.failure`` equal to any one of the entries in X. An -empty string will skip any material failure analyses. - - -.. _failureCriteriaOptions: -.. csv-table:: Supported failure criteria and associated ``config`` flags. - :file: failureCriteriaOptions.csv - :widths: 2, 2 - :header-rows: 1 - - - -Depending on the criterion used, it is necessary for the ``materialDef`` to -have the appropriate material properties defined in ``blade.materials``. - -Since each element section is a layered composite, by default, -``result.failure`` will hold the maximum failure index of all elements and -every layer. - -.. _globalBucklingFEA: - -Global Buckling -~~~~~~~~~~~~~~~ - -A nonzero number for ``config.analysisFlags.globalBuckling`` will call -ANSYS to run a buckling analysis. The buckling analysis can either be -linear or nonlinear. The nonlinear case will be activated by creating -``config.analysisFlags.imperfection`` and setting it to a nonempty -number array. ANSYS will then be directed to perform an eigenvalue -buckling analysis. The load which results in nonconvergence will be -reported as the nonlinear buckling load factor. - -For the nonlinear case, it is necessary to introduce a synthetic -imperfection for the analysis to provide reasonable results. The -imperfection introduced is of the geometric kind and corresponds to the -buckled mode shapes obtained in the eigenvalue buckling analysis. -Therefore, an eigenvalue buckling analysis precedes the nonlinear static -analyses. Currently, for nonlinear buckling, it is assumed here that -buckling will be in the aeroshell (not the web). Thus, each mode shape -is scaled such that the maximum displacement in the :math:`x_{2}` -direction (flapwise) is equal to config.analysisFlags.imperfection -in value. Robustness could be increased if the script can select whether -to find the maximum displacement in the :math:`x_{2}` (buckling in -aeroshell) or :math:`x_{1}` direction (buckling in the webs). - -Finally, it is supposed that the mode shape corresponding to the lowest -load factor from the eigenvalue analysis will not always cause the -lowest load factor from the nonlinear case. Thus, a nonlinear static -analysis for each requested mode is performed and the minimum load -factor is reported. - -.. _localBucklingFEA: - -Local Buckling -~~~~~~~~~~~~~~ - -Sandwich panels typically consist of a relatively soft core layer -*sandwiched* between two faces sheets. For the parts of blade that are -described as sandwhich panels, local instabilities can be checked in -NuMAD with a strip theory model from Ref. [2]. In particular, this check -examines if the outermost facesheet wrinkles under compression. - -To activate this check, set ``config.analysisFlags.localBuckling`` -equal to the name of the core material in your BladeDef as a string -(e.g. ``config.analysisFlags.localBuckling = 'Balsa'``). Otherwise an -empty string will skip the analysis. Currently, all ply angles are -limited to zero (i.e. no off-axis layups). - - -.. _fatigueFEA: - -Fatigue -~~~~~~~ - -If ``config.fatigue`` is a nonempty string, then ANSYS will be -directed to write model data and field output to text files for fatigue -post-processing in MATLAB. Namely, ``Elements.txt``, ``Materials.txt``, -``Strengths.txt``, ``Sections.txt``, and plate strain measures. The results from running -the fatigue post-processor will be a :math:`1 \times n_{\theta}/2` cell -array, where :math:`n_{\theta}` is the number of cells in the ``loadsTable`` -variable (where each cell holds the loads for a single analysis -direction). This is because stress results from two orthogonal loading -directions are utilized for a single evaluation of fatigue damage (e.g. -one fatigue evaluation is the combined effect of flap loads and edge -loads). Furthermore, it assumes that the ``loadsTable`` is arranged in -ascending order for the loads direction angle. This is already accounted -for if ``loadsTable`` was constructed from ``FastLoads4ansys.m``. -Make sure to set ``fatigueCriterion`` to Shifted Goodman -in the ``IECInput.inp`` file. - -Fatigue damage is computed at the root and at the locations of the FAST -gages. In this document, these will be referred to as the *spanwise -fatigue locations*. Fatigue results are restricted to the spanwise -fatigue locations because the fatigue analysis relies on Markov matrices -and these matrices need cycle counts from time-history data. The time -histories that are available from FAST are at the root and the FAST -gages. - -The end-user has the ability to either obtain a single fatigue damage -fraction at each spanwise fatigue location or several fatigue damage -fractions each corresponding to a region in x. The former is -accomplished by setting ``config.analysisFlags.fatigue = ["ALL"]``. -The latter is accomplished by setting ``config.analysisFlags.fatigue`` -to a MATLAB string array where any and all Region Names in x are allowed. - - -.. _regionNames: -.. csv-table:: Region Names to specify in config for fatigue analyses. - :file: regionNames.csv - :widths: 2,5 - :header-rows: 1 - - -For example, suppose that the fatigue damage was only desired at the -spar caps and the reinforcement locations one would set - -.. code-block:: matlabsession - - >> config.analysisFlags.fatigue = ["HP_TE_FLAT","HP_TE_REINF","HP_SPAR","HP_LE","LP_LE","LP_SPAR","LP_TE_REINF","LP_TE_FLAT"] - -If ``"ALL"`` is included along with other regions, the other regions are -ignored and the analysis carries forth as it would for ``"ALL"``. - -The result will be a :math:`1 \times n_{\theta}/2` cell array. Each cell -will hold a struct with the following field names: ``fatigueDamage``, -``criticalElement``, ``criticalLayerNo``, and ``criticalMatNo``. Each of these field -names allow access to a :math:`n_{\text{region}} \times 10` matrix where -:math:`n_{\text{region}}` is the length of -``config.analysisFlags.fatigue``. The results are organized such that -the :math:`i_{\text{th}}` row number corresponds to fatigue damage -results of the :math:`i_{\text{th}}` Region Name from -``config.analysisFlags.fatigue``. The columns correspond to the -fatigue damage spanwise locations where column 1 is the results at the -root. Subsequent columns correspond to successively farther gage -locations. - -The results from the first fatigue evaluation can visualized as shown in -:numref:`fatigueDamageFractionExample`. - -.. _fatigueDamageFractionExample: -.. figure:: /_static/images/fatigueDamageFractionExample.bmp - :alt: Diagram Description automatically generated - :width: 4.17467in - :height: 3.131in - - Fatigue damage fraction visualization. - - -.. _localFieldsFEA: - -Local Fields -~~~~~~~~~~~~ - -If ``config.analysisFlags.localFeilds`` is activated, then the plate -strains and curvatures for every element will be written to -plateStrains-all-1.txt. - -After mainAnsysAnalysis completes execution, access the local -fields with - -.. literalinclude:: localFieldsExample.m - :language: matlab - -``elNo`` is an scalar or array of element numbers for -which to extract the local fields. Set ``coordSys='local'`` to obtain -results in the local layer coordinate system or set ``coordSys='global'`` to -obtain results in the element coordinate system. - -For example if one sets ``elNo=[1950,2558]`` then, ``myresult`` is a struct with -two fields: - -.. code-block:: matlabsession - - >> myresult - element1950: [1x1 struct] - element2558: [1x1 struct] - -Looking at the first struct shows: - -.. code-block:: matlabsession - - >> myresult.element1950 - x3: [8x1 double] - eps11: [8x1 double] - eps22: [8x1 double] - eps33: [8x1 double] - eps23: [8x1 double] - eps13: [8x1 double] - eps12: [8x1 double] - sig11: [8x1 double] - sig22: [8x1 double] - sig12: [8x1 double] - matNumber: [8x1 double] - -where ``x3`` is the thickness coordinate, ``eps`` are the strains and sig are the -stresses. - -.. Note:: - Note the ``x3`` value that is zero corresponds to the reference surface in the shell model. - -In this example the shell offset in ANSYS was set to ``BOT`` so the zero appears the end: - -.. _localFieldsDataExplanationFigure: -.. figure:: /_static/images/localFieldsDataExplanationFigure.png - :width: 5.03004in - :height: 2.30597in - - Explanation of how data for local fields is ordered. - - -A plotting utility has been made to visualize the local fields. This can -be achieved for example: - -.. literalinclude:: localFieldsPlotExample.m - :language: matlab - -.. _localFieldsPlotExample: -.. figure:: /_static/images/localFieldsPlotExample.png - :width: 6.5in - :height: 2.98472in - - Local fields example plots. - - -.. _resultantsFEA: - -Resultant Forces and Moments -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The resultant forces and moments due to stresses on cross-sections along -the span can be obtained by activating -``config.analysisFlags.resultantVSspan``. ``result. resultantVSspan{i}`` -will yield a :math:`n \times 7` matrix, where :math:`n` is approximately -equal to the blade length divided by blade.mesh. The first column is the -distance along :math:`x_{3}` that locates the cross-section. The next -three columns correspond to resultant forces in the :math:`x_{1}`, -:math:`x_{2}`, and :math:`x_{3}` directions (in that order). The next -three columns correspond to resultant moments about in the -:math:`x_{1}`, :math:`x_{2}`, and :math:`x_{3}` directions (in that -order). For example, access results such as - -.. code-block:: matlabsession - - >> result.resultantVSspan{i} - -where i is the i\ :sup:`th` load case in ``loadsTable``. diff --git a/docs/getting-started.rst b/docs/user-guide/getting-started.rst similarity index 100% rename from docs/getting-started.rst rename to docs/user-guide/getting-started.rst diff --git a/docs/user-guide/index.rst b/docs/user-guide/index.rst index 9e90331..ccd24e1 100644 --- a/docs/user-guide/index.rst +++ b/docs/user-guide/index.rst @@ -5,5 +5,18 @@ User’s Guide .. toctree:: :maxdepth: 2 + :caption: Get Started + overview + installation + getting-started + +.. toctree:: + :maxdepth: 2 + :caption: User Interface + blade_definition + meshing + beam_models + shell_models + solid_models diff --git a/docs/installation.rst b/docs/user-guide/installation.rst similarity index 100% rename from docs/installation.rst rename to docs/user-guide/installation.rst diff --git a/docs/meshing.rst b/docs/user-guide/meshing.rst similarity index 100% rename from docs/meshing.rst rename to docs/user-guide/meshing.rst diff --git a/docs/overview.rst b/docs/user-guide/overview.rst similarity index 97% rename from docs/overview.rst rename to docs/user-guide/overview.rst index 1d9b747..a38a50b 100644 --- a/docs/overview.rst +++ b/docs/user-guide/overview.rst @@ -23,8 +23,9 @@ Namely, - In-house mesher for pure shell, pure solid, or shell + solid adhesive - Cubit mesher for contiguous solid meshes and cross-sectional analysis -Supported input files: -- yaml files from the `IEA Ontology __ +Supported input files: + +- yaml files from the `IEA Ontology `__ - Excel files from the legacy version of NuMAD diff --git a/docs/user-guide/running_numad.rst b/docs/user-guide/running_numad.rst deleted file mode 100644 index 4560a13..0000000 --- a/docs/user-guide/running_numad.rst +++ /dev/null @@ -1,205 +0,0 @@ -.. _runningNuMAD: - -Running NuMAD -================ - -The following sections go through the basics of putting together and -analyzing a blade design in NuMAD, from creating a blade object, to -modifying its parameters and attributes, and generating structural models -for analysis. Tips for implementation are given to ensure the smoothest -execution. - -Blade Generation ----------------- - -There are several ways to construct a blade model in NuMAD -3.0. In many ways the most intuitive approach is by using the graphical -user interface carried over from NuMAD 2.0 (for detailed instructions, -please refer to the NuMAD 2.0 user manual [3]). Although the current -version is designed not to be reliant on this GUI, it is still supported -and can be a useful tool if designing a blade model from scratch. - -A more automated way to generate a blade model is by reading a ``.yaml`` -file, and using the data stored within to populate the model definition. -The ``.yaml`` format contains all the geometric, aerodynamic and material -information needed to define a blade structure, and is widely used in -the field, making it a convenient choice for the source data file. -Several examples of ``.yaml`` files are provided in the ``NuMAD/examples/referenceModels`` directory -of the GitHub repository. - -.. Kelley: this would be a good place to introduce the difference between the source directory and the case directory (for a run) - -To read a ``.yaml`` file's data into NuMAD from a MATLAB script or command -window, first save the ``.yaml`` file in the working directory for the blade -model. Typically, each blade design should have its own working -directory, which contains aerodynamic/airfoil data, FAST input files -(``*.fst`` extension) and subfolders for NuMAD operations and FAST -simulation output files (``*.out`` extension). Once the ``.yaml`` file is saved -alongside these items, it can be read by creating a new blade object of -type ``BladeDef`` and calling the reader function, as shown: - -.. code-block:: matlabsession - - >> blade = BladeDef - >> blade.readYAML() - -After entering these commands, the blade model data will be stored in -the object called ``blade``, which can be printed out and modified as -desired as further explained in :ref:`bladeVarAssign`. Many types of analysis and -operations can be performed once a blade model is stored as a blade -object in this way. - -If it is desired to run aeroelastic simulation with -``runIEC``, or to generate loads from FAST-generated output files as -described in :ref:`FEAOps`, it is advisable to update the FAST input files -in the blade's main working directory to ensure that certain quantities -within are consistent with the data stored in the ``.yaml`` file, such as -prebend, presweep, and structural twist. This can be done using the -commands - -.. code-block:: matlabsession - - >> IEC = IECdef(inputFileName) - >> updateFASTFromBLADEDef(IEC,blade) - -``inputFileName`` refers to the path/name of the input file containing variables -related to the aeroelastic analysis and simulation (see x for more -details). - -After all desired analyses and modifications are complete, a new, -updated ``.yaml`` file can be generated to represent the optimized, or -re-designed blade. To do this issue the command: - -.. code-block:: matlabsession - - >> writeYAML(blade,); - -The new file name should be of the form ``_mod.yaml``, adding -an ``_mod`` extension to the name of the original ``.yaml`` file from which -the blade model was generated. The new file will be written into the -blade model's working directory alongside the original. - -Generating blades from ``.yaml`` files is useful for streamlining analysis -and optimization processes, since all operations can be called from a -MATLAB script, without depending on the graphical user interface or any -manual input during execution. - - - -.. _bladeVarAssign: - -Blade Variable Assignment -------------------------- - -Any blade design process involves setting and modifying characteristics -of the blade's geometric, structural, and material properties in some -way. The NuMAD blade object contains a collection of variables that -represent these properties, and can be set and modified by value -assignment within a MATLAB script or in the command line. A -comprehensive list of all public variables in the ``BladeDef`` class used in -NuMAD is given in the :ref:`classDefs`. - -Here we give some highlighted examples of key variables within the blade -object and their basic access. The overall shape of the blade is defined -largely by the stations (access: ``blade.stations``). Each station -contains several variables whose values can be edited. For instance, if -a blade model was generated by reading a ``.yaml`` file as described in -:ref:`bladeGen`, and it was desired to set the spanwise position of the -second station at 3.5 meters, the command - -.. code-block:: matlabsession - - >> blade.stations(2).spanlocation = 3.5 - -could be used. Many variables are arrays with multiple values, and can -be set according using standard MATLAB syntax. The coordinates of the -points defining the outer airfoil shape at a given station, for example, -are stored in the airfoil object at each individual station as an :math:`N X 2` -array, and can be set as follows: - -.. code-block:: matlabsession - - >> blade.stations(2).airfoil.coordinates = [X1, Y1; X2, Y2; ...; XN, YN] - -There are several properties that each define some aspect of the blade's -shape with a value at any given spanwise location, including chord -length, angle of twist, aerodynamic center, sweep and prebend. These can -be set at any number of spanwise points, with the variable *span* -specifying their locations. If a user wanted to, say, set the prebend of -the blade to some constant :math:`k` times cube of the spanwise location, -specified at 10 equally spaced points, they could set - -.. code-block:: matlabsession - - >> blade.span = linspace(0,,10); - >> blade.prebend = k*blade.span.^3; - -The bulk of the structural properties of the blade's components are -stored in ``blade.components`` variable. A single component contains a name, -a material ID number, labels representing the points it spans between -according to :numref:`bladeKeyPoints`, and a control point array, called ``cp``. The -control point array specifies the thickness of the given component at -every spanwise location, expressed in number of layers (the actual -thickness of a layer is defined by the material object it corresponds -to, shown shortly). Suppose component 3 in the blade was the suction -side spar cap, and it was desired to vary the thickness linearly from 10 -layers at the root to 2 layers at the tip, say 50 meters span. The user -could set - -.. code-block:: matlabsession - - >> blade.components(3).cp = [0, 10; 50, 2]; - -The width of the spar caps and the leading edge and trailing edge bands -are single nominal values for the entire length of the blade, stored in -the variables ``blade.sparcapwidth``, ``blade.leband`` and ``blade.teband`` -respectively. - -The data defining the properties of all the materials used throughout -the blade are stored in the variable ``blade.materials``. Each entry in -``blade.materials`` is a ``MaterialDef`` object, which stores a name, elastic -properties, density, and strength properties among others (see :ref:`materialClass` in the :ref:`classDefs`). -It also stores the thickness that a single layer of that material in a -composite is assumed to be, which can be important to know or edit when -defining the thickness distribution of the blade's components as just described. - -After editing the design properties of a blade model as illustrated in -these few examples, a user should run the command - -.. code-block:: matlabsession - - >> blade.UpdateBlade() - -This function updates numerous internal private variables based on the -edited values in the public variables. Among other things, it -interpolates the properties that vary along the span of the blade to the -spanwise points specified in the variable ``blade.ispan``. These include -all the properties defined in ``blade.stations``, as well as the general -spanwise properties such as prebend, twist, etc. ``UpdateBlade`` also -updates the bill of materials for the blade, stored in ``blade.bom`` and -various details of the geometry, stored in ``blade.geometry``. - -When the variables defining the blade design are set to satisfaction, -the blade object can be used to perform various operations for analysis -and optimization, such as generating representative structural models as -described in the next section. - -.. _genBladeStructural: - -Generating Representative Blade Structural Models -------------------------------------------------- - -A NuMAD blade object can be used to construct structural models for -various types of analysis. Several tools exist that analyze -characteristics such as section stiffness, mass, and natural frequencies -of wind blades by representing them with low-fidelity beam models. These -include PreComp, BModes, and BPE. The most straightforward way of -invoking these capabilities is through the graphical user interface (for -details please see ref. [3]). - -In addition to these, however, NuMAD 3.0 has many built-in functions for -performing high-fidelity analysis of a blade as a shell-element model in -ANSYS, which are easily invokable from a MATLAB script or command line. -These include analysis for maximum tip deflection, ultimate rupture -failure, global and local buckling, fatigue and natural frequencies and -are discussed in detail in :ref:`FEAOps`. \ No newline at end of file diff --git a/docs/settings_dict.csv b/docs/user-guide/settings_dict.csv similarity index 100% rename from docs/settings_dict.csv rename to docs/user-guide/settings_dict.csv diff --git a/docs/shell_models.rst b/docs/user-guide/shell_models.rst similarity index 100% rename from docs/shell_models.rst rename to docs/user-guide/shell_models.rst diff --git a/docs/solid_models.rst b/docs/user-guide/solid_models.rst similarity index 100% rename from docs/solid_models.rst rename to docs/user-guide/solid_models.rst diff --git a/src/pynumad/analysis/cubit/make_blade.py b/src/pynumad/analysis/cubit/make_blade.py index bc115ca..4a6d1b7 100644 --- a/src/pynumad/analysis/cubit/make_blade.py +++ b/src/pynumad/analysis/cubit/make_blade.py @@ -45,10 +45,9 @@ def cubit_make_cross_sections( surface_dict: dict Keys are integers for the Cubit surface IDs for the cross sections. Each surface has it's own dictionary with the following keys: 'curves', 'verts', 'material_name', 'ply_angle'. - e.g. >> surface_dict[9] - {'curves': [131, 164, 129, 163], 'verts': [500, 501, 497, 496], 'material_name': 'glass_triax', 'ply_angle': 0} + >> {'curves': [131, 164, 129, 163], 'verts': [500, 501, 497, 496], 'material_name': 'glass_triax', 'ply_angle': 0} birds_mouth_verts: tuple Used internally.