From 474f1e3fa0a220bbd2bea8c7a70c97424f500c9b Mon Sep 17 00:00:00 2001
From: camUrban
Date: Wed, 4 Dec 2024 13:17:04 -0500
Subject: [PATCH] I reformatted my code with Black.
---
BUILD.md | 15 +-
CODE_OF_CONDUCT.md | 126 +-
README.md | 185 +-
SECURITY.md | 4 +-
benchmarks/unsteady_benchmark.py | 108 +-
benchmarks/unsteady_benchmark_converge.py | 106 +-
benchmarks/unsteady_benchmark_timed.py | 3 +-
examples/analyze_steady_trim_example.py | 74 +-
examples/analyze_unsteady_trim_example.py | 137 +-
examples/steady_convergence_example.py | 162 +-
..._horseshoe_vortex_lattice_method_solver.py | 256 +-
...teady_ring_vortex_lattice_method_solver.py | 290 +-
...ing_vortex_lattice_method_solver_static.py | 182 +-
...g_vortex_lattice_method_solver_variable.py | 176 +-
...attice_method_solver_variable_formation.py | 301 +-
.../unsteady_static_convergence_example.py | 80 +-
.../unsteady_variable_convergence_example.py | 82 +-
formation flight/formation_flight.py | 145 +-
.../formation_flight_convergence.py | 295 +-
main.py | 1 -
pterasoftware/aerodynamics.py | 373 +-
pterasoftware/convergence.py | 6 +-
pterasoftware/functions.py | 4 -
pterasoftware/geometry.py | 225 +-
..._horseshoe_vortex_lattice_method_solver.py | 130 +-
...teady_ring_vortex_lattice_method_solver.py | 290 +-
...ing_vortex_lattice_method_solver_static.py | 182 +-
...g_vortex_lattice_method_solver_variable.py | 176 +-
...attice_method_solver_variable_formation.py | 310 +-
pterasoftware/movement.py | 531 +--
pterasoftware/operating_point.py | 38 +-
pterasoftware/output.py | 783 ++---
pterasoftware/panel.py | 24 +-
pterasoftware/problems.py | 10 +-
.../steady_horseshoe_vortex_lattice_method.py | 92 +-
.../steady_ring_vortex_lattice_method.py | 195 +-
pterasoftware/trim.py | 162 +-
pterasoftware/ui_resources/main_window.py | 3 +-
pterasoftware/ui_resources/main_window.ui | 3092 ++++++++++-------
pterasoftware/ui_resources/textdialog.py | 15 +-
.../unsteady_ring_vortex_lattice_method.py | 712 ++--
tests/integration/__init__.py | 7 +-
.../integration/fixtures/airplane_fixtures.py | 313 +-
.../integration/fixtures/movement_fixtures.py | 283 +-
.../integration/fixtures/problem_fixtures.py | 33 +-
tests/integration/test_output.py | 27 +-
tests/integration/test_steady_convergence.py | 15 +-
..._steady_horseshoe_vortex_lattice_method.py | 56 +-
.../test_steady_ring_vortex_lattice_method.py | 23 +-
...ce_method_multiple_wing_static_geometry.py | 14 +-
..._method_multiple_wing_variable_geometry.py | 17 +-
...g_vortex_lattice_method_static_geometry.py | 18 +-
...vortex_lattice_method_variable_geometry.py | 18 +-
tests/unit/fixtures/vortex_fixtures.py | 17 +-
tests/unit/test_horseshoe_vortex.py | 102 +-
tests/unit/test_line_vortex.py | 21 +-
tests/unit/test_ring_vortex.py | 252 +-
57 files changed, 4251 insertions(+), 7046 deletions(-)
diff --git a/BUILD.md b/BUILD.md
index dba04411..a0d9cbb4 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -1,15 +1,18 @@
# Packaging
-There are 2 available packaging formats: Installer or wheel. The former is what is distributed, while the latter is
+There are 2 available packaging formats: Installer or wheel. The former is what is
+distributed, while the latter is
required for use of the CLI for instance.
-When packaging don't forget to check versions in both `setup.py` and `make_installer.iss` and ensure they match!
+When packaging don't forget to check versions in both `setup.py` and
+`make_installer.iss` and ensure they match!
### Installer
**Currently, this is only supported on Windows.**
-The installer uses `PyInstaller` to extract all the dependencies and `InnoSetup` to create a Windows installer package
+The installer uses `PyInstaller` to extract all the dependencies and `InnoSetup` to
+create a Windows installer package
out of them.
1. Ensure you have installed `InnoSetup` [here](https://jrsoftware.org/isdl.php).
@@ -20,8 +23,10 @@ out of them.
python -O -m PyInstaller --noconfirm "pterasoftware.spec"
```
-We run `python` with the first level optimise flag `-O` to slim down some now unnecessary debug code. *Do not use second
+We run `python` with the first level optimise flag `-O` to slim down some now
+unnecessary debug code. *Do not use second
level optimisation `-OO`, as this removes some docstrings that break dependencies.*
-3. Open `make_installer.iss` in InnoSetup and run the packaging process. This can take a while, but should output an
+3. Open `make_installer.iss` in InnoSetup and run the packaging process. This can take a
+ while, but should output an
installer in the `Output` folder.
\ No newline at end of file
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 656a3c23..2bdbc634 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -2,120 +2,120 @@
## Our Pledge
-We as members, contributors, and leaders pledge to make participation in our community
-a harassment-free experience for everyone, regardless of age, body size, visible or
-invisible disability, ethnicity, sex characteristics, gender identity and expression,
-level of experience, education, socio-economic status, nationality, personal
-appearance, race, religion, or sexual identity and orientation.
+We as members, contributors, and leaders pledge to make participation in our community
+a harassment-free experience for everyone, regardless of age, body size, visible or
+invisible disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
-We pledge to act and interact in ways that contribute to an open, welcoming, diverse,
-inclusive, and healthy community.
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse,
+inclusive, and healthy community.
## Our Standards
-Examples of behavior that contributes to a positive environment for our community
-include:
+Examples of behavior that contributes to a positive environment for our community
+include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
-* Accepting responsibility and apologizing to those affected by our mistakes, and
-learning from the experience
+* Accepting responsibility and apologizing to those affected by our mistakes, and
+ learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
-* The use of sexualized language or imagery, and sexual attention or advances of any
-kind
+* The use of sexualized language or imagery, and sexual attention or advances of any
+ kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
-* Publishing others' private information, such as a physical or email address, without
-their explicit permission
-* Other conduct which could reasonably be considered inappropriate in a professional
-setting
+* Publishing others' private information, such as a physical or email address, without
+ their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional
+ setting
## Enforcement Responsibilities
-Community leaders are responsible for clarifying and enforcing our standards of
-acceptable behavior and will take appropriate and fair corrective action in response to
-any behavior that they deem inappropriate, threatening, offensive, or harmful.
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in response to
+any behavior that they deem inappropriate, threatening, offensive, or harmful.
-Community leaders have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions that are not
-aligned to this Code of Conduct, and will communicate reasons for moderation decisions
-when appropriate.
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are not
+aligned to this Code of Conduct, and will communicate reasons for moderation decisions
+when appropriate.
## Scope
-This Code of Conduct applies within all community spaces, and also applies when an
-individual is officially representing the community in public spaces. Examples of
-representing our community include using an official e-mail address, posting via an
-official social media account, or acting as an appointed representative at an online
-or offline event.
+This Code of Conduct applies within all community spaces, and also applies when an
+individual is officially representing the community in public spaces. Examples of
+representing our community include using an official e-mail address, posting via an
+official social media account, or acting as an appointed representative at an online
+or offline event.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to
-the community leaders responsible for enforcement at camerongurban@gmail.com. All
-complaints will be reviewed and investigated promptly and fairly.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to
+the community leaders responsible for enforcement at camerongurban@gmail.com. All
+complaints will be reviewed and investigated promptly and fairly.
-All community leaders are obligated to respect the privacy and security of the reporter
-of any incident.
+All community leaders are obligated to respect the privacy and security of the reporter
+of any incident.
## Enforcement Guidelines
-Community leaders will follow these Community Impact Guidelines in determining the
-consequences for any action they deem in violation of this Code of Conduct:
+Community leaders will follow these Community Impact Guidelines in determining the
+consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
-**Community Impact**: Use of inappropriate language or other behavior deemed
-unprofessional or unwelcome in the community.
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
-**Consequence**: A private, written warning from community leaders, providing clarity
-around the nature of the violation and an explanation of why the behavior was
-inappropriate. A public apology may be requested.
+**Consequence**: A private, written warning from community leaders, providing clarity
+around the nature of the violation and an explanation of why the behavior was
+inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
-**Consequence**: A warning with consequences for continued behavior. No interaction
-with the people involved, including unsolicited interaction with those enforcing the
-Code of Conduct, for a specified period of time. This includes avoiding interactions in
-community spaces as well as external channels like social media. Violating these terms
-may lead to a temporary or permanent ban.
+**Consequence**: A warning with consequences for continued behavior. No interaction
+with the people involved, including unsolicited interaction with those enforcing the
+Code of Conduct, for a specified period of time. This includes avoiding interactions in
+community spaces as well as external channels like social media. Violating these terms
+may lead to a temporary or permanent ban.
### 3. Temporary Ban
-**Community Impact**: A serious violation of community standards, including sustained
-inappropriate behavior.
+**Community Impact**: A serious violation of community standards, including sustained
+inappropriate behavior.
-**Consequence**: A temporary ban from any sort of interaction or public communication
-with the community for a specified period of time. No public or private interaction
-with the people involved, including unsolicited interaction with those enforcing the
-Code of Conduct, is allowed during this period. Violating these terms may lead to a
-permanent ban.
+**Consequence**: A temporary ban from any sort of interaction or public communication
+with the community for a specified period of time. No public or private interaction
+with the people involved, including unsolicited interaction with those enforcing the
+Code of Conduct, is allowed during this period. Violating these terms may lead to a
+permanent ban.
### 4. Permanent Ban
-**Community Impact**: Demonstrating a pattern of violation of community standards,
-including sustained inappropriate behavior, harassment of an individual, or aggression
-toward or disparagement of classes of individuals.
+**Community Impact**: Demonstrating a pattern of violation of community standards,
+including sustained inappropriate behavior, harassment of an individual, or aggression
+toward or disparagement of classes of individuals.
-**Consequence**: A permanent ban from any sort of public interaction within the
-community.
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
-available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
+available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by
-[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
+[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
-For answers to common questions about this code of conduct, see the FAQ at
-https://www.contributor-covenant.org/faq. Translations are available at
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
diff --git a/README.md b/README.md
index a08fcc3a..602cad30 100644
--- a/README.md
+++ b/README.md
@@ -13,105 +13,106 @@
![Example Unsteady Formation Flight](https://raw.githubusercontent.com/camUrban/PteraSoftware/master/docs/examples%20expected%20output/unsteady%20ring%20vortex%20lattice%20method%20solver%20variable%20formation/Animate.webp)
-This is Ptera Software: a fast, easy-to-use, and open-source package for analyzing
+This is Ptera Software: a fast, easy-to-use, and open-source package for analyzing
flapping-wing flight.
## Motivation
-In late 2018, I became curious about biological flight. To sate this curiosity, I
-wanted to computationally simulate some flapping-wing fliers. I quickly realized I had
+In late 2018, I became curious about biological flight. To sate this curiosity, I
+wanted to computationally simulate some flapping-wing fliers. I quickly realized I had
two options:
-1. Spend thousands of dollars on a closed-source CFD program, which would take hours to
-solve a simple case.
-2. Try to learn someone else's open-source, unsteady solver written in a language I
-didn't know, or using a framework that is overly complicated for my use case.
+1. Spend thousands of dollars on a closed-source CFD program, which would take hours to
+ solve a simple case.
+2. Try to learn someone else's open-source, unsteady solver written in a language I
+ didn't know, or using a framework that is overly complicated for my use case.
Neither of these seemed like the right choice.
-Thankfully, my friend, Peter Sharpe, had just released his own open-source aerodynamics
-solver: AeroSandbox. With his support, I have used AeroSandbox as a jumping-off point
+Thankfully, my friend, Peter Sharpe, had just released his own open-source aerodynamics
+solver: AeroSandbox. With his support, I have used AeroSandbox as a jumping-off point
to develop a solver package capable of unsteady simulations.
-Through the combined efforts of Peter Sharpe, Suhas Kodali, and me, Ptera Software was
-born. It is an easy-to-use, open-source, and actively-maintained UVLM package capable
-of analyzing flapping-wing flight. Moreover, it's written in Python, is well
+Through the combined efforts of Peter Sharpe, Suhas Kodali, and me, Ptera Software was
+born. It is an easy-to-use, open-source, and actively-maintained UVLM package capable
+of analyzing flapping-wing flight. Moreover, it's written in Python, is well
documented, tested, and validated.
Beginning with version 3.0.0, Ptera Software also includes a GUI developed by Zach Tait.
Although it is still rudimentary, we hope that it will help make this tool accessible to
even more users.
-With your help, I hope we will increase the open-source community's interest and
+With your help, I hope we will increase the open-source community's interest and
understanding of biological flight.
## Features
1. Various Aerodynamic Simulation Methods
- * Steady simulations can be run with a standard horseshoe vortex-lattice method
- (VLM) or a ring VLM.
- * Unsteady simulations use a ring unsteady VLM (UVLM) solver.
- * Unsteady simulations support both fixed and free wakes.
- * Unsteady simulations implement vortex aging to reduce numerical instabilities.
+ * Steady simulations can be run with a standard horseshoe vortex-lattice method
+ (VLM) or a ring VLM.
+ * Unsteady simulations use a ring unsteady VLM (UVLM) solver.
+ * Unsteady simulations support both fixed and free wakes.
+ * Unsteady simulations implement vortex aging to reduce numerical instabilities.
2. Customizable Aircraft Geometry
- * Aircraft can be defined as a collection of one or more wings of any dimensions and
- positions.
- * Wings can be defined as a collection of two or more wing cross sections of any
- dimensions and positions.
- * Wing cross sections can be specified to match the mean camber line of an airfoil.
- * The package comes with a massive database of airfoil to chose from.
- * Wings are automatically discretized into panels with customizable sizes and
- spacings.
+ * Aircraft can be defined as a collection of one or more wings of any dimensions and
+ positions.
+ * Wings can be defined as a collection of two or more wing cross sections of any
+ dimensions and positions.
+ * Wing cross sections can be specified to match the mean camber line of an airfoil.
+ * The package comes with a massive database of airfoil to chose from.
+ * Wings are automatically discretized into panels with customizable sizes and
+ spacings.
3. Customizable Aircraft Motion
- * The relative motion of wings and wing cross sections can be defined using any
- time-dependent functions of sweep, pitch, and heave angles.
+ * The relative motion of wings and wing cross sections can be defined using any
+ time-dependent functions of sweep, pitch, and heave angles.
4. Customizable Operating Points
- * Parameters such as the free-stream velocity, density, angle of attack, angle of
- sideslip, etc. can be changed by the user.
+ * Parameters such as the free-stream velocity, density, angle of attack, angle of
+ sideslip, etc. can be changed by the user.
5. High-Speed Simulations
- * Using Just-In-Time compilation, Ptera Software can solve many unsteady
- flapping-wing simulations in less than a minute!
- * Steady simulations take only seconds!
+ * Using Just-In-Time compilation, Ptera Software can solve many unsteady
+ flapping-wing simulations in less than a minute!
+ * Steady simulations take only seconds!
6. Simulations of Formation Flight
- * Since v2.0.0, Ptera Software has supported simulations with more than one
- airplane.
- * This feature can be used to analyze the aerodynamics of flapping-wing formation
- flight!
+ * Since v2.0.0, Ptera Software has supported simulations with more than one
+ airplane.
+ * This feature can be used to analyze the aerodynamics of flapping-wing formation
+ flight!
7. Features for Flapping-Wing Vehicle Design
- * Ptera Software is focused on developing features to facilitate designing
- flapping-wing vehicles.
- * For example, use the functions in the trim module to automatically search for a
- trim operating point for steady and unsteady simulations of aircraft.
+ * Ptera Software is focused on developing features to facilitate designing
+ flapping-wing vehicles.
+ * For example, use the functions in the trim module to automatically search for a
+ trim operating point for steady and unsteady simulations of aircraft.
8. A Basic GUI
- * This is still in its beta stage, but we will be adding more functionality over the
- next several releases.
+ * This is still in its beta stage, but we will be adding more functionality over the
+ next several releases.
## Installation and Use
-First things first, you will need a copy of Python 3.10, which you can download from the official Python website.
-At this time, I do not recommend using a version from the Anaconda distribution as it
+First things first, you will need a copy of Python 3.10, which you can download from the
+official Python website.
+At this time, I do not recommend using a version from the Anaconda distribution as it
could introduce compatibility issues with PyPI.
-There are two ways to use Ptera Software. The first is by downloading GitHub release,
-which will provide you your own copy of the source code, in which you can get a feel
-for how it works (this can also be accomplished by forking the main branch). The second
-is by importing the Ptera Software package using PyPI, which will allow you to call
-Ptera Software's functions in your own scripts. If you are new to this tool, I
-recommend first downloading a release, as this will give you access to the "examples"
+There are two ways to use Ptera Software. The first is by downloading GitHub release,
+which will provide you your own copy of the source code, in which you can get a feel
+for how it works (this can also be accomplished by forking the main branch). The second
+is by importing the Ptera Software package using PyPI, which will allow you to call
+Ptera Software's functions in your own scripts. If you are new to this tool, I
+recommend first downloading a release, as this will give you access to the "examples"
directory.
-Next, make sure you have an IDE in which you can run Ptera Software. I recommend using
-the Community Edition of PyCharm, which is free, powerful, and well documented. If
-you've never set up a Python project before, follow
-[this guide](https://www.jetbrains.com/help/pycharm/quick-start-guide.html) to set up a
-new project in PyCharm. If you'll be downloading a release, follow that tutorial's
+Next, make sure you have an IDE in which you can run Ptera Software. I recommend using
+the Community Edition of PyCharm, which is free, powerful, and well documented. If
+you've never set up a Python project before, follow
+[this guide](https://www.jetbrains.com/help/pycharm/quick-start-guide.html) to set up a
+new project in PyCharm. If you'll be downloading a release, follow that tutorial's
"Open an existing project guide." Otherwise, follow the "Create a new project guide."
### Downloading A Release
-To download a release, navigate to
-[the releases page](https://github.com/camUrban/PteraSoftware/releases) and download
-the latest zipped directory. Extract the contents, and set up a python project as
+To download a release, navigate to
+[the releases page](https://github.com/camUrban/PteraSoftware/releases) and download
+the latest zipped directory. Extract the contents, and set up a python project as
described in the PyCharm tutorial.
Then, open a command prompt window in your project's directory and enter:
@@ -124,8 +125,8 @@ via the command prompt in your fork's directory. You may also want to run:
if you plan on making significant changes to the software.
-Finally, open the "examples" folder, which contains several heavily commented scripts
-that demonstrate different features and simulations. Read through each example, and
+Finally, open the "examples" folder, which contains several heavily commented scripts
+that demonstrate different features and simulations. Read through each example, and
then run them to admire their pretty output!
### Importing As A Package
@@ -134,30 +135,32 @@ If you wish to use this package as a dependency in your own project, simply run:
```pip install pterasoftware```
-via the command prompt in your project's directory. Then, in a script that you'd like
+via the command prompt in your project's directory. Then, in a script that you'd like
to use features from Ptera Software, add:
```import pterasoftware as ps```
-If you haven't previously downloaded Ptera Software's source code, you can also learn
-about the available functions by reading their docstrings, which should be fetched
-automatically by many IDEs. Otherwise, you can return to the GitHub and read through
+If you haven't previously downloaded Ptera Software's source code, you can also learn
+about the available functions by reading their docstrings, which should be fetched
+automatically by many IDEs. Otherwise, you can return to the GitHub and read through
the docstrings there.
-I am hoping to implement a web-based documentation guide soon! If you'd like to
+I am hoping to implement a web-based documentation guide soon! If you'd like to
contribute to this, feel free to open a feature request issue and start a conversation!
### What If I'm Having Trouble Getting Set Up?
-Not to worry! I've made [a video](https://www.youtube.com/watch?v=oX8u2ZflJM4) that walks through getting Ptera Software up and
-running. It includes every step, from downloading Python for the first time to setting
-up your IDE to running the software. However, I recorded this video a while ago, so in it
-I download Python 3.8. For all versions of Ptera Software 3.1.0 and on, use Python 3.10
+Not to worry! I've made [a video](https://www.youtube.com/watch?v=oX8u2ZflJM4) that
+walks through getting Ptera Software up and
+running. It includes every step, from downloading Python for the first time to setting
+up your IDE to running the software. However, I recorded this video a while ago, so in
+it
+I download Python 3.8. For all versions of Ptera Software 3.1.0 and on, use Python 3.10
instead. If you still run into problems, feel free to open an issue for guidance.
## Example Code
-The following code snippet is all that is needed (after running pip install
+The following code snippet is all that is needed (after running pip install
pterasoftware) to run the steady horseshoe solver on an airplane with custom geometry.
```
@@ -199,8 +202,8 @@ ps.output.draw(solver=solver, scalar_type="lift", show_streamlines=True)
## Example Output
-This package currently supports three different solvers, a steady horseshoe vortex
-lattice method (VLM), a steady ring VLM, and an unsteady ring VLM (UVLM). Here are
+This package currently supports three different solvers, a steady horseshoe vortex
+lattice method (VLM), a steady ring VLM, and an unsteady ring VLM (UVLM). Here are
examples of the output you can expect to receive from each of them.
### Steady Horseshoe VLM
@@ -246,25 +249,25 @@ Additionally, these packages are useful for continued development of the softwar
## Validation
-Since the release of version 1.0.0, Ptera Software is now validated against
-experimental flapping-wing data! See the "validation" directory to run the test case
+Since the release of version 1.0.0, Ptera Software is now validated against
+experimental flapping-wing data! See the "validation" directory to run the test case
and read a report on the software's accuracy.
## How to Contribute
-As I said before, the primary goal of this project is to increase the open-source
-community's understanding and appreciation for unsteady aerodynamics in general and
-flapping-wing flight in particular. This will only happen through your participation.
-Feel free to request features, report bugs or security issues, and provide suggestions.
+As I said before, the primary goal of this project is to increase the open-source
+community's understanding and appreciation for unsteady aerodynamics in general and
+flapping-wing flight in particular. This will only happen through your participation.
+Feel free to request features, report bugs or security issues, and provide suggestions.
No comment is too big or small!
-Here is a list of changes I would like to make in the coming releases. If you want to
+Here is a list of changes I would like to make in the coming releases. If you want to
contribute and don't know where to start, this is for you!
### Testing
-* We should make sure that all the integration tests compare output against expected
-results. This means getting rid of all the "test_method_does_not_throw" tests.
+* We should make sure that all the integration tests compare output against expected
+ results. This means getting rid of all the "test_method_does_not_throw" tests.
* We should maintain the repository's testing coverage to be at least 80%.
### Style and Documentation
@@ -276,13 +279,13 @@ results. This means getting rid of all the "test_method_does_not_throw" tests.
### Features
-* We should implement a leading-edge model to account for flow separation. See
-"Modified Unsteady Vortex-Lattice Method to Study Flapping Wings in Hover Flight." by
-Bruno Roccia, Sergio Preidikman, Julio Massa, and Dean Mook for details.
+* We should implement a leading-edge model to account for flow separation. See
+ "Modified Unsteady Vortex-Lattice Method to Study Flapping Wings in Hover Flight." by
+ Bruno Roccia, Sergio Preidikman, Julio Massa, and Dean Mook for details.
* We should try to implement aeroelastic effects in Ptera Software's solvers.
-* Flapping wing controls is both fascinating and complicated. We should try to create a
-workflow in Ptera Software for controls systems identification for flapping-wing
-vehicles.
+* Flapping wing controls is both fascinating and complicated. We should try to create a
+ workflow in Ptera Software for controls systems identification for flapping-wing
+ vehicles.
## Credits
@@ -321,7 +324,7 @@ where applicable.
## Notes
-To the best of my ability, I am following SemVer conventions in naming my releases. I
-am also using the GitFlow method of branching for this project's development. This
-means that nightly builds will be available on the develop branch. The latest stable
+To the best of my ability, I am following SemVer conventions in naming my releases. I
+am also using the GitFlow method of branching for this project's development. This
+means that nightly builds will be available on the develop branch. The latest stable
releases can be found on the master branch.
diff --git a/SECURITY.md b/SECURITY.md
index 4912c10d..d3446d86 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,8 +2,8 @@
## Supported Versions
-Due to time constraints, only the most recent version will be updated with security
-patches.
+Due to time constraints, only the most recent version will be updated with security
+patches.
## Reporting a Vulnerability
diff --git a/benchmarks/unsteady_benchmark.py b/benchmarks/unsteady_benchmark.py
index 250492a5..f21aef8e 100644
--- a/benchmarks/unsteady_benchmark.py
+++ b/benchmarks/unsteady_benchmark.py
@@ -9,105 +9,59 @@
num_chordwise_panels = 5
num_spanwise_panels = 20
-example_airplane = ps.geometry.Airplane(
- name="Example Airplane",
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- symmetric=True,
- num_chordwise_panels=num_chordwise_panels,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- num_spanwise_panels=num_spanwise_panels,
- spanwise_spacing="uniform",
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0000",
- ),
- ),
- ps.geometry.WingCrossSection(
- num_spanwise_panels=num_spanwise_panels,
- spanwise_spacing="uniform",
- x_le=0.625,
- y_le=5.0,
- chord=0.5,
- airfoil=ps.geometry.Airfoil(
- name="naca0000",
- ),
- ),
- ],
- ),
- ],
-)
+example_airplane = ps.geometry.Airplane(name="Example Airplane", wings=[
+ ps.geometry.Wing(name="Main Wing", symmetric=True,
+ num_chordwise_panels=num_chordwise_panels, chordwise_spacing="uniform",
+ wing_cross_sections=[
+ ps.geometry.WingCrossSection(num_spanwise_panels=num_spanwise_panels,
+ spanwise_spacing="uniform", chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0000", ), ),
+ ps.geometry.WingCrossSection(num_spanwise_panels=num_spanwise_panels,
+ spanwise_spacing="uniform", x_le=0.625, y_le=5.0, chord=0.5,
+ airfoil=ps.geometry.Airfoil(name="naca0000", ), ), ], ), ], )
upper_wing_root_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[0],
-)
+ base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[0], )
upper_wing_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1],
- sweeping_amplitude=15.0,
- sweeping_period=1 / flapping_frequency,
- sweeping_spacing="sine",
- pitching_amplitude=5.0,
- pitching_period=1 / flapping_frequency,
- pitching_spacing="sine",
- heaving_amplitude=5.0,
- heaving_period=1 / flapping_frequency,
- heaving_spacing="sine",
-)
-
-upper_wing_movement = ps.movement.WingMovement(
- base_wing=example_airplane.wings[0],
- wing_cross_sections_movements=[
- upper_wing_root_wing_cross_section_movement,
- upper_wing_tip_wing_cross_section_movement,
- ],
-)
+ sweeping_amplitude=15.0, sweeping_period=1 / flapping_frequency,
+ sweeping_spacing="sine", pitching_amplitude=5.0,
+ pitching_period=1 / flapping_frequency, pitching_spacing="sine",
+ heaving_amplitude=5.0, heaving_period=1 / flapping_frequency,
+ heaving_spacing="sine", )
+
+upper_wing_movement = ps.movement.WingMovement(base_wing=example_airplane.wings[0],
+ wing_cross_sections_movements=[upper_wing_root_wing_cross_section_movement,
+ upper_wing_tip_wing_cross_section_movement, ], )
del upper_wing_root_wing_cross_section_movement
del upper_wing_tip_wing_cross_section_movement
-airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=example_airplane,
- wing_movements=[upper_wing_movement],
-)
+airplane_movement = ps.movement.AirplaneMovement(base_airplane=example_airplane,
+ wing_movements=[upper_wing_movement], )
del upper_wing_movement
-example_operating_point = ps.operating_point.OperatingPoint(
- density=1.225,
- beta=0.0,
- velocity=10.0,
- alpha=0.0,
-)
+example_operating_point = ps.operating_point.OperatingPoint(density=1.225, beta=0.0,
+ velocity=10.0, alpha=0.0, )
operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=example_operating_point,
-)
+ base_operating_point=example_operating_point, )
-movement = ps.movement.Movement(
- airplane_movements=[airplane_movement],
- operating_point_movement=operating_point_movement,
-)
+movement = ps.movement.Movement(airplane_movements=[airplane_movement],
+ operating_point_movement=operating_point_movement, )
del airplane_movement
del operating_point_movement
-example_problem = ps.problems.UnsteadyProblem(
- movement=movement, only_final_results=True
-)
+example_problem = ps.problems.UnsteadyProblem(movement=movement,
+ only_final_results=True)
example_solver = (
ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
- unsteady_problem=example_problem,
- )
-)
+ unsteady_problem=example_problem, ))
del example_problem
-example_solver.run(
- prescribed_wake=True,
- calculate_streamlines=False,
-)
+example_solver.run(prescribed_wake=True, calculate_streamlines=False, )
diff --git a/benchmarks/unsteady_benchmark_converge.py b/benchmarks/unsteady_benchmark_converge.py
index 4ad98122..30e4062f 100644
--- a/benchmarks/unsteady_benchmark_converge.py
+++ b/benchmarks/unsteady_benchmark_converge.py
@@ -4,105 +4,59 @@
num_chordwise_panels = 5
num_spanwise_panels = 20
-example_airplane = ps.geometry.Airplane(
- name="Example Airplane",
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- symmetric=True,
- num_chordwise_panels=num_chordwise_panels,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- num_spanwise_panels=num_spanwise_panels,
- spanwise_spacing="uniform",
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0000",
- ),
- ),
- ps.geometry.WingCrossSection(
- num_spanwise_panels=num_spanwise_panels,
- spanwise_spacing="uniform",
- x_le=0.625,
- y_le=5.0,
- chord=0.5,
- airfoil=ps.geometry.Airfoil(
- name="naca0000",
- ),
- ),
- ],
- ),
- ],
-)
+example_airplane = ps.geometry.Airplane(name="Example Airplane", wings=[
+ ps.geometry.Wing(name="Main Wing", symmetric=True,
+ num_chordwise_panels=num_chordwise_panels, chordwise_spacing="uniform",
+ wing_cross_sections=[
+ ps.geometry.WingCrossSection(num_spanwise_panels=num_spanwise_panels,
+ spanwise_spacing="uniform", chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0000", ), ),
+ ps.geometry.WingCrossSection(num_spanwise_panels=num_spanwise_panels,
+ spanwise_spacing="uniform", x_le=0.625, y_le=5.0, chord=0.5,
+ airfoil=ps.geometry.Airfoil(name="naca0000", ), ), ], ), ], )
upper_wing_root_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[0],
-)
+ base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[0], )
upper_wing_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1],
- sweeping_amplitude=15.0,
- sweeping_period=1 / flapping_frequency,
- sweeping_spacing="sine",
- pitching_amplitude=5.0,
- pitching_period=1 / flapping_frequency,
- pitching_spacing="sine",
- heaving_amplitude=5.0,
- heaving_period=1 / flapping_frequency,
- heaving_spacing="sine",
-)
+ sweeping_amplitude=15.0, sweeping_period=1 / flapping_frequency,
+ sweeping_spacing="sine", pitching_amplitude=5.0,
+ pitching_period=1 / flapping_frequency, pitching_spacing="sine",
+ heaving_amplitude=5.0, heaving_period=1 / flapping_frequency,
+ heaving_spacing="sine", )
-upper_wing_movement = ps.movement.WingMovement(
- base_wing=example_airplane.wings[0],
- wing_cross_sections_movements=[
- upper_wing_root_wing_cross_section_movement,
- upper_wing_tip_wing_cross_section_movement,
- ],
-)
+upper_wing_movement = ps.movement.WingMovement(base_wing=example_airplane.wings[0],
+ wing_cross_sections_movements=[upper_wing_root_wing_cross_section_movement,
+ upper_wing_tip_wing_cross_section_movement, ], )
del upper_wing_root_wing_cross_section_movement
del upper_wing_tip_wing_cross_section_movement
-airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=example_airplane,
- wing_movements=[upper_wing_movement],
-)
+airplane_movement = ps.movement.AirplaneMovement(base_airplane=example_airplane,
+ wing_movements=[upper_wing_movement], )
del example_airplane
del upper_wing_movement
-example_operating_point = ps.operating_point.OperatingPoint(
- density=1.225,
- beta=0.0,
- velocity=10.0,
- alpha=0.0,
-)
+example_operating_point = ps.operating_point.OperatingPoint(density=1.225, beta=0.0,
+ velocity=10.0, alpha=0.0, )
operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=example_operating_point,
-)
+ base_operating_point=example_operating_point, )
del example_operating_point
-movement = ps.movement.Movement(
- airplane_movements=[airplane_movement],
- operating_point_movement=operating_point_movement,
-)
+movement = ps.movement.Movement(airplane_movements=[airplane_movement],
+ operating_point_movement=operating_point_movement, )
del airplane_movement
del operating_point_movement
-ps.convergence.analyze_unsteady_convergence(
- ref_movement=movement,
- prescribed_wake=True,
- free_wake=True,
- num_cycles_bounds=(1, 3),
- num_chords_bounds=None,
- panel_aspect_ratio_bounds=(4, 1),
- num_chordwise_panels_bounds=(5, 10),
- convergence_criteria=5.0,
-)
+ps.convergence.analyze_unsteady_convergence(ref_movement=movement, prescribed_wake=True,
+ free_wake=True, num_cycles_bounds=(1, 3), num_chords_bounds=None,
+ panel_aspect_ratio_bounds=(4, 1), num_chordwise_panels_bounds=(5, 10),
+ convergence_criteria=5.0, )
# Converged result:
# wake=false
diff --git a/benchmarks/unsteady_benchmark_timed.py b/benchmarks/unsteady_benchmark_timed.py
index 17c504b7..c21ad257 100644
--- a/benchmarks/unsteady_benchmark_timed.py
+++ b/benchmarks/unsteady_benchmark_timed.py
@@ -96,7 +96,8 @@
del airplane_movement
del operating_point_movement
-example_problem = ps.problems.UnsteadyProblem(movement=movement, only_final_results=True)
+example_problem = ps.problems.UnsteadyProblem(movement=movement,
+only_final_results=True)
unsteady_solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
unsteady_problem=example_problem,
diff --git a/examples/analyze_steady_trim_example.py b/examples/analyze_steady_trim_example.py
index 8a4be2de..4b551db3 100644
--- a/examples/analyze_steady_trim_example.py
+++ b/examples/analyze_steady_trim_example.py
@@ -12,55 +12,16 @@
# Create an airplane object. Read through the solver examples for more details on
# creating this object.
-default_airplane = ps.geometry.Airplane(
- weight=250,
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ps.geometry.Wing(
- x_le=7.50,
- z_le=0.25,
- symmetric=True,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=0.0,
- chord=0.5,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=1.0,
- chord=0.5,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+default_airplane = ps.geometry.Airplane(weight=250, wings=[
+ ps.geometry.Wing(symmetric=True, wing_cross_sections=[
+ ps.geometry.WingCrossSection(airfoil=ps.geometry.Airfoil(name="naca2412", ), ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
+ ps.geometry.Wing(x_le=7.50, z_le=0.25, symmetric=True, wing_cross_sections=[
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=0.0, chord=0.5, twist=-5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=1.0, chord=0.5, twist=-5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Create an operating point object for this example's problem. Be sure to specify an
# external thrust because this aircraft is not flapping, and will therefore generate
@@ -69,20 +30,15 @@
default_operating_point = ps.operating_point.OperatingPoint(external_thrust=5)
# Construct this example's problem object.
-default_problem = ps.problems.SteadyProblem(
- airplanes=[default_airplane], operating_point=default_operating_point
-)
+default_problem = ps.problems.SteadyProblem(airplanes=[default_airplane],
+ operating_point=default_operating_point)
# Call the analyze_steady_trim function to search for a trim condition (thrust
# balances drag, weight balances lift, and all moments are close to zero) within a
# certain set of bounds.
-trim_conditions = ps.trim.analyze_steady_trim(
- problem=default_problem,
- velocity_bounds=(5, 15),
- alpha_bounds=(-10, 10),
- beta_bounds=(-1, 1),
- external_thrust_bounds=(0, 10),
-)
+trim_conditions = ps.trim.analyze_steady_trim(problem=default_problem,
+ velocity_bounds=(5, 15), alpha_bounds=(-10, 10), beta_bounds=(-1, 1),
+ external_thrust_bounds=(0, 10), )
# Log the trim conditions. If these display "nan", then the trim function couldn't
# find a trimmed state.
diff --git a/examples/analyze_unsteady_trim_example.py b/examples/analyze_unsteady_trim_example.py
index 28d4035e..ed2c76c2 100644
--- a/examples/analyze_unsteady_trim_example.py
+++ b/examples/analyze_unsteady_trim_example.py
@@ -12,98 +12,35 @@
# Create an airplane object. Read through the solver examples for more details on
# creating this object.
-example_airplane = ps.geometry.Airplane(
- x_ref=0.14,
- weight=420,
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- num_chordwise_panels=5,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- num_spanwise_panels=5,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ps.geometry.Wing(
- x_le=5,
- symmetric=True,
- num_chordwise_panels=5,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- num_spanwise_panels=5,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=1.0,
- chord=1.0,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+example_airplane = ps.geometry.Airplane(x_ref=0.14, weight=420, wings=[
+ ps.geometry.Wing(symmetric=True, num_chordwise_panels=5, wing_cross_sections=[
+ ps.geometry.WingCrossSection(num_spanwise_panels=5,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
+ ps.geometry.Wing(x_le=5, symmetric=True, num_chordwise_panels=5,
+ wing_cross_sections=[
+ ps.geometry.WingCrossSection(num_spanwise_panels=5, twist=-5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=1.0, chord=1.0, twist=-5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Create a movement for this example's airplane. Read through the unsteady solver
# examples for more details on this type of object.
-example_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=example_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=example_airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[
- 0
- ].wing_cross_sections[0]
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_period=1.0,
- sweeping_amplitude=5.0,
- heaving_period=1.0,
- heaving_amplitude=10.0,
- ),
- ],
- ),
- ps.movement.WingMovement(
- base_wing=example_airplane.wings[1],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[
- 1
- ].wing_cross_sections[0]
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[
- 1
- ].wing_cross_sections[1]
- ),
- ],
- ),
- ],
-)
+example_airplane_movement = ps.movement.AirplaneMovement(base_airplane=example_airplane,
+ wing_movements=[ps.movement.WingMovement(base_wing=example_airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[0]),
+ ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[
+ 1], sweeping_period=1.0, sweeping_amplitude=5.0, heaving_period=1.0,
+ heaving_amplitude=10.0, ), ], ),
+ ps.movement.WingMovement(base_wing=example_airplane.wings[1],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[
+ 0]), ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[
+ 1]), ], ), ], )
# Create an operating point object for this example's problem using the default values.
example_operating_point = ps.operating_point.OperatingPoint()
@@ -111,30 +48,22 @@
# Create an operating point movement object. Read through the unsteady solver
# examples for more details on this type of object.
example_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=example_operating_point
-)
+ base_operating_point=example_operating_point)
# Construct this example's movement and problem object. Only calculate final results
# to speed up the solver.
-example_movement = ps.movement.Movement(
- airplane_movements=[example_airplane_movement],
- operating_point_movement=example_operating_point_movement,
-)
-example_problem = ps.problems.UnsteadyProblem(
- movement=example_movement,
- only_final_results=False,
-)
+example_movement = ps.movement.Movement(airplane_movements=[example_airplane_movement],
+ operating_point_movement=example_operating_point_movement, )
+example_problem = ps.problems.UnsteadyProblem(movement=example_movement,
+ only_final_results=False, )
# Call the analyze_unsteady_trim function to search for a trim condition (thrust
# balances drag, weight balances lift, and all moments are close to zero) within a
# certain set of bounds.
trim_conditions = ps.trim.analyze_unsteady_trim(
airplane_movement=example_airplane_movement,
- operating_point=example_operating_point,
- velocity_bounds=(5, 15),
- alpha_bounds=(-10, 10),
- beta_bounds=(-0.1, 0.1),
-)
+ operating_point=example_operating_point, velocity_bounds=(5, 15),
+ alpha_bounds=(-10, 10), beta_bounds=(-0.1, 0.1), )
# Log the trim conditions. If these display "nan", then the trim function couldn't
# find a trimmed state.
diff --git a/examples/steady_convergence_example.py b/examples/steady_convergence_example.py
index d6516cc8..d20c6bf0 100644
--- a/examples/steady_convergence_example.py
+++ b/examples/steady_convergence_example.py
@@ -6,132 +6,42 @@
# Create two airplane objects. Read through the solver and formation examples for
# more details on creating these objects.
-leading_airplane = ps.geometry.Airplane(
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.25,
- y_le=10.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ps.geometry.Wing(
- x_le=5.0,
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
-trailing_airplane = ps.geometry.Airplane(
- x_ref=10,
- y_ref=-5,
- wings=[
- ps.geometry.Wing(
- x_le=10,
- y_le=-5,
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.25,
- y_le=10.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ps.geometry.Wing(
- x_le=15.0,
- y_le=-5,
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+leading_airplane = ps.geometry.Airplane(wings=[
+ ps.geometry.Wing(symmetric=True, chordwise_spacing="uniform", wing_cross_sections=[
+ ps.geometry.WingCrossSection(airfoil=ps.geometry.Airfoil(name="naca2412", ),
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ),
+ ps.geometry.WingCrossSection(x_le=0.25, y_le=10.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
+ ps.geometry.Wing(x_le=5.0, symmetric=True, chordwise_spacing="uniform",
+ wing_cross_sections=[
+ ps.geometry.WingCrossSection(airfoil=ps.geometry.Airfoil(name="naca0012", ),
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
+trailing_airplane = ps.geometry.Airplane(x_ref=10, y_ref=-5, wings=[
+ ps.geometry.Wing(x_le=10, y_le=-5, symmetric=True, chordwise_spacing="uniform",
+ wing_cross_sections=[
+ ps.geometry.WingCrossSection(airfoil=ps.geometry.Airfoil(name="naca2412", ),
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ),
+ ps.geometry.WingCrossSection(x_le=0.25, y_le=10.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
+ ps.geometry.Wing(x_le=15.0, y_le=-5, symmetric=True, chordwise_spacing="uniform",
+ wing_cross_sections=[
+ ps.geometry.WingCrossSection(airfoil=ps.geometry.Airfoil(name="naca0012", ),
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Create an operating point object.
operating_point = ps.operating_point.OperatingPoint()
# Create a steady problem. We will pass this into the convergence function.
-problem = ps.problems.SteadyProblem(
- airplanes=[leading_airplane, trailing_airplane],
- operating_point=operating_point,
-)
+problem = ps.problems.SteadyProblem(airplanes=[leading_airplane, trailing_airplane],
+ operating_point=operating_point, )
del leading_airplane
del trailing_airplane
@@ -144,13 +54,9 @@
# return the parameters it found to result in a converged solution. See the
# analyze_steady_convergence function docstring for more details. The progress and
# results are displayed to the console.
-ps.convergence.analyze_steady_convergence(
- ref_problem=problem,
- solver_type="steady ring vortex lattice method",
- panel_aspect_ratio_bounds=(4, 1),
- num_chordwise_panels_bounds=(3, 8),
- convergence_criteria=1.0,
-)
+ps.convergence.analyze_steady_convergence(ref_problem=problem,
+ solver_type="steady ring vortex lattice method", panel_aspect_ratio_bounds=(4, 1),
+ num_chordwise_panels_bounds=(3, 8), convergence_criteria=1.0, )
# Check the console that the convergence analysis found that the solution converged
# with the following parameters:
diff --git a/examples/steady_horseshoe_vortex_lattice_method_solver.py b/examples/steady_horseshoe_vortex_lattice_method_solver.py
index 46bf9ad6..d7b259ba 100644
--- a/examples/steady_horseshoe_vortex_lattice_method_solver.py
+++ b/examples/steady_horseshoe_vortex_lattice_method_solver.py
@@ -18,159 +18,110 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- # Define the location of the leading edge of the wing relative to the
- # global coordinate system fixed front left corner of the first
- # airplane's first wing's root wing cross section. These values all
+ s_ref=None, b_ref=None, c_ref=None, wings=[ps.geometry.Wing(name="Main Wing",
+ # Define the location of the leading edge of the wing relative to the
+ # global coordinate system fixed front left corner of the first
+ # airplane's first wing's root wing cross section. These values all
+ # default to 0.0 meters.
+ x_le=0.0, y_le=0.0, z_le=0.0,
+ # Declare that this wing is symmetric. This means that the geometry will
+ # be reflected across plane of this wing's root wing cross section. Note
+ # that the geometry coordinates are defined as such: If you were riding
+ # in the airplane, the positive x direction would point behind you,
+ # the positive y direction would point out of your right wing, and the
+ # positive z direction would point upwards, out of your chair. These
+ # directions form a right-handed coordinate system. The default value of
+ # "symmetric" is False.
+ symmetric=True,
+ # Define the number of chordwise panels on the wing, and the spacing
+ # between them. The number of chordwise panels defaults to 8 panels. The
+ # spacing defaults to "cosine", which makes the panels relatively finer,
+ # in the chordwise direction, near the leading and trailing edges. The
+ # other option is "uniform".
+ num_chordwise_panels=6, chordwise_spacing="cosine",
+ # Every wing has a list of wing cross sections. In order for the geometry
+ # output to be sensible, each wing must have at least two wing cross
+ # sections.
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ # Define the location of the leading edge of the wing cross
+ # section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- # Declare that this wing is symmetric. This means that the geometry will
- # be reflected across plane of this wing's root wing cross section. Note
- # that the geometry coordinates are defined as such: If you were riding
- # in the airplane, the positive x direction would point behind you,
- # the positive y direction would point out of your right wing, and the
- # positive z direction would point upwards, out of your chair. These
- # directions form a right-handed coordinate system. The default value of
- # "symmetric" is False.
- symmetric=True,
- # Define the number of chordwise panels on the wing, and the spacing
- # between them. The number of chordwise panels defaults to 8 panels. The
- # spacing defaults to "cosine", which makes the panels relatively finer,
- # in the chordwise direction, near the leading and trailing edges. The
- # other option is "uniform".
- num_chordwise_panels=6,
- chordwise_spacing="cosine",
- # Every wing has a list of wing cross sections. In order for the geometry
- # output to be sensible, each wing must have at least two wing cross
- # sections.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- # Define the location of the leading edge of the wing cross
- # section relative to the wing's leading edge. These values all
- # default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- # Define the twist of the wing cross section in degrees. This is
- # equivalent to incidence angle of cross section. The twist is
- # about the leading edge. Note that the twist is only stable up
- # to 45.0 degrees. Values above that produce unexpected results.
- # This will be fixed in a future release. The default value is
- # 0.0 degrees. Positive twist corresponds to positive rotation
- # about the y axis, as defined by the right-hand rule.
- twist=0.0,
- # Define the type of control surface. The options are "symmetric"
- # and "asymmetric". This is only applicable if your wing is also
- # symmetric. If so, symmetric control surfaces will deflect in
- # the same direction, like flaps, while asymmetric control
- # surfaces will deflect in opposite directions, like ailerons.
- # The default value is "symmetric".
- control_surface_type="symmetric",
- # Define the point on the airfoil where the control surface
- # hinges. This is expressed as a faction of the chord length,
- # back from the leading edge. The default value is 0.75.
- control_surface_hinge_point=0.75,
- # Define the deflection of the control surface in degrees. The
- # default is 0.0 degrees.
- control_surface_deflection=0.0,
- # Define the number of spanwise panels on the wing cross section,
- # and the spacing between them. The number of spanwise panels
- # defaults to 8 panels. The spacing defaults to "cosine",
- # which makes the panels relatively finer, in the spanwise
- # direction, near the cross section ends. The other option is
- # "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
- # Set the chord of this cross section to be 1.75 meters. This
- # value defaults to 1.0 meter.
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- # Give the airfoil a name. This defaults to "Untitled
- # Airfoil". This name should correspond to a name in the
- # airfoil directory or a NACA four series airfoil, unless you
- # are passing in your own coordinates.
- name="naca2412",
- # If you wish to pass in coordinates, set this to an N x 2
- # array of the airfoil's coordinates, where N is the number
- # of coordinates. Treat this as an immutable, don't edit
- # directly after initialization. If you wish to load
- # coordinates from the airfoil directory, leave this as None.
- # The default is None. Make sure that any airfoil coordinates
- # used range in x from 0 to 1.
- coordinates=None,
- # This is the variable that determines whether you would like
- # to repanel the airfoil coordinates. This applies to
- # coordinates passed in by the user or to the directory
- # coordinates. I highly recommended setting this to True. The
- # default is True.
- repanel=True,
- # This is number of points to use if repaneling the airfoil.
- # It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
- # Define the next wing cross section. From here on out,
- # the declarations will not be as commented as the previous. See the
- # above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- z_le=1.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ x_le=0.0, y_le=0.0, z_le=0.0,
+ # Define the twist of the wing cross section in degrees. This is
+ # equivalent to incidence angle of cross section. The twist is
+ # about the leading edge. Note that the twist is only stable up
+ # to 45.0 degrees. Values above that produce unexpected results.
+ # This will be fixed in a future release. The default value is
+ # 0.0 degrees. Positive twist corresponds to positive rotation
+ # about the y axis, as defined by the right-hand rule.
+ twist=0.0, # Define the type of control surface. The options are "symmetric"
+ # and "asymmetric". This is only applicable if your wing is also
+ # symmetric. If so, symmetric control surfaces will deflect in
+ # the same direction, like flaps, while asymmetric control
+ # surfaces will deflect in opposite directions, like ailerons.
+ # The default value is "symmetric".
+ control_surface_type="symmetric",
+ # Define the point on the airfoil where the control surface
+ # hinges. This is expressed as a faction of the chord length,
+ # back from the leading edge. The default value is 0.75.
+ control_surface_hinge_point=0.75,
+ # Define the deflection of the control surface in degrees. The
+ # default is 0.0 degrees.
+ control_surface_deflection=0.0,
+ # Define the number of spanwise panels on the wing cross section,
+ # and the spacing between them. The number of spanwise panels
+ # defaults to 8 panels. The spacing defaults to "cosine",
+ # which makes the panels relatively finer, in the spanwise
+ # direction, near the cross section ends. The other option is
+ # "uniform".
+ num_spanwise_panels=8, spanwise_spacing="cosine",
+ # Set the chord of this cross section to be 1.75 meters. This
+ # value defaults to 1.0 meter.
+ chord=1.75, airfoil=ps.geometry.Airfoil(
+ # Give the airfoil a name. This defaults to "Untitled
+ # Airfoil". This name should correspond to a name in the
+ # airfoil directory or a NACA four series airfoil, unless you
+ # are passing in your own coordinates.
+ name="naca2412",
+ # If you wish to pass in coordinates, set this to an N x 2
+ # array of the airfoil's coordinates, where N is the number
+ # of coordinates. Treat this as an immutable, don't edit
+ # directly after initialization. If you wish to load
+ # coordinates from the airfoil directory, leave this as None.
+ # The default is None. Make sure that any airfoil coordinates
+ # used range in x from 0 to 1.
+ coordinates=None,
+ # This is the variable that determines whether you would like
+ # to repanel the airfoil coordinates. This applies to
+ # coordinates passed in by the user or to the directory
+ # coordinates. I highly recommended setting this to True. The
+ # default is True.
+ repanel=True,
+ # This is number of points to use if repaneling the airfoil.
+ # It is ignored if the repanel is False. The default is 400.
+ n_points_per_side=400, ), ),
+ # Define the next wing cross section. From here on out,
+ # the declarations will not be as commented as the previous. See the
+ # above comments if you have questions.
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, z_le=1.0, chord=1.5,
+ twist=5.0, airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="V-Tail",
- x_le=6.75,
- z_le=0.25,
- symmetric=True,
+ ps.geometry.Wing(name="V-Tail", x_le=6.75, z_le=0.25, symmetric=True,
# Define this wing's root wing cross section.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- z_le=1.0,
- chord=1.0,
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, z_le=1.0, chord=1.0,
twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Define a new operating point object. This defines the state at which the airplane
# object is operating.
@@ -186,8 +137,7 @@
velocity=10.0,
# Define the angle of attack the airplane is experiencing. This defaults to 5.0
# degrees.
- alpha=1.0,
-)
+ alpha=1.0, )
# Define a new steady problem. A steady problem contains an airplane object and an
# operating point object.
@@ -195,8 +145,7 @@
# Set this steady problem's airplane object to be the one we just created.
airplanes=[example_airplane],
# Set this steady problem's operating point object ot be the one we just created.
- operating_point=example_operating_point,
-)
+ operating_point=example_operating_point, )
# Now, the airplane and operating point object exist within the steady problem
# object. I like to delete the external pointers to these objects to ease debugging.
@@ -206,10 +155,10 @@
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.steady_horseshoe_vortex_lattice_method.SteadyHorseshoeVortexLatticeMethodSolver(
+example_solver = (ps.steady_horseshoe_vortex_lattice_method
+.SteadyHorseshoeVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- steady_problem=example_problem
-)
+ steady_problem=example_problem))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver. Again, this is unnecessary, I just like to do this to ease debugging.
@@ -220,15 +169,13 @@
# This parameter determines the detail of information that the solver's logger
# will output while running. The options are, in order of detail and severity,
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
- logging_level="Warning",
-)
+ logging_level="Warning", )
# Call this function from the output module to print the results.
ps.output.print_steady_results(steady_solver=example_solver)
# Call the software's draw function on the solver.
-ps.output.draw(
- solver=example_solver,
+ps.output.draw(solver=example_solver,
# Tell the draw function to color the aircraft's wing panels with the local lift
# coefficient. The valid arguments for this parameter are None, "induced drag",
# "side force", or "lift".
@@ -241,8 +188,7 @@
show_wake_vortices=False,
# Tell the draw function to not save the drawing as an image file. This way,
# the drawing will still be displayed but not saved. This value defaults to false.
- save=False,
-)
+ save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/examples/steady_ring_vortex_lattice_method_solver.py b/examples/steady_ring_vortex_lattice_method_solver.py
index ba494e56..04c321e1 100644
--- a/examples/steady_ring_vortex_lattice_method_solver.py
+++ b/examples/steady_ring_vortex_lattice_method_solver.py
@@ -18,187 +18,122 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- # Define the location of the leading edge of the wing relative to the
- # global coordinate system fixed front left corner of the first
- # airplane's first wing's root wing cross section. These values all
+ s_ref=None, b_ref=None, c_ref=None, wings=[ps.geometry.Wing(name="Main Wing",
+ # Define the location of the leading edge of the wing relative to the
+ # global coordinate system fixed front left corner of the first
+ # airplane's first wing's root wing cross section. These values all
+ # default to 0.0 meters.
+ x_le=0.0, y_le=0.0, z_le=0.0,
+ # Declare that this wing is symmetric. This means that the geometry will
+ # be reflected across plane of this wing's root wing cross section. Note
+ # that the geometry coordinates are defined as such: If you were riding
+ # in the airplane, the positive x direction would point behind you,
+ # the positive y direction would point out of your right wing, and the
+ # positive z direction would point upwards, out of your chair. These
+ # directions form a right-handed coordinate system. The default value of
+ # "symmetric" is false.
+ symmetric=True,
+ # Define the number of chordwise panels on the wing, and the spacing
+ # between them. The number of chordwise panels defaults to 8 panels. The
+ # spacing defaults to "cosine", which makes the panels relatively finer,
+ # in the chordwise direction, near the leading and trailing edges. The
+ # other option is "uniform".
+ num_chordwise_panels=8, chordwise_spacing="cosine",
+ # Every wing has a list of wing cross sections. In order for the geometry
+ # output to be sensible, each wing must have at least two wing cross
+ # sections.
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ # Define the location of the leading edge of the wing cross
+ # section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- # Declare that this wing is symmetric. This means that the geometry will
- # be reflected across plane of this wing's root wing cross section. Note
- # that the geometry coordinates are defined as such: If you were riding
- # in the airplane, the positive x direction would point behind you,
- # the positive y direction would point out of your right wing, and the
- # positive z direction would point upwards, out of your chair. These
- # directions form a right-handed coordinate system. The default value of
- # "symmetric" is false.
- symmetric=True,
- # Define the number of chordwise panels on the wing, and the spacing
- # between them. The number of chordwise panels defaults to 8 panels. The
- # spacing defaults to "cosine", which makes the panels relatively finer,
- # in the chordwise direction, near the leading and trailing edges. The
- # other option is "uniform".
- num_chordwise_panels=8,
- chordwise_spacing="cosine",
- # Every wing has a list of wing cross sections. In order for the geometry
- # output to be sensible, each wing must have at least two wing cross
- # sections.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- # Define the location of the leading edge of the wing cross
- # section relative to the wing's leading edge. These values all
- # default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- # Define the twist of the wing cross section in degrees. This is
- # equivalent to incidence angle of cross section. The twist is
- # about the leading edge. Note that the twist is only stable up
- # to 45.0 degrees. Values above that produce unexpected results.
- # This will be fixed in a future release. The default value is
- # 0.0 degrees. Positive twist corresponds to positive rotation
- # about the y axis, as defined by the right-hand rule.
- twist=0.0,
- # Define the type of control surface. The options are "symmetric"
- # and "asymmetric". This is only applicable if your wing is also
- # symmetric. If so, symmetric control surfaces will deflect in
- # the same direction, like flaps, while asymmetric control
- # surfaces will deflect in opposite directions, like ailerons.
- # The default value is "symmetric".
- control_surface_type="asymmetric",
- # Define the point on the airfoil where the control surface
- # hinges. This is expressed as a faction of the chord length,
- # back from the leading edge. The default value is 0.75.
- control_surface_hinge_point=0.75,
- # Define the deflection of the control surface in degrees. The
- # default is 0.0 degrees. We'll set it to 10.0 degrees to show an
- # example of an aileron deflection.
- control_surface_deflection=10.0,
- # Define the number of spanwise panels on the wing cross section,
- # and the spacing between them. The number of spanwise panels
- # defaults to 8 panels. The spacing defaults to "cosine",
- # which makes the panels relatively finer, in the spanwise
- # direction, near the cross section ends. The other option is
- # "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
- # Set the chord of this cross section to be 1.75 meters. This
- # value defaults to 1.0 meter.
- chord=1.5,
- airfoil=ps.geometry.Airfoil(
- # Give the airfoil a name. This defaults to "Untitled
- # Airfoil". This name should correspond to a name in the
- # airfoil directory or a NACA four series airfoil, unless you
- # are passing in your own coordinates.
- name="naca2412",
- # If you wish to pass in coordinates, set this to an N x 2
- # array of the airfoil's coordinates, where N is the number
- # of coordinates. Treat this as an immutable, don't edit
- # directly after initialization. If you wish to load
- # coordinates from the airfoil directory, leave this as None.
- # The default is None. Make sure that any airfoil coordinates
- # used range in x from 0 to 1.
- coordinates=None,
- # This is the variable that determines whether you would like
- # to repanel the airfoil coordinates. This applies to
- # coordinates passed in by the user or to the directory
- # coordinates. I highly recommended setting this to True. The
- # default is True.
- repanel=True,
- # This is number of points to use if repaneling the airfoil.
- # It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
- # Define the next wing cross section. From here on out,
- # the declarations will not be as commented as the previous. See the
- # above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=1.5,
- y_le=6.0,
- z_le=0.5,
- chord=0.75,
- control_surface_type="asymmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=10.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ x_le=0.0, y_le=0.0, z_le=0.0,
+ # Define the twist of the wing cross section in degrees. This is
+ # equivalent to incidence angle of cross section. The twist is
+ # about the leading edge. Note that the twist is only stable up
+ # to 45.0 degrees. Values above that produce unexpected results.
+ # This will be fixed in a future release. The default value is
+ # 0.0 degrees. Positive twist corresponds to positive rotation
+ # about the y axis, as defined by the right-hand rule.
+ twist=0.0, # Define the type of control surface. The options are "symmetric"
+ # and "asymmetric". This is only applicable if your wing is also
+ # symmetric. If so, symmetric control surfaces will deflect in
+ # the same direction, like flaps, while asymmetric control
+ # surfaces will deflect in opposite directions, like ailerons.
+ # The default value is "symmetric".
+ control_surface_type="asymmetric",
+ # Define the point on the airfoil where the control surface
+ # hinges. This is expressed as a faction of the chord length,
+ # back from the leading edge. The default value is 0.75.
+ control_surface_hinge_point=0.75,
+ # Define the deflection of the control surface in degrees. The
+ # default is 0.0 degrees. We'll set it to 10.0 degrees to show an
+ # example of an aileron deflection.
+ control_surface_deflection=10.0,
+ # Define the number of spanwise panels on the wing cross section,
+ # and the spacing between them. The number of spanwise panels
+ # defaults to 8 panels. The spacing defaults to "cosine",
+ # which makes the panels relatively finer, in the spanwise
+ # direction, near the cross section ends. The other option is
+ # "uniform".
+ num_spanwise_panels=8, spanwise_spacing="cosine",
+ # Set the chord of this cross section to be 1.75 meters. This
+ # value defaults to 1.0 meter.
+ chord=1.5, airfoil=ps.geometry.Airfoil(
+ # Give the airfoil a name. This defaults to "Untitled
+ # Airfoil". This name should correspond to a name in the
+ # airfoil directory or a NACA four series airfoil, unless you
+ # are passing in your own coordinates.
+ name="naca2412",
+ # If you wish to pass in coordinates, set this to an N x 2
+ # array of the airfoil's coordinates, where N is the number
+ # of coordinates. Treat this as an immutable, don't edit
+ # directly after initialization. If you wish to load
+ # coordinates from the airfoil directory, leave this as None.
+ # The default is None. Make sure that any airfoil coordinates
+ # used range in x from 0 to 1.
+ coordinates=None,
+ # This is the variable that determines whether you would like
+ # to repanel the airfoil coordinates. This applies to
+ # coordinates passed in by the user or to the directory
+ # coordinates. I highly recommended setting this to True. The
+ # default is True.
+ repanel=True,
+ # This is number of points to use if repaneling the airfoil.
+ # It is ignored if the repanel is False. The default is 400.
+ n_points_per_side=400, ), ),
+ # Define the next wing cross section. From here on out,
+ # the declarations will not be as commented as the previous. See the
+ # above comments if you have questions.
+ ps.geometry.WingCrossSection(x_le=1.5, y_le=6.0, z_le=0.5, chord=0.75,
+ control_surface_type="asymmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=10.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="Horizontal Stabilizer",
- x_le=6.75,
- z_le=0.25,
- symmetric=True,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ ps.geometry.Wing(name="Horizontal Stabilizer", x_le=6.75, z_le=0.25,
+ symmetric=True, wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- chord=1.0,
- twist=-5.0,
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, chord=1.0, twist=-5.0,
# Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="Vertical Stabilizer",
- x_le=6.75,
- z_le=0.5,
- symmetric=False,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
+ ps.geometry.Wing(name="Vertical Stabilizer", x_le=6.75, z_le=0.5,
+ symmetric=False, wing_cross_sections=[
+ ps.geometry.WingCrossSection(chord=1.5,
# Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- z_le=2.0,
- chord=1.0,
+ ps.geometry.WingCrossSection(x_le=0.5, z_le=2.0, chord=1.0,
# Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Define a new operating point object. This defines the state at which the airplane
# object is operating.
@@ -214,8 +149,7 @@
velocity=10.0,
# Define the angle of attack the airplane is experiencing. This defaults to 5.0
# degrees.
- alpha=1.0,
-)
+ alpha=1.0, )
# Define a new steady problem. A steady problem contains an airplane object and an
# operating point object.
@@ -223,8 +157,7 @@
# Set this steady problem's list of airplane objects to be the one we just created.
airplanes=[example_airplane],
# Set this steady problem's operating point object ot be the one we just created.
- operating_point=example_operating_point,
-)
+ operating_point=example_operating_point, )
# Now, the airplane and operating point object exist within the steady problem
# object. I like to delete the external pointers to these objects to ease debugging.
@@ -234,10 +167,10 @@
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.steady_ring_vortex_lattice_method.SteadyRingVortexLatticeMethodSolver(
+example_solver = (ps.steady_ring_vortex_lattice_method
+.SteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- steady_problem=example_problem
-)
+ steady_problem=example_problem))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver. Again, this is unnecessary, I just like to do this to ease debugging.
@@ -248,15 +181,13 @@
# This parameter determines the detail of information that the solver's logger
# will output while running. The options are, in order of detail and severity,
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
- logging_level="Warning",
-)
+ logging_level="Warning", )
# Call this function from the output module to print the results.
ps.output.print_steady_results(steady_solver=example_solver)
# Call the software's draw function on the solver.
-ps.output.draw(
- solver=example_solver,
+ps.output.draw(solver=example_solver,
# Tell the draw function to color the aircraft's wing panels with the local
# lift coefficient. The valid arguments for this parameter are None, "induced drag",
# "side force", or "lift".
@@ -269,8 +200,7 @@
show_wake_vortices=False,
# Tell the draw function to not save the drawing as an image file. This way,
# the drawing will still be displayed but not saved. This value defaults to false.
- save=False,
-)
+ save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/examples/unsteady_ring_vortex_lattice_method_solver_static.py b/examples/unsteady_ring_vortex_lattice_method_solver_static.py
index 322b968f..1133f73e 100644
--- a/examples/unsteady_ring_vortex_lattice_method_solver_static.py
+++ b/examples/unsteady_ring_vortex_lattice_method_solver_static.py
@@ -18,31 +18,22 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- # All airplane objects have a list of wings.
- wings=[
- # Create the first wing object in this airplane.
- ps.geometry.Wing(
- # Give the wing a name, this defaults to "Untitled Wing".
+ s_ref=None, b_ref=None, c_ref=None, # All airplane objects have a list of wings.
+ wings=[# Create the first wing object in this airplane.
+ ps.geometry.Wing(# Give the wing a name, this defaults to "Untitled Wing".
name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Declare that this wing is symmetric. This means that the geometry will
# be reflected across plane of this wing's root wing cross section. Note
# that the geometry coordinates are defined as such: If you were riding
@@ -58,20 +49,16 @@
# in the chordwise direction, near the leading and trailing edges. The
# other option is "uniform". I set this value to "uniform" here as it
# increase the accuracy of unsteady solvers.
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
+ num_chordwise_panels=6, chordwise_spacing="uniform",
# Every wing has a list of wing cross sections. In order for the geometry
# output to be sensible, each wing must have at least two wing cross
# sections.
- wing_cross_sections=[
- # Create a new wing cross section object.
+ wing_cross_sections=[# Create a new wing cross section object.
ps.geometry.WingCrossSection(
# Define the location of the leading edge of the wing cross
# section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Define the twist of the wing cross section in degrees. This is
# equivalent to incidence angle of cross section. The twist is
# about the leading edge. Note that the twist is only stable up
@@ -100,12 +87,10 @@
# which makes the panels relatively finer, in the spanwise
# direction, near the cross section ends. The other option is
# "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
+ num_spanwise_panels=8, spanwise_spacing="cosine",
# Set the chord of this cross section to be 1.75 meters. This
# value defaults to 1.0 meter.
- chord=1.75,
- # Every wing cross section has an airfoil object.
+ chord=1.75, # Every wing cross section has an airfoil object.
airfoil=ps.geometry.Airfoil(
# Give the airfoil a name. This defaults to "Untitled
# Airfoil". This name should correspond to a name in the
@@ -128,59 +113,24 @@
repanel=True,
# This is number of points to use if repaneling the airfoil.
# It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
+ n_points_per_side=400, ), ),
# Define the next wing cross section. From here on out,
# the declarations will not be as commented as the previous. See the
# above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- z_le=1.0,
- chord=1.5,
- twist=5.0,
- # Give this wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, z_le=1.0, chord=1.5,
+ twist=5.0, # Give this wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="V-Tail",
- x_le=6.75,
- z_le=0.25,
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
- symmetric=True,
+ ps.geometry.Wing(name="V-Tail", x_le=6.75, z_le=0.25, num_chordwise_panels=6,
+ chordwise_spacing="uniform", symmetric=True,
# Define this wing's root wing cross section.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- z_le=1.0,
- chord=1.0,
- twist=-5.0,
- # Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, z_le=1.0, chord=1.0,
+ twist=-5.0, # Give the tip wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the main wing's root wing cross section's movement. Cross sections can
# move in three ways: sweeping, pitching, and heaving. Sweeping is defined as the
@@ -220,39 +170,33 @@
heaving_period=0.0,
# Define the time step spacing of the heaving. This is "sine" by default. The
# options are "sine" and "uniform".
- heaving_spacing="sine",
-)
+ heaving_spacing="sine", )
# Define the main wing's tip wing cross section's movement. As the example has static
# geometry, the movement attributes can be excluded, and the default values will
# suffice.
main_wing_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1],
-)
+ base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1], )
# Define the v-tail's root wing cross section's movement. As the example has static
# geometry, the movement attributes can be excluded, and the default values will
# suffice.
v_tail_root_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0], )
# Define the v-tail's tip wing cross section's movement. As the example has static
# geometry, the movement attributes can be excluded, and the default values will
# suffice.
v_tail_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1], )
# Now define the main wing's movement. In addition to their wing cross sections'
# relative movements, wings' leading edge positions can move as well.
main_wing_movement = ps.movement.WingMovement( # Define the base wing object.
base_wing=example_airplane.wings[0],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- main_wing_root_wing_cross_section_movement,
- main_wing_tip_wing_cross_section_movement,
- ],
+ wing_cross_sections_movements=[main_wing_root_wing_cross_section_movement,
+ main_wing_tip_wing_cross_section_movement, ],
# Define the amplitude of the leading edge's change in x position. This value is
# in meters. This is set to 0.0 meters, which is the default value.
x_le_amplitude=0.0,
@@ -279,8 +223,7 @@
z_le_period=0.0,
# Define the time step spacing of the leading edge's change in z position. This
# is "sine" by default. The options are "sine" and "uniform".
- z_le_spacing="sine",
-)
+ z_le_spacing="sine", )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -289,15 +232,11 @@
del main_wing_tip_wing_cross_section_movement
# Make the v-tail's wing movement object.
-v_tail_movement = ps.movement.WingMovement(
- # Define the base wing object.
+v_tail_movement = ps.movement.WingMovement(# Define the base wing object.
base_wing=example_airplane.wings[1],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- v_tail_root_wing_cross_section_movement,
- v_tail_tip_wing_cross_section_movement,
- ],
-)
+ wing_cross_sections_movements=[v_tail_root_wing_cross_section_movement,
+ v_tail_tip_wing_cross_section_movement, ], )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -307,10 +246,8 @@
# Now define the airplane's movement object. In addition to their wing's and wing
# cross sections' relative movements, airplane's reference positions can move as well.
-airplane_movement = ps.movement.AirplaneMovement(
- # Define the base airplane object.
- base_airplane=example_airplane,
- # Add the list of wing movement objects.
+airplane_movement = ps.movement.AirplaneMovement(# Define the base airplane object.
+ base_airplane=example_airplane, # Add the list of wing movement objects.
wing_movements=[main_wing_movement, v_tail_movement],
# Define the amplitude of the reference position's change in x position. This
# value is in meters. This is set to 0.0 meters, which is the default value.
@@ -338,8 +275,7 @@
z_ref_period=0.0,
# Define the time step spacing of the reference position's change in z position.
# This is "sine" by default. The options are "sine" and "uniform".
- z_ref_spacing="sine",
-)
+ z_ref_spacing="sine", )
# Delete the extraneous wing movement objects, as these are now contained within the
# airplane movement object.
@@ -364,8 +300,7 @@
# Define the kinematic viscosity of the air in meters squared per second. This
# defaults to 15.06e-6 meters squared per second, which corresponds to an air
# temperature of 20 degrees Celsius.
- nu=15.06e-6,
-)
+ nu=15.06e-6, )
# Define the operating point's movement. The operating point's velocity can change
# with respect to time.
@@ -380,15 +315,12 @@
velocity_period=0.0,
# Define the time step spacing of the velocity's change in time. This is "sine"
# by default. The options are "sine" and "uniform".
- velocity_spacing="sine",
-)
+ velocity_spacing="sine", )
# Define the movement object. This contains the airplane movement and the operating
# point movement.
-movement = ps.movement.Movement(
- # Add the airplane movement.
- airplane_movements=[airplane_movement],
- # Add the operating point movement.
+movement = ps.movement.Movement(# Add the airplane movement.
+ airplane_movements=[airplane_movement], # Add the operating point movement.
operating_point_movement=operating_point_movement,
# Leave the number of time steps and the length of each time step unspecified.
# The solver will automatically set the length of the time steps so that the wake
@@ -397,9 +329,7 @@
# the number of steps will be set such that the wake extends ten chord lengths
# back from the main wing. If the geometry isn't static, the number of steps will
# be set such that three periods of the slowest movement oscillation complete.
- num_steps=None,
- delta_time=None,
-)
+ num_steps=None, delta_time=None, )
# Delete the extraneous airplane and operating point movement objects, as these are
# now contained within the movement object.
@@ -407,17 +337,15 @@
del operating_point_movement
# Define the unsteady example problem.
-example_problem = ps.problems.UnsteadyProblem(
- movement=movement,
-)
+example_problem = ps.problems.UnsteadyProblem(movement=movement, )
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
+example_solver = (ps.unsteady_ring_vortex_lattice_method
+.UnsteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- unsteady_problem=example_problem,
-)
+ unsteady_problem=example_problem, ))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver.
@@ -430,13 +358,11 @@
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
logging_level="Warning",
# Use a prescribed wake model. This is faster, but may be slightly less accurate.
- prescribed_wake=True,
-)
+ prescribed_wake=True, )
# Call the software's draw function on the solver. Press "q" to close the plotter
# after it draws the output.
-ps.output.draw(
- # Set the solver to the one we just ran.
+ps.output.draw(# Set the solver to the one we just ran.
solver=example_solver,
# Tell the draw function to color the aircraft's wing panels with the local lift
# coefficient. The valid arguments for this parameter are None, "induced drag",
@@ -450,14 +376,12 @@
show_wake_vortices=False,
# Tell the draw function to not save the drawing as an image file. This way,
# the drawing will still be displayed but not saved. This value defaults to False.
- save=False,
-)
+ save=False, )
# Call the software's animate function on the solver. This produces a GIF of the wake
# being shed. The GIF is saved in the same directory as this script. Press "q",
# after orienting the view, to begin the animation.
-ps.output.animate(
- # Set the unsteady solver to the one we just ran.
+ps.output.animate(# Set the unsteady solver to the one we just ran.
unsteady_solver=example_solver,
# Tell the animate function to color the aircraft's wing panels with the local
# lift coefficient. The valid arguments for this parameter are None, "induced drag",
@@ -469,22 +393,18 @@
# Tell the animate function to not save the animation as file. This way,
# the animation will still be displayed but not saved. This value defaults to
# False.
- save=False,
-)
+ save=False, )
# Call the software's plotting function on the solver. This produces graphs of the
# output forces and moments with respect to time.
-ps.output.plot_results_versus_time(
- # Set the unsteady solver to the one we just ran.
+ps.output.plot_results_versus_time(# Set the unsteady solver to the one we just ran.
unsteady_solver=example_solver,
# Set the show attribute to True, which is the default value. With this set to
# show, some IDEs (such as PyCharm in "Scientific Mode") will display the plots
# in a sidebar. Other IDEs may not display the plots, in which case you should
# set the save attribute to True, and open the files after they've been saved to
# the current directory.
- show=True,
- save=False,
-)
+ show=True, save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/examples/unsteady_ring_vortex_lattice_method_solver_variable.py b/examples/unsteady_ring_vortex_lattice_method_solver_variable.py
index 834f1073..f103ef46 100644
--- a/examples/unsteady_ring_vortex_lattice_method_solver_variable.py
+++ b/examples/unsteady_ring_vortex_lattice_method_solver_variable.py
@@ -18,30 +18,22 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- # All airplane objects have a list of wings.
- wings=[
- # Create the first wing object in this airplane.
+ s_ref=None, b_ref=None, c_ref=None, # All airplane objects have a list of wings.
+ wings=[# Create the first wing object in this airplane.
ps.geometry.Wing( # Give the wing a name, this defaults to "Untitled Wing".
name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Declare that this wing is symmetric. This means that the geometry will
# be reflected across plane of this wing's root wing cross section. Note
# that the geometry coordinates are defined as such: If you were riding
@@ -57,20 +49,16 @@
# in the chordwise direction, near the leading and trailing edges. The
# other option is "uniform". I set this value to "uniform" here as it
# increase the accuracy of unsteady solvers.
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
+ num_chordwise_panels=6, chordwise_spacing="uniform",
# Every wing has a list of wing cross sections. In order for the geometry
# output to be sensible, each wing must have at least two wing cross
# sections.
- wing_cross_sections=[
- # Create a new wing cross section object.
+ wing_cross_sections=[# Create a new wing cross section object.
ps.geometry.WingCrossSection(
# Define the location of the leading edge of the wing cross
# section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Define the twist of the wing cross section in degrees. This is
# equivalent to incidence angle of cross section. The twist is
# about the leading edge. Note that the twist is only stable up
@@ -99,12 +87,10 @@
# which makes the panels relatively finer, in the spanwise
# direction, near the cross section ends. The other option is
# "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
+ num_spanwise_panels=8, spanwise_spacing="cosine",
# Set the chord of this cross section to be 1.75 meters. This
# value defaults to 1.0 meter.
- chord=1.75,
- # Every wing cross section has an airfoil object.
+ chord=1.75, # Every wing cross section has an airfoil object.
airfoil=ps.geometry.Airfoil(
# Give the airfoil a name. This defaults to "Untitled
# Airfoil". This name should correspond to a name in the
@@ -127,59 +113,24 @@
repanel=True,
# This is number of points to use if repaneling the airfoil.
# It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
+ n_points_per_side=400, ), ),
# Define the next wing cross section. From here on out,
# the declarations will not be as commented as the previous. See the
# above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- z_le=1.0,
- chord=1.5,
- twist=5.0,
- # Give this wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, z_le=1.0, chord=1.5,
+ twist=5.0, # Give this wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="V-Tail",
- x_le=6.75,
- z_le=0.25,
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
- symmetric=True,
+ ps.geometry.Wing(name="V-Tail", x_le=6.75, z_le=0.25, num_chordwise_panels=6,
+ chordwise_spacing="uniform", symmetric=True,
# Define this wing's root wing cross section.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- z_le=1.0,
- chord=1.0,
- twist=-5.0,
- # Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, z_le=1.0, chord=1.0,
+ twist=-5.0, # Give the tip wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the main wing's root wing cross section's movement. Cross sections can
# move in three ways: sweeping, pitching, and heaving. Sweeping is defined as the
@@ -219,44 +170,32 @@
heaving_period=0.0,
# Define the time step spacing of the heaving. This is "sine" by default. The
# options are "sine" and "uniform".
- heaving_spacing="sine",
-)
+ heaving_spacing="sine", )
# Define the main wing's tip wing cross section's movement.
main_wing_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1],
- sweeping_amplitude=30.0,
- sweeping_period=1.0,
- sweeping_spacing="sine",
- pitching_amplitude=15.0,
- pitching_period=1.0,
- pitching_spacing="sine",
- heaving_amplitude=0.0,
- heaving_period=0.0,
- heaving_spacing="sine",
-)
+ sweeping_amplitude=30.0, sweeping_period=1.0, sweeping_spacing="sine",
+ pitching_amplitude=15.0, pitching_period=1.0, pitching_spacing="sine",
+ heaving_amplitude=0.0, heaving_period=0.0, heaving_spacing="sine", )
# Define the v-tail's root wing cross section's movement. This wing will be static,
# so the movement attributes can be excluded, and the default values will suffice.
v_tail_root_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0], )
# Define the v-tail's root wing cross section's movement. This wing will be static,
# so the movement attributes can be excluded, and the default values will suffice.
v_tail_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1], )
# Now define the main wing's movement. In addition to their wing cross sections'
# relative movements, wings' leading edge positions can move as well.
main_wing_movement = ps.movement.WingMovement( # Define the base wing object.
base_wing=example_airplane.wings[0],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- main_wing_root_wing_cross_section_movement,
- main_wing_tip_wing_cross_section_movement,
- ],
+ wing_cross_sections_movements=[main_wing_root_wing_cross_section_movement,
+ main_wing_tip_wing_cross_section_movement, ],
# Define the amplitude of the leading edge's change in x position. This value is
# in meters. This is set to 0.0 meters, which is the default value.
x_le_amplitude=0.0,
@@ -283,8 +222,7 @@
z_le_period=0.0,
# Define the time step spacing of the leading edge's change in z position. This
# is "sine" by default. The options are "sine" and "uniform".
- z_le_spacing="sine",
-)
+ z_le_spacing="sine", )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -293,15 +231,11 @@
del main_wing_tip_wing_cross_section_movement
# Make the v-tail's wing movement object.
-v_tail_movement = ps.movement.WingMovement(
- # Define the base wing object.
+v_tail_movement = ps.movement.WingMovement(# Define the base wing object.
base_wing=example_airplane.wings[1],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- v_tail_root_wing_cross_section_movement,
- v_tail_tip_wing_cross_section_movement,
- ],
-)
+ wing_cross_sections_movements=[v_tail_root_wing_cross_section_movement,
+ v_tail_tip_wing_cross_section_movement, ], )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -311,10 +245,8 @@
# Now define the airplane's movement object. In addition to their wing's and wing
# cross sections' relative movements, airplane's reference positions can move as well.
-airplane_movement = ps.movement.AirplaneMovement(
- # Define the base airplane object.
- base_airplane=example_airplane,
- # Add the list of wing movement objects.
+airplane_movement = ps.movement.AirplaneMovement(# Define the base airplane object.
+ base_airplane=example_airplane, # Add the list of wing movement objects.
wing_movements=[main_wing_movement, v_tail_movement],
# Define the amplitude of the reference position's change in x position. This
# value is in meters. This is set to 0.0 meters, which is the default value.
@@ -342,8 +274,7 @@
z_ref_period=0.0,
# Define the time step spacing of the reference position's change in z position.
# This is "sine" by default. The options are "sine" and "uniform".
- z_ref_spacing="sine",
-)
+ z_ref_spacing="sine", )
# Delete the extraneous wing movement objects, as these are now contained within the
# airplane movement object.
@@ -368,8 +299,7 @@
# Define the kinematic viscosity of the air in meters squared per second. This
# defaults to 15.06e-6 meters squared per second, which corresponds to an air
# temperature of 20 degrees Celsius.
- nu=15.06e-6,
-)
+ nu=15.06e-6, )
# Define the operating point's movement. The operating point's velocity can change
# with respect to time.
@@ -384,15 +314,12 @@
velocity_period=0.0,
# Define the time step spacing of the velocity's change in time. This is "sine"
# by default. The options are "sine" and "uniform".
- velocity_spacing="sine",
-)
+ velocity_spacing="sine", )
# Define the movement object. This contains the airplane movement and the operating
# point movement.
-movement = ps.movement.Movement(
- # Add the airplane movement.
- airplane_movements=[airplane_movement],
- # Add the operating point movement.
+movement = ps.movement.Movement(# Add the airplane movement.
+ airplane_movements=[airplane_movement], # Add the operating point movement.
operating_point_movement=operating_point_movement,
# Leave the number of time steps and the length of each time step unspecified.
# The solver will automatically set the length of the time steps so that the wake
@@ -401,9 +328,7 @@
# the number of steps will be set such that the wake extends ten chord lengths
# back from the main wing. If the geometry isn't static, the number of steps will
# be set such that three periods of the slowest movement oscillation complete.
- num_steps=None,
- delta_time=None,
-)
+ num_steps=None, delta_time=None, )
# Delete the extraneous airplane and operating point movement objects, as these are
# now contained within the movement object.
@@ -411,17 +336,15 @@
del operating_point_movement
# Define the unsteady example problem.
-example_problem = ps.problems.UnsteadyProblem(
- movement=movement,
-)
+example_problem = ps.problems.UnsteadyProblem(movement=movement, )
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
+example_solver = (ps.unsteady_ring_vortex_lattice_method
+.UnsteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- unsteady_problem=example_problem,
-)
+ unsteady_problem=example_problem, ))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver.
@@ -434,14 +357,12 @@
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
logging_level="Warning",
# Use a prescribed wake model. This is faster, but may be slightly less accurate.
- prescribed_wake=True,
-)
+ prescribed_wake=True, )
# Call the software's animate function on the solver. This produces a GIF of the wake
# being shed. The GIF is saved in the same directory as this script. Press "q",
# after orienting the view, to begin the animation.
-ps.output.animate(
- # Set the unsteady solver to the one we just ran.
+ps.output.animate(# Set the unsteady solver to the one we just ran.
unsteady_solver=example_solver,
# Tell the animate function to color the aircraft's wing panels with the local
# lift coefficient. The valid arguments for this parameter are None, "induced drag",
@@ -453,8 +374,7 @@
# Tell the animate function to not save the animation as file. This way,
# the animation will still be displayed but not saved. This value defaults to
# False.
- save=False,
-)
+ save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/examples/unsteady_ring_vortex_lattice_method_solver_variable_formation.py b/examples/unsteady_ring_vortex_lattice_method_solver_variable_formation.py
index d4d94560..01ec8f12 100644
--- a/examples/unsteady_ring_vortex_lattice_method_solver_variable_formation.py
+++ b/examples/unsteady_ring_vortex_lattice_method_solver_variable_formation.py
@@ -10,250 +10,127 @@
y_spacing = 13
# Create the lead airplane object.
-lead_airplane = ps.geometry.Airplane(
- name="Lead Airplane",
+lead_airplane = ps.geometry.Airplane(name="Lead Airplane",
# Specify the location of the lead airplane's center of gravity. This is the
# point around about which the solver will calculate the moments on the airplane.
# These three values default to 0.0 meters. Note: these values are relative to
# the global coordinate system fixed front left corner of the first airplane's
# first wing's root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- # Define the location of the leading edge of the wing relative to the
- # global coordinate system fixed front left corner of the first
- # airplane's first wing's root wing cross section.
- x_le=0.0,
- y_le=0.0,
- # Declare that this wing is symmetric. This means that the geometry will
- # be reflected across plane of this wing's root wing cross section. Note
- # that the geometry coordinates are defined as such: If you were riding
- # in the airplane, the positive x direction would point behind you,
- # the positive y direction would point out of your right wing, and the
- # positive z direction would point upwards, out of your chair. These
- # directions form a right-handed coordinate system. The default value of
- # "symmetric" is false.
- symmetric=True,
- # Define the chordwise spacing of the wing panels to be "uniform" as this
- # increase the accuracy of unsteady solvers.
- chordwise_spacing="uniform",
- num_chordwise_panels=4,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- # Define the location of the leading edge of the wing cross
- # section relative to the wing's leading edge. These values all
- # default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- # Assign the twist of this wing cross section. Note: when
- # assigning angles of attack to multiple airplanes, it is better
- # to set the operating point's angle of attack to zero, and then
- # use offset the twist values of all the wing cross sections to
- # simulate each aircraft having an angle of attack.
- twist=5.0,
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ x_ref=0.0, y_ref=0.0, z_ref=0.0, wings=[ps.geometry.Wing(name="Main Wing",
+ # Define the location of the leading edge of the wing relative to the
+ # global coordinate system fixed front left corner of the first
+ # airplane's first wing's root wing cross section.
+ x_le=0.0, y_le=0.0,
+ # Declare that this wing is symmetric. This means that the geometry will
+ # be reflected across plane of this wing's root wing cross section. Note
+ # that the geometry coordinates are defined as such: If you were riding
+ # in the airplane, the positive x direction would point behind you,
+ # the positive y direction would point out of your right wing, and the
+ # positive z direction would point upwards, out of your chair. These
+ # directions form a right-handed coordinate system. The default value of
+ # "symmetric" is false.
+ symmetric=True,
+ # Define the chordwise spacing of the wing panels to be "uniform" as this
+ # increase the accuracy of unsteady solvers.
+ chordwise_spacing="uniform", num_chordwise_panels=4, wing_cross_sections=[
+ ps.geometry.WingCrossSection(
+ # Define the location of the leading edge of the wing cross
+ # section relative to the wing's leading edge. These values all
+ # default to 0.0 meters.
+ x_le=0.0, y_le=0.0,
+ # Assign the twist of this wing cross section. Note: when
+ # assigning angles of attack to multiple airplanes, it is better
+ # to set the operating point's angle of attack to zero, and then
+ # use offset the twist values of all the wing cross sections to
+ # simulate each aircraft having an angle of attack.
+ twist=5.0, chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, chord=1.5, twist=5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the lead airplane's movement object.
-lead_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=lead_airplane,
- wing_movements=[
- # Define the main wing's movement.
- ps.movement.WingMovement(
- base_wing=lead_airplane.wings[0],
+lead_airplane_movement = ps.movement.AirplaneMovement(base_airplane=lead_airplane,
+ wing_movements=[# Define the main wing's movement.
+ ps.movement.WingMovement(base_wing=lead_airplane.wings[0],
# Add the list of wing cross section movement objects.
wing_cross_sections_movements=[
# Define the root wing cross section's movement object.
ps.movement.WingCrossSectionMovement(
base_wing_cross_section=lead_airplane.wings[0].wing_cross_sections[
- 0
- ],
- ),
- # Define the tip wing cross section's movement object.
+ 0], ), # Define the tip wing cross section's movement object.
ps.movement.WingCrossSectionMovement(
base_wing_cross_section=lead_airplane.wings[0].wing_cross_sections[
- 1
- ],
- sweeping_amplitude=15.0,
- sweeping_period=1.5,
- sweeping_spacing="sine",
- ),
- ],
- ),
- ],
-)
+ 1], sweeping_amplitude=15.0, sweeping_period=1.5,
+ sweeping_spacing="sine", ), ], ), ], )
# Create the trailing right airplane object.
-right_airplane = ps.geometry.Airplane(
- name="Right Airplane",
+right_airplane = ps.geometry.Airplane(name="Right Airplane",
# Specify the location of the right airplane's center of gravity. This is the
# point around about which the solver will calculate the moments on the airplane.
# These three values default to 0.0 meters. Note: these values are relative to
# the global coordinate system fixed front left corner of the first airplane's
# first wing's root wing cross section.
- x_ref=x_spacing,
- y_ref=y_spacing,
- z_ref=0.0,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
+ x_ref=x_spacing, y_ref=y_spacing, z_ref=0.0, wings=[
+ ps.geometry.Wing(name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section.
- x_le=x_spacing,
- y_le=y_spacing,
- symmetric=True,
- chordwise_spacing="uniform",
- num_chordwise_panels=4,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- twist=5.0,
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ x_le=x_spacing, y_le=y_spacing, symmetric=True, chordwise_spacing="uniform",
+ num_chordwise_panels=4, wing_cross_sections=[
+ ps.geometry.WingCrossSection(twist=5.0, chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, chord=1.5, twist=5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the trailing right airplane's movement object.
-right_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=right_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=right_airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=right_airplane.wings[0].wing_cross_sections[
- 0
- ],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=right_airplane.wings[0].wing_cross_sections[
- 1
- ],
- sweeping_amplitude=15.0,
- sweeping_period=1.5,
- sweeping_spacing="sine",
- ),
- ],
- ),
- ],
-)
+right_airplane_movement = ps.movement.AirplaneMovement(base_airplane=right_airplane,
+ wing_movements=[ps.movement.WingMovement(base_wing=right_airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=right_airplane.wings[0].wing_cross_sections[0], ),
+ ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=right_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=15.0, sweeping_period=1.5,
+ sweeping_spacing="sine", ), ], ), ], )
# Create the trailing left airplane object.
-left_airplane = ps.geometry.Airplane(
- name="Left Airplane",
+left_airplane = ps.geometry.Airplane(name="Left Airplane",
# Specify the location of the left airplane's center of gravity. This is the
# point around about which the solver will calculate the moments on the airplane.
# These three values default to 0.0 meters. Note: these values are relative to
# the global coordinate system fixed front left corner of the first airplane's
# first wing's root wing cross section.
- x_ref=x_spacing,
- y_ref=-y_spacing,
- z_ref=0.0,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
+ x_ref=x_spacing, y_ref=-y_spacing, z_ref=0.0, wings=[
+ ps.geometry.Wing(name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section.
- x_le=x_spacing,
- y_le=-y_spacing,
- symmetric=True,
- chordwise_spacing="uniform",
- num_chordwise_panels=4,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- twist=5.0,
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ x_le=x_spacing, y_le=-y_spacing, symmetric=True,
+ chordwise_spacing="uniform", num_chordwise_panels=4, wing_cross_sections=[
+ ps.geometry.WingCrossSection(twist=5.0, chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, chord=1.5, twist=5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the trailing left airplane's movement object.
-left_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=left_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=left_airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=left_airplane.wings[0].wing_cross_sections[
- 0
- ],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=left_airplane.wings[0].wing_cross_sections[
- 1
- ],
- sweeping_amplitude=15.0,
- sweeping_period=1.5,
- sweeping_spacing="sine",
- ),
- ],
- ),
- ],
-)
+left_airplane_movement = ps.movement.AirplaneMovement(base_airplane=left_airplane,
+ wing_movements=[ps.movement.WingMovement(base_wing=left_airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=left_airplane.wings[0].wing_cross_sections[0], ),
+ ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=left_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=15.0, sweeping_period=1.5,
+ sweeping_spacing="sine", ), ], ), ], )
# Define a new operating point object. This defines the state at which all the
# airplanes objects are operating. Note: when assigning angles of attack to multiple
# airplanes, it is better to set the operating point's angle of attack to zero,
# and then use offset the twist values of all the wing cross sections to simulate
# each aircraft having an angle of attack.
-operating_point = ps.operating_point.OperatingPoint(
- velocity=10.0,
- alpha=0.0,
-)
+operating_point = ps.operating_point.OperatingPoint(velocity=10.0, alpha=0.0, )
# Define the operating point's movement.
operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=operating_point,
-)
+ base_operating_point=operating_point, )
# Delete the extraneous airplane and operating point objects, as these are now
# contained within their respective movement objects.
@@ -265,14 +142,9 @@
# Define the movement object. This contains each airplane's movement and the operating
# point movement.
movement = ps.movement.Movement(
- airplane_movements=[
- lead_airplane_movement,
- right_airplane_movement,
- left_airplane_movement,
- ],
- operating_point_movement=operating_point_movement,
- num_cycles=2,
-)
+ airplane_movements=[lead_airplane_movement, right_airplane_movement,
+ left_airplane_movement, ], operating_point_movement=operating_point_movement,
+ num_cycles=2, )
# Delete the extraneous airplane and operating point movement objects, as these are
# now contained within the movement object.
@@ -282,39 +154,30 @@
del operating_point_movement
# Define the unsteady example problem.
-problem = ps.problems.UnsteadyProblem(
- movement=movement,
-)
+problem = ps.problems.UnsteadyProblem(movement=movement, )
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- unsteady_problem=problem,
-)
+ unsteady_problem=problem, )
# Delete the extraneous pointer to the problem as it is now contained within the
# solver.
del problem
# Run the example solver.
-solver.run(
- prescribed_wake=False,
-)
+solver.run(prescribed_wake=False, )
# Call the software's animate function on the solver. This produces a WebP animation
# of the wake being shed. The animation is saved in the same directory as this
# script. Press "q", after orienting the view, to begin the animation.
-ps.output.animate(
- unsteady_solver=solver,
- scalar_type="lift",
- show_wake_vortices=True,
+ps.output.animate(unsteady_solver=solver, scalar_type="lift", show_wake_vortices=True,
# Tell the animate function to not save the animation as file. This way,
# the animation will still be displayed but not saved. This value defaults to
# false.
- save=True,
-)
+ save=True, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/examples/unsteady_static_convergence_example.py b/examples/unsteady_static_convergence_example.py
index 0524e291..1c1a9a6f 100644
--- a/examples/unsteady_static_convergence_example.py
+++ b/examples/unsteady_static_convergence_example.py
@@ -6,64 +6,30 @@
# Create an airplane and airplane movement object. Read through the unsteady solver
# examples for more details on creating this object.
-airplane = ps.geometry.Airplane(
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- spanwise_spacing="uniform",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=3.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ],
-)
-airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=airplane.wings[0].wing_cross_sections[0],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=airplane.wings[0].wing_cross_sections[1],
- ),
- ],
- )
- ],
-)
+airplane = ps.geometry.Airplane(wings=[
+ ps.geometry.Wing(symmetric=True, chordwise_spacing="uniform", wing_cross_sections=[
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=0.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ),
+ spanwise_spacing="uniform", ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=3.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ), ], )
+airplane_movement = ps.movement.AirplaneMovement(base_airplane=airplane,
+ wing_movements=[ps.movement.WingMovement(base_wing=airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=airplane.wings[0].wing_cross_sections[0], ),
+ ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=airplane.wings[0].wing_cross_sections[
+ 1], ), ], )], )
# Create an operating point and an operating point movement object.
operating_point = ps.operating_point.OperatingPoint()
operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=operating_point
-)
+ base_operating_point=operating_point)
# Create a movement object from the airplane movement and operating point movement
# objects.
-movement = ps.movement.Movement(
- airplane_movements=[airplane_movement],
- operating_point_movement=operating_point_movement,
-)
+movement = ps.movement.Movement(airplane_movements=[airplane_movement],
+ operating_point_movement=operating_point_movement, )
del airplane_movement
del operating_point_movement
@@ -80,15 +46,9 @@
# absolute percent error), it will return the parameters it found to result in a
# converged solution. See the analyze_unsteady_convergence function docstring for
# more details. The progress and results are displayed to the console.
-ps.convergence.analyze_unsteady_convergence(
- ref_problem=problem,
- prescribed_wake=True,
- free_wake=True,
- num_chords_bounds=(5, 8),
- panel_aspect_ratio_bounds=(2, 1),
- num_chordwise_panels_bounds=(3, 6),
- convergence_criteria=1.0,
-)
+ps.convergence.analyze_unsteady_convergence(ref_problem=problem, prescribed_wake=True,
+ free_wake=True, num_chords_bounds=(5, 8), panel_aspect_ratio_bounds=(2, 1),
+ num_chordwise_panels_bounds=(3, 6), convergence_criteria=1.0, )
# Check the console that the convergence analysis found that the solution converged
# with the following parameters:
diff --git a/examples/unsteady_variable_convergence_example.py b/examples/unsteady_variable_convergence_example.py
index 1b0ba048..7f51e7fa 100644
--- a/examples/unsteady_variable_convergence_example.py
+++ b/examples/unsteady_variable_convergence_example.py
@@ -6,66 +6,30 @@
# Create an airplane and airplane movement object. Read through the unsteady solver
# examples for more details on creating this object.
-airplane = ps.geometry.Airplane(
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- spanwise_spacing="uniform",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=3.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ],
-)
-airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=airplane.wings[0].wing_cross_sections[0],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=airplane.wings[0].wing_cross_sections[1],
- sweeping_amplitude=15.0,
- sweeping_period=1.0,
- ),
- ],
- )
- ],
-)
+airplane = ps.geometry.Airplane(wings=[
+ ps.geometry.Wing(symmetric=True, chordwise_spacing="uniform", wing_cross_sections=[
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=0.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ),
+ spanwise_spacing="uniform", ),
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=3.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ), ], )
+airplane_movement = ps.movement.AirplaneMovement(base_airplane=airplane,
+ wing_movements=[ps.movement.WingMovement(base_wing=airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=airplane.wings[0].wing_cross_sections[0], ),
+ ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=15.0, sweeping_period=1.0, ), ], )], )
# Create an operating point and an operating point movement object.
operating_point = ps.operating_point.OperatingPoint()
operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=operating_point
-)
+ base_operating_point=operating_point)
# Create a movement object from the airplane movement and operating point movement
# objects.
-movement = ps.movement.Movement(
- airplane_movements=[airplane_movement],
- operating_point_movement=operating_point_movement,
-)
+movement = ps.movement.Movement(airplane_movements=[airplane_movement],
+ operating_point_movement=operating_point_movement, )
del airplane_movement
del operating_point_movement
@@ -82,15 +46,9 @@
# absolute percent error), it will return the parameters it found to result in a
# converged solution. See the analyze_unsteady_convergence function docstring for
# more details. The progress and results are displayed to the console.
-ps.convergence.analyze_unsteady_convergence(
- ref_problem=problem,
- prescribed_wake=True,
- free_wake=True,
- num_cycles_bounds=(1, 4),
- panel_aspect_ratio_bounds=(2, 1),
- num_chordwise_panels_bounds=(4, 7),
- convergence_criteria=1.0,
-)
+ps.convergence.analyze_unsteady_convergence(ref_problem=problem, prescribed_wake=True,
+ free_wake=True, num_cycles_bounds=(1, 4), panel_aspect_ratio_bounds=(2, 1),
+ num_chordwise_panels_bounds=(4, 7), convergence_criteria=1.0, )
# Check the console that the convergence analysis found that the solution converged
# with the following parameters:
diff --git a/formation flight/formation_flight.py b/formation flight/formation_flight.py
index efa7a205..c5cb6ee4 100644
--- a/formation flight/formation_flight.py
+++ b/formation flight/formation_flight.py
@@ -28,13 +28,9 @@
root_to_mid_chord = root_chord
mid_to_tip_chord = (root_chord + tip_chord) / 2
-this_operating_point = ps.operating_point.OperatingPoint(
- velocity=speed,
- alpha=0.0,
-)
+this_operating_point = ps.operating_point.OperatingPoint(velocity=speed, alpha=0.0, )
this_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=this_operating_point,
-)
+ base_operating_point=this_operating_point, )
del this_operating_point
print("Prescribed Wake:", prescribed_wake)
@@ -45,8 +41,7 @@
mid_to_tip_panel_chord = mid_to_tip_chord / num_chord
root_to_mid_num_span = round(
- root_to_mid_span / (aspect_ratio * root_to_mid_panel_chord)
-)
+ root_to_mid_span / (aspect_ratio * root_to_mid_panel_chord))
mid_to_tip_num_span = round(mid_to_tip_span / (aspect_ratio * mid_to_tip_panel_chord))
these_airplane_movements = []
@@ -70,126 +65,66 @@
offset = row - 1
- this_airplane = ps.geometry.Airplane(
- name=this_name,
- x_ref=offset * x_spacing,
- y_ref=offset_sign * offset * y_spacing,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- symmetric=True,
- chordwise_spacing="uniform",
- x_le=offset * x_spacing,
- y_le=offset_sign * offset * y_spacing,
- num_chordwise_panels=num_chord,
+ this_airplane = ps.geometry.Airplane(name=this_name, x_ref=offset * x_spacing,
+ y_ref=offset_sign * offset * y_spacing, wings=[
+ ps.geometry.Wing(name="Main Wing", symmetric=True,
+ chordwise_spacing="uniform", x_le=offset * x_spacing,
+ y_le=offset_sign * offset * y_spacing, num_chordwise_panels=num_chord,
wing_cross_sections=[
- ps.geometry.WingCrossSection(
- twist=alpha,
- chord=root_chord,
+ ps.geometry.WingCrossSection(twist=alpha, chord=root_chord,
airfoil=ps.geometry.Airfoil(name="naca0012"),
num_spanwise_panels=root_to_mid_num_span,
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- twist=alpha,
- y_le=root_to_mid_span,
- chord=root_chord,
- airfoil=ps.geometry.Airfoil(name="naca0012"),
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(twist=alpha, y_le=root_to_mid_span,
+ chord=root_chord, airfoil=ps.geometry.Airfoil(name="naca0012"),
num_spanwise_panels=mid_to_tip_num_span,
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- twist=alpha,
- y_le=root_to_mid_span + mid_to_tip_span,
- chord=tip_chord,
- airfoil=ps.geometry.Airfoil(name="naca0012"),
- ),
- ],
- ),
- ],
- )
-
- this_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=this_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=this_airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=this_airplane.wings[
- 0
- ].wing_cross_sections[0],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=this_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_amplitude=flapping_amplitude,
- sweeping_period=period,
- sweeping_spacing="sine",
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=this_airplane.wings[
- 0
- ].wing_cross_sections[2],
- sweeping_amplitude=flapping_amplitude,
- sweeping_period=period,
- sweeping_spacing="sine",
- ),
- ],
- )
- ],
- )
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(twist=alpha,
+ y_le=root_to_mid_span + mid_to_tip_span, chord=tip_chord,
+ airfoil=ps.geometry.Airfoil(name="naca0012"), ), ], ), ], )
+
+ this_airplane_movement = ps.movement.AirplaneMovement(base_airplane=this_airplane,
+ wing_movements=[ps.movement.WingMovement(base_wing=this_airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=this_airplane.wings[0].wing_cross_sections[
+ 0], ), ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=this_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=flapping_amplitude, sweeping_period=period,
+ sweeping_spacing="sine", ), ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=this_airplane.wings[0].wing_cross_sections[2],
+ sweeping_amplitude=flapping_amplitude, sweeping_period=period,
+ sweeping_spacing="sine", ), ], )], )
these_airplane_movements.append(this_airplane_movement)
del this_airplane
del this_airplane_movement
-this_movement = ps.movement.Movement(
- airplane_movements=these_airplane_movements,
- operating_point_movement=this_operating_point_movement,
- num_steps=None,
- num_cycles=num_flaps,
- delta_time=None,
-)
+this_movement = ps.movement.Movement(airplane_movements=these_airplane_movements,
+ operating_point_movement=this_operating_point_movement, num_steps=None,
+ num_cycles=num_flaps, delta_time=None, )
del these_airplane_movements
-this_problem = ps.problems.UnsteadyProblem(
- movement=this_movement,
- only_final_results=False,
-)
+this_problem = ps.problems.UnsteadyProblem(movement=this_movement,
+ only_final_results=False, )
del this_movement
this_solver = (
ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
- unsteady_problem=this_problem,
- )
-)
+ unsteady_problem=this_problem, ))
del this_problem
-this_solver.run(
- prescribed_wake=prescribed_wake,
- calculate_streamlines=False,
-)
+this_solver.run(prescribed_wake=prescribed_wake, calculate_streamlines=False, )
ps.output.print_unsteady_results(unsteady_solver=this_solver)
ps.output.plot_results_versus_time(unsteady_solver=this_solver, save=True)
-ps.output.draw(
- solver=this_solver,
- scalar_type="lift",
- show_wake_vortices=True,
- save=True,
-)
-
-ps.output.animate(
- unsteady_solver=this_solver,
- scalar_type="lift",
- show_wake_vortices=True,
- save=True,
-)
+ps.output.draw(solver=this_solver, scalar_type="lift", show_wake_vortices=True,
+ save=True, )
+
+ps.output.animate(unsteady_solver=this_solver, scalar_type="lift",
+ show_wake_vortices=True, save=True, )
diff --git a/formation flight/formation_flight_convergence.py b/formation flight/formation_flight_convergence.py
index c22a93ef..7693ef4d 100644
--- a/formation flight/formation_flight_convergence.py
+++ b/formation flight/formation_flight_convergence.py
@@ -43,11 +43,9 @@
num_chord_list = [i for i in range(min_num_chord, max_num_chord + 1)]
rms_lifts = np.zeros(
- (len(wake_state_list), len(num_flaps_list), len(num_chord_list), num_airplanes)
-)
+ (len(wake_state_list), len(num_flaps_list), len(num_chord_list), num_airplanes))
rms_drags = np.zeros(
- (len(wake_state_list), len(num_flaps_list), len(num_chord_list), num_airplanes)
-)
+ (len(wake_state_list), len(num_flaps_list), len(num_chord_list), num_airplanes))
iter_times = np.zeros((len(wake_state_list), len(num_flaps_list), len(num_chord_list)))
iteration = 0
@@ -67,13 +65,9 @@
wake_saturated = None
this_solver = None
-this_operating_point = ps.operating_point.OperatingPoint(
- velocity=speed,
- alpha=0.0,
-)
+this_operating_point = ps.operating_point.OperatingPoint(velocity=speed, alpha=0.0, )
this_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=this_operating_point,
-)
+ base_operating_point=this_operating_point, )
del this_operating_point
for wake_state_id, prescribed_wake in enumerate(wake_state_list):
@@ -90,11 +84,9 @@
mid_to_tip_panel_chord = mid_to_tip_chord / num_chord
root_to_mid_num_span = round(
- root_to_mid_span / (aspect_ratio * root_to_mid_panel_chord)
- )
+ root_to_mid_span / (aspect_ratio * root_to_mid_panel_chord))
mid_to_tip_num_span = round(
- mid_to_tip_span / (aspect_ratio * mid_to_tip_panel_chord)
- )
+ mid_to_tip_span / (aspect_ratio * mid_to_tip_panel_chord))
these_airplane_movements = []
row = None
@@ -117,76 +109,44 @@
offset = row - 1
- this_airplane = ps.geometry.Airplane(
- name=this_name,
- x_ref=offset * x_spacing,
- y_ref=offset_sign * offset * y_spacing,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- symmetric=True,
- chordwise_spacing="uniform",
- x_le=offset * x_spacing,
- y_le=offset_sign * offset * y_spacing,
- num_chordwise_panels=num_chord,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- twist=alpha,
- chord=root_chord,
- airfoil=ps.geometry.Airfoil(name="naca0012"),
- num_spanwise_panels=root_to_mid_num_span,
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- twist=alpha,
- y_le=root_to_mid_span,
- chord=root_chord,
- airfoil=ps.geometry.Airfoil(name="naca0012"),
- num_spanwise_panels=mid_to_tip_num_span,
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- twist=alpha,
- y_le=root_to_mid_span + mid_to_tip_span,
- chord=tip_chord,
- airfoil=ps.geometry.Airfoil(name="naca0012"),
- ),
- ],
- ),
- ],
- )
+ this_airplane = ps.geometry.Airplane(name=this_name,
+ x_ref=offset * x_spacing, y_ref=offset_sign * offset * y_spacing,
+ wings=[ps.geometry.Wing(name="Main Wing", symmetric=True,
+ chordwise_spacing="uniform", x_le=offset * x_spacing,
+ y_le=offset_sign * offset * y_spacing,
+ num_chordwise_panels=num_chord, wing_cross_sections=[
+ ps.geometry.WingCrossSection(twist=alpha, chord=root_chord,
+ airfoil=ps.geometry.Airfoil(name="naca0012"),
+ num_spanwise_panels=root_to_mid_num_span,
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(twist=alpha,
+ y_le=root_to_mid_span, chord=root_chord,
+ airfoil=ps.geometry.Airfoil(name="naca0012"),
+ num_spanwise_panels=mid_to_tip_num_span,
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(twist=alpha,
+ y_le=root_to_mid_span + mid_to_tip_span,
+ chord=tip_chord, airfoil=ps.geometry.Airfoil(
+ name="naca0012"), ), ], ), ], )
this_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=this_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=this_airplane.wings[0],
+ base_airplane=this_airplane, wing_movements=[
+ ps.movement.WingMovement(base_wing=this_airplane.wings[0],
wing_cross_sections_movements=[
ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=this_airplane.wings[
- 0
- ].wing_cross_sections[0],
- ),
+ base_wing_cross_section=
+ this_airplane.wings[0].wing_cross_sections[0], ),
ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=this_airplane.wings[
- 0
- ].wing_cross_sections[1],
+ base_wing_cross_section=
+ this_airplane.wings[0].wing_cross_sections[1],
sweeping_amplitude=flapping_amplitude,
- sweeping_period=period,
- sweeping_spacing="sine",
- ),
+ sweeping_period=period, sweeping_spacing="sine", ),
ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=this_airplane.wings[
- 0
- ].wing_cross_sections[2],
+ base_wing_cross_section=
+ this_airplane.wings[0].wing_cross_sections[2],
sweeping_amplitude=flapping_amplitude,
sweeping_period=period,
- sweeping_spacing="sine",
- ),
- ],
- )
- ],
- )
+ sweeping_spacing="sine", ), ], )], )
these_airplane_movements.append(this_airplane_movement)
@@ -195,34 +155,26 @@
this_movement = ps.movement.Movement(
airplane_movements=these_airplane_movements,
- operating_point_movement=this_operating_point_movement,
- num_steps=None,
- num_cycles=num_flaps,
- delta_time=None,
- )
+ operating_point_movement=this_operating_point_movement, num_steps=None,
+ num_cycles=num_flaps, delta_time=None, )
del these_airplane_movements
- this_problem = ps.problems.UnsteadyProblem(
- movement=this_movement,
- only_final_results=True,
- )
+ this_problem = ps.problems.UnsteadyProblem(movement=this_movement,
+ only_final_results=True, )
del this_movement
- this_solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
- unsteady_problem=this_problem,
- )
+ this_solver = (
+ ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
+ unsteady_problem=this_problem, ))
del this_problem
iter_start = time.time()
- this_solver.run(
- logging_level="Critical",
- prescribed_wake=prescribed_wake,
- calculate_streamlines=False,
- )
+ this_solver.run(logging_level="Critical", prescribed_wake=prescribed_wake,
+ calculate_streamlines=False, )
iter_stop = time.time()
iter_time = round((iter_stop - iter_start), 2)
@@ -241,11 +193,9 @@
airplanes = this_solver.steady_problems[step].airplanes
for airplane_id, airplane in enumerate(airplanes):
total_forces[airplane_id, :, results_step] = (
- airplane.total_near_field_force_wind_axes
- )
+ airplane.total_near_field_force_wind_axes)
total_moments[airplane_id, :, results_step] = (
- airplane.total_near_field_moment_wind_axes
- )
+ airplane.total_near_field_moment_wind_axes)
results_step += 1
these_s_drags = total_forces[:, 0, :] ** 2
@@ -254,8 +204,8 @@
these_ms_drags = np.mean(these_s_drags, axis=-1)
these_ms_lifts = np.mean(these_s_lifts, axis=-1)
- these_rms_drags = these_ms_drags**0.5
- these_rms_lifts = these_ms_lifts**0.5
+ these_rms_drags = these_ms_drags ** 0.5
+ these_rms_lifts = these_ms_lifts ** 0.5
rms_drags[wake_state_id, num_flaps_id, num_chord_id, :] = these_rms_drags
rms_lifts[wake_state_id, num_flaps_id, num_chord_id, :] = these_rms_lifts
@@ -265,80 +215,56 @@
max_chord_rmspc = np.inf
if wake_state_id > 0:
- last_wake_rms_lifts = rms_lifts[
- wake_state_id - 1, num_flaps_id, num_chord_id, :
- ]
- last_wake_rms_drags = rms_drags[
- wake_state_id - 1, num_flaps_id, num_chord_id, :
- ]
+ last_wake_rms_lifts = rms_lifts[wake_state_id - 1, num_flaps_id,
+ num_chord_id, :]
+ last_wake_rms_drags = rms_drags[wake_state_id - 1, num_flaps_id,
+ num_chord_id, :]
wake_lift_rmspcs = 100 * np.abs(
- (these_rms_lifts - last_wake_rms_lifts) / last_wake_rms_lifts
- )
+ (these_rms_lifts - last_wake_rms_lifts) / last_wake_rms_lifts)
wake_drag_rmspcs = 100 * np.abs(
- (these_rms_drags - last_wake_rms_drags) / last_wake_rms_drags
- )
+ (these_rms_drags - last_wake_rms_drags) / last_wake_rms_drags)
max_wake_lift_rmspc = np.max(wake_lift_rmspcs)
max_wake_drag_rmspc = np.max(wake_drag_rmspcs)
max_wake_rmspc = max(max_wake_lift_rmspc, max_wake_drag_rmspc)
- print(
- "\t\t\t\tMax Wake RMSPC: ",
- round(max_wake_rmspc, 2),
- "%",
- sep="",
- )
+ print("\t\t\t\tMax Wake RMSPC: ", round(max_wake_rmspc, 2), "%",
+ sep="", )
else:
print("\t\t\t\tMax Wake RMSPC:", max_wake_rmspc)
if num_flaps_id > 0:
- last_flap_rms_lifts = rms_lifts[
- wake_state_id, num_flaps_id - 1, num_chord_id, :
- ]
- last_flap_rms_drags = rms_drags[
- wake_state_id, num_flaps_id - 1, num_chord_id, :
- ]
+ last_flap_rms_lifts = rms_lifts[wake_state_id, num_flaps_id - 1,
+ num_chord_id, :]
+ last_flap_rms_drags = rms_drags[wake_state_id, num_flaps_id - 1,
+ num_chord_id, :]
flap_lift_rmspcs = 100 * np.abs(
- (these_rms_lifts - last_flap_rms_lifts) / last_flap_rms_lifts
- )
+ (these_rms_lifts - last_flap_rms_lifts) / last_flap_rms_lifts)
flap_drag_rmspcs = 100 * np.abs(
- (these_rms_drags - last_flap_rms_drags) / last_flap_rms_drags
- )
+ (these_rms_drags - last_flap_rms_drags) / last_flap_rms_drags)
max_flap_lift_rmspc = np.max(flap_lift_rmspcs)
max_flap_drag_rmspc = np.max(flap_drag_rmspcs)
max_flap_rmspc = max(max_flap_lift_rmspc, max_flap_drag_rmspc)
- print(
- "\t\t\t\tMax Flap RMSPC: ",
- round(max_flap_rmspc, 2),
- "%",
- sep="",
- )
+ print("\t\t\t\tMax Flap RMSPC: ", round(max_flap_rmspc, 2), "%",
+ sep="", )
else:
print("\t\t\t\tMax Flap RMSPC:", max_flap_rmspc)
if num_chord_id > 0:
- last_chord_rms_lifts = rms_lifts[
- wake_state_id, num_flaps_id, num_chord_id - 1, :
- ]
- last_chord_rms_drags = rms_drags[
- wake_state_id, num_flaps_id, num_chord_id - 1, :
- ]
+ last_chord_rms_lifts = rms_lifts[wake_state_id, num_flaps_id,
+ num_chord_id - 1, :]
+ last_chord_rms_drags = rms_drags[wake_state_id, num_flaps_id,
+ num_chord_id - 1, :]
chord_lift_rmspcs = 100 * np.abs(
- (these_rms_lifts - last_chord_rms_lifts) / last_chord_rms_lifts
- )
+ (these_rms_lifts - last_chord_rms_lifts) / last_chord_rms_lifts)
chord_drag_rmspcs = 100 * np.abs(
- (these_rms_drags - last_chord_rms_drags) / last_chord_rms_drags
- )
+ (these_rms_drags - last_chord_rms_drags) / last_chord_rms_drags)
max_chord_lift_rmspc = np.max(chord_lift_rmspcs)
max_chord_drag_rmspc = np.max(chord_drag_rmspcs)
max_chord_rmspc = max(max_chord_lift_rmspc, max_chord_drag_rmspc)
- print(
- "\t\t\t\tMax Chord RMSPC: ",
- round(max_chord_rmspc, 2),
- "%",
- sep="",
- )
+ print("\t\t\t\tMax Chord RMSPC: ", round(max_chord_rmspc, 2), "%",
+ sep="", )
else:
print("\t\t\t\tMax Chord RMSPC:", max_chord_rmspc)
@@ -404,10 +330,7 @@
converged_num_flaps = num_flaps_list[converged_num_flaps_id]
converged_num_chord = num_chord_list[converged_num_chord_id]
this_iter_time = iter_times[
- converged_wake_state_id,
- converged_num_flaps_id,
- converged_num_chord_id,
- ]
+ converged_wake_state_id, converged_num_flaps_id, converged_num_chord_id,]
plot_wake_state_id = converged_wake_state_id
plot_num_flaps_id = converged_num_flaps_id
@@ -433,33 +356,15 @@
else:
continue
- these_rms_lifts = rms_lifts[
- plot_wake_state_id,
- plot_num_flaps_id,
- : (plot_num_chord_id + 2),
- airplane_id,
- ]
- these_rms_drags = rms_drags[
- plot_wake_state_id,
- plot_num_flaps_id,
- : (plot_num_chord_id + 2),
- airplane_id,
- ]
-
- lift_axes.plot(
- num_chord_list[: (plot_num_chord_id + 2)],
- these_rms_lifts,
- label="Row " + str(row),
- marker="o",
- linestyle="--",
- )
- drag_axes.plot(
- num_chord_list[: (plot_num_chord_id + 2)],
- these_rms_drags,
- label="Row " + str(row),
- marker="o",
- linestyle="--",
- )
+ these_rms_lifts = rms_lifts[plot_wake_state_id, plot_num_flaps_id,
+ : (plot_num_chord_id + 2), airplane_id, ]
+ these_rms_drags = rms_drags[plot_wake_state_id, plot_num_flaps_id,
+ : (plot_num_chord_id + 2), airplane_id, ]
+
+ lift_axes.plot(num_chord_list[: (plot_num_chord_id + 2)], these_rms_lifts,
+ label="Row " + str(row), marker="o", linestyle="--", )
+ drag_axes.plot(num_chord_list[: (plot_num_chord_id + 2)], these_rms_drags,
+ label="Row " + str(row), marker="o", linestyle="--", )
lift_axes.set_xlabel("Number of Chordwise Panels")
drag_axes.set_xlabel("Number of Chordwise Panels")
@@ -495,33 +400,15 @@
else:
continue
- these_rms_lifts = rms_lifts[
- plot_wake_state_id,
- : (plot_num_flaps_id + 2),
- plot_num_chord_id,
- airplane_id,
- ]
- these_rms_drags = rms_drags[
- plot_wake_state_id,
- : (plot_num_flaps_id + 2),
- plot_num_chord_id,
- airplane_id,
- ]
-
- lift_axes.plot(
- num_flaps_list[: (plot_num_flaps_id + 2)],
- these_rms_lifts,
- label="Row " + str(row),
- marker="o",
- linestyle="--",
- )
- drag_axes.plot(
- num_flaps_list[: (plot_num_flaps_id + 2)],
- these_rms_drags,
- label="Row " + str(row),
- marker="o",
- linestyle="--",
- )
+ these_rms_lifts = rms_lifts[plot_wake_state_id, : (plot_num_flaps_id + 2),
+ plot_num_chord_id, airplane_id, ]
+ these_rms_drags = rms_drags[plot_wake_state_id, : (plot_num_flaps_id + 2),
+ plot_num_chord_id, airplane_id, ]
+
+ lift_axes.plot(num_flaps_list[: (plot_num_flaps_id + 2)], these_rms_lifts,
+ label="Row " + str(row), marker="o", linestyle="--", )
+ drag_axes.plot(num_flaps_list[: (plot_num_flaps_id + 2)], these_rms_drags,
+ label="Row " + str(row), marker="o", linestyle="--", )
lift_axes.set_xlabel("Number of Flap Cycles")
drag_axes.set_xlabel("Number of Flap Cycles")
diff --git a/main.py b/main.py
index c8f74bec..d787a600 100644
--- a/main.py
+++ b/main.py
@@ -48,7 +48,6 @@ def __init__(self):
self.displayText = ""
def exampleMenu(self, ex_num):
-
files = []
for i, filename in enumerate(os.listdir("examples")):
f = "examples." + filename
diff --git a/pterasoftware/aerodynamics.py b/pterasoftware/aerodynamics.py
index fac44c8c..7ebc3372 100644
--- a/pterasoftware/aerodynamics.py
+++ b/pterasoftware/aerodynamics.py
@@ -48,14 +48,13 @@
from . import functions
-
# Set the value of Squire's parameter that will be used by the induced velocity
# functions. Squire's parameter relates to the size of the vortex cores and the rate
# at which they grow. The value of this parameter is slightly controversial. It
# dramatically affects the stability of the result. I'm using this value, as cited
# for use in flapping-wing vehicles in "Role of Filament Strain in the Free-Vortex
# Modeling of Rotor Wakes" (Ananthan and Leishman, 2004). It is unitless.
-squire = 10**-4
+squire = 10 ** -4
# Set the value of Lamb's constant that will be used by the induced velocity
# functions. Lamb's constant relates to the size of the vortex cores and the rate at
@@ -118,14 +117,8 @@ class HorseshoeVortex:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- finite_leg_origin,
- finite_leg_termination,
- strength,
- infinite_leg_direction,
- infinite_leg_length,
- ):
+ def __init__(self, finite_leg_origin, finite_leg_termination, strength,
+ infinite_leg_direction, infinite_leg_length, ):
"""This is the initialization method.
:param finite_leg_origin: 1D array
@@ -151,28 +144,18 @@ def __init__(
self.infinite_leg_direction = infinite_leg_direction
self.infinite_leg_length = infinite_leg_length
self.right_leg_origin = (
- self.finite_leg_origin + infinite_leg_direction * infinite_leg_length
- )
+ self.finite_leg_origin + infinite_leg_direction * infinite_leg_length)
self.left_leg_termination = (
- self.finite_leg_termination + infinite_leg_direction * infinite_leg_length
- )
+ self.finite_leg_termination + infinite_leg_direction *
+ infinite_leg_length)
# Initialize a line vortex to represent the horseshoe's finite leg.
- self.right_leg = LineVortex(
- origin=self.right_leg_origin,
- termination=self.finite_leg_origin,
- strength=self.strength,
- )
- self.finite_leg = LineVortex(
- origin=self.finite_leg_origin,
- termination=self.finite_leg_termination,
- strength=self.strength,
- )
- self.left_leg = LineVortex(
- origin=self.finite_leg_termination,
- termination=self.left_leg_termination,
- strength=self.strength,
- )
+ self.right_leg = LineVortex(origin=self.right_leg_origin,
+ termination=self.finite_leg_origin, strength=self.strength, )
+ self.finite_leg = LineVortex(origin=self.finite_leg_origin,
+ termination=self.finite_leg_termination, strength=self.strength, )
+ self.left_leg = LineVortex(origin=self.finite_leg_termination,
+ termination=self.left_leg_termination, strength=self.strength, )
def update_strength(self, strength):
"""This method updates the strength of this horseshoe vortex object, and the
@@ -206,14 +189,8 @@ class RingVortex:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- front_left_vertex,
- front_right_vertex,
- back_left_vertex,
- back_right_vertex,
- strength,
- ):
+ def __init__(self, front_left_vertex, front_right_vertex, back_left_vertex,
+ back_right_vertex, strength, ):
"""This is the initialization method.
:param front_left_vertex: 1D array
@@ -238,34 +215,18 @@ def __init__(
self.strength = strength
# Initialize the line vortices that make up the ring vortex.
- self.front_leg = LineVortex(
- origin=self.front_right_vertex,
- termination=self.front_left_vertex,
- strength=self.strength,
- )
- self.left_leg = LineVortex(
- origin=self.front_left_vertex,
- termination=self.back_left_vertex,
- strength=self.strength,
- )
- self.back_leg = LineVortex(
- origin=self.back_left_vertex,
- termination=self.back_right_vertex,
- strength=self.strength,
- )
- self.right_leg = LineVortex(
- origin=self.back_right_vertex,
- termination=self.front_right_vertex,
- strength=self.strength,
- )
+ self.front_leg = LineVortex(origin=self.front_right_vertex,
+ termination=self.front_left_vertex, strength=self.strength, )
+ self.left_leg = LineVortex(origin=self.front_left_vertex,
+ termination=self.back_left_vertex, strength=self.strength, )
+ self.back_leg = LineVortex(origin=self.back_left_vertex,
+ termination=self.back_right_vertex, strength=self.strength, )
+ self.right_leg = LineVortex(origin=self.back_right_vertex,
+ termination=self.front_right_vertex, strength=self.strength, )
# Initialize a variable to hold the centroid of the ring vortex.
- self.center = functions.numba_centroid_of_quadrilateral(
- self.front_left_vertex,
- self.front_right_vertex,
- self.back_left_vertex,
- self.back_right_vertex,
- )
+ self.center = functions.numba_centroid_of_quadrilateral(self.front_left_vertex,
+ self.front_right_vertex, self.back_left_vertex, self.back_right_vertex, )
# Initialize a variable to hold the age of the ring vortex in seconds.
self.age = 0
@@ -285,9 +246,8 @@ def update_strength(self, strength):
self.left_leg.strength = strength
self.back_leg.strength = strength
- def update_position(
- self, front_left_vertex, front_right_vertex, back_left_vertex, back_right_vertex
- ):
+ def update_position(self, front_left_vertex, front_right_vertex, back_left_vertex,
+ back_right_vertex):
"""This method updates the position of the ring vortex, and the positions of
all its attributes.
@@ -311,47 +271,24 @@ def update_position(
self.back_right_vertex = back_right_vertex
# Initialize the line vortices that make up the ring vortex.
- self.front_leg = LineVortex(
- origin=self.front_right_vertex,
- termination=self.front_left_vertex,
- strength=self.strength,
- )
- self.left_leg = LineVortex(
- origin=self.front_left_vertex,
- termination=self.back_left_vertex,
- strength=self.strength,
- )
- self.back_leg = LineVortex(
- origin=self.back_left_vertex,
- termination=self.back_right_vertex,
- strength=self.strength,
- )
- self.right_leg = LineVortex(
- origin=self.back_right_vertex,
- termination=self.front_right_vertex,
- strength=self.strength,
- )
+ self.front_leg = LineVortex(origin=self.front_right_vertex,
+ termination=self.front_left_vertex, strength=self.strength, )
+ self.left_leg = LineVortex(origin=self.front_left_vertex,
+ termination=self.back_left_vertex, strength=self.strength, )
+ self.back_leg = LineVortex(origin=self.back_left_vertex,
+ termination=self.back_right_vertex, strength=self.strength, )
+ self.right_leg = LineVortex(origin=self.back_right_vertex,
+ termination=self.front_right_vertex, strength=self.strength, )
# Initialize a variable to hold the centroid of the ring vortex.
- self.center = functions.numba_centroid_of_quadrilateral(
- self.front_left_vertex,
- self.front_right_vertex,
- self.back_left_vertex,
- self.back_right_vertex,
- )
+ self.center = functions.numba_centroid_of_quadrilateral(self.front_left_vertex,
+ self.front_right_vertex, self.back_left_vertex, self.back_right_vertex, )
@njit(cache=True, fastmath=False)
-def collapsed_velocities_from_horseshoe_vortices(
- points,
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- strengths,
- ages=None,
- nu=0.0,
-):
+def collapsed_velocities_from_horseshoe_vortices(points, back_right_vortex_vertices,
+ front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, strengths, ages=None, nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
horseshoe vortices. At every point, it finds the cumulative induced velocity due
to all the horseshoe vortices.
@@ -400,42 +337,24 @@ def collapsed_velocities_from_horseshoe_vortices(
velocity at each of the N points due to all the horseshoe vortices. The units
are meters per second.
"""
- origins_list = [
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- ]
- terminations_list = [
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- ]
+ origins_list = [back_right_vortex_vertices, front_right_vortex_vertices,
+ front_left_vortex_vertices, ]
+ terminations_list = [front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, ]
induced_velocities = np.zeros((points.shape[0], 3))
# Get the velocity induced by each leg of the ring vortex.
for i in range(3):
- induced_velocities += collapsed_velocities_from_line_vortices(
- points=points,
- origins=origins_list[i],
- terminations=terminations_list[i],
- strengths=strengths,
- ages=ages,
- nu=nu,
- )
+ induced_velocities += collapsed_velocities_from_line_vortices(points=points,
+ origins=origins_list[i], terminations=terminations_list[i],
+ strengths=strengths, ages=ages, nu=nu, )
return induced_velocities
@njit(cache=True, fastmath=False)
-def expanded_velocities_from_horseshoe_vortices(
- points,
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- strengths,
- ages=None,
- nu=0.0,
-):
+def expanded_velocities_from_horseshoe_vortices(points, back_right_vortex_vertices,
+ front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, strengths, ages=None, nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
horseshoe vortices. At every point, it finds the induced velocity due to each
horseshoe vortex.
@@ -484,42 +403,24 @@ def expanded_velocities_from_horseshoe_vortices(
the velocity induced at one point by one of the horseshoe vortices. The units
are meters per second.
"""
- origins_list = [
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- ]
- terminations_list = [
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- ]
+ origins_list = [back_right_vortex_vertices, front_right_vortex_vertices,
+ front_left_vortex_vertices, ]
+ terminations_list = [front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, ]
induced_velocities = np.zeros((points.shape[0], strengths.shape[0], 3))
# Get the velocity induced by each leg of the ring vortex.
for i in range(3):
- induced_velocities += expanded_velocities_from_line_vortices(
- points=points,
- origins=origins_list[i],
- terminations=terminations_list[i],
- strengths=strengths,
- ages=ages,
- nu=nu,
- )
+ induced_velocities += expanded_velocities_from_line_vortices(points=points,
+ origins=origins_list[i], terminations=terminations_list[i],
+ strengths=strengths, ages=ages, nu=nu, )
return induced_velocities
@njit(cache=True, fastmath=False)
-def collapsed_velocities_from_ring_vortices(
- points,
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- strengths,
- ages=None,
- nu=0.0,
-):
+def collapsed_velocities_from_ring_vortices(points, back_right_vortex_vertices,
+ front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, strengths, ages=None, nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
ring vortices. At every point, it finds the cumulative induced velocity due to
all the ring vortices.
@@ -568,44 +469,25 @@ def collapsed_velocities_from_ring_vortices(
velocity at each of the N points due to all the ring vortices. The units are
meters per second.
"""
- origins_list = [
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- ]
- terminations_list = [
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- back_right_vortex_vertices,
- ]
+ origins_list = [back_right_vortex_vertices, front_right_vortex_vertices,
+ front_left_vortex_vertices, back_left_vortex_vertices, ]
+ terminations_list = [front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, back_right_vortex_vertices, ]
induced_velocities = np.zeros((points.shape[0], 3))
# Get the velocity induced by each leg of the ring vortex.
for i in range(4):
- induced_velocities += collapsed_velocities_from_line_vortices(
- points=points,
- origins=origins_list[i],
- terminations=terminations_list[i],
- strengths=strengths,
- ages=ages,
- nu=nu,
- )
+ induced_velocities += collapsed_velocities_from_line_vortices(points=points,
+ origins=origins_list[i], terminations=terminations_list[i],
+ strengths=strengths, ages=ages, nu=nu, )
return induced_velocities
@njit(cache=True, fastmath=False)
-def collapsed_velocities_from_ring_vortices_chordwise_segments(
- points,
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- strengths,
- ages=None,
- nu=0.0,
-):
+def collapsed_velocities_from_ring_vortices_chordwise_segments(points,
+ back_right_vortex_vertices, front_right_vortex_vertices,
+ front_left_vortex_vertices, back_left_vortex_vertices, strengths, ages=None,
+ nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
ring vortices. At every point, it finds the cumulative induced velocity due to
all the ring vortices' chordwise segments.
@@ -654,40 +536,22 @@ def collapsed_velocities_from_ring_vortices_chordwise_segments(
velocity at each of the N points due to all the ring vortices' spanwise
segments. The units are meters per second.
"""
- origins_list = [
- back_right_vortex_vertices,
- front_left_vortex_vertices,
- ]
- terminations_list = [
- front_right_vortex_vertices,
- back_left_vortex_vertices,
- ]
+ origins_list = [back_right_vortex_vertices, front_left_vortex_vertices, ]
+ terminations_list = [front_right_vortex_vertices, back_left_vortex_vertices, ]
induced_velocities = np.zeros((points.shape[0], 3))
# Get the velocity induced by each leg of the ring vortex.
for i in range(2):
- induced_velocities += collapsed_velocities_from_line_vortices(
- points=points,
- origins=origins_list[i],
- terminations=terminations_list[i],
- strengths=strengths,
- ages=ages,
- nu=nu,
- )
+ induced_velocities += collapsed_velocities_from_line_vortices(points=points,
+ origins=origins_list[i], terminations=terminations_list[i],
+ strengths=strengths, ages=ages, nu=nu, )
return induced_velocities
@njit(cache=True, fastmath=False)
-def expanded_velocities_from_ring_vortices(
- points,
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- strengths,
- ages=None,
- nu=0.0,
-):
+def expanded_velocities_from_ring_vortices(points, back_right_vortex_vertices,
+ front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, strengths, ages=None, nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
ring vortices. At every point, it finds the induced velocity due to each ring
vortex.
@@ -736,42 +600,23 @@ def expanded_velocities_from_ring_vortices(
the velocity induced at one point by one of the ring vortices. The units are
meters per second.
"""
- origins_list = [
- back_right_vortex_vertices,
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- ]
- terminations_list = [
- front_right_vortex_vertices,
- front_left_vortex_vertices,
- back_left_vortex_vertices,
- back_right_vortex_vertices,
- ]
+ origins_list = [back_right_vortex_vertices, front_right_vortex_vertices,
+ front_left_vortex_vertices, back_left_vortex_vertices, ]
+ terminations_list = [front_right_vortex_vertices, front_left_vortex_vertices,
+ back_left_vortex_vertices, back_right_vortex_vertices, ]
induced_velocities = np.zeros((points.shape[0], strengths.shape[0], 3))
# Get the velocity induced by each leg of the ring vortex.
for i in range(4):
- induced_velocities += expanded_velocities_from_line_vortices(
- points=points,
- origins=origins_list[i],
- terminations=terminations_list[i],
- strengths=strengths,
- ages=ages,
- nu=nu,
- )
+ induced_velocities += expanded_velocities_from_line_vortices(points=points,
+ origins=origins_list[i], terminations=terminations_list[i],
+ strengths=strengths, ages=ages, nu=nu, )
return induced_velocities
@njit(cache=True, fastmath=False)
-def collapsed_velocities_from_line_vortices(
- points,
- origins,
- terminations,
- strengths,
- ages=None,
- nu=0.0,
-):
+def collapsed_velocities_from_line_vortices(points, origins, terminations, strengths,
+ ages=None, nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
line vortices. At every point, it finds the cumulative induced velocity due to
all the line vortices.
@@ -847,10 +692,10 @@ def collapsed_velocities_from_line_vortices(
r_0_z = termination[2] - origin[2]
# Find the r_0 vector's length.
- r_0 = math.sqrt(r_0_x**2 + r_0_y**2 + r_0_z**2)
+ r_0 = math.sqrt(r_0_x ** 2 + r_0_y ** 2 + r_0_z ** 2)
c_1 = strength / (4 * math.pi)
- c_2 = r_0**2 * r_c**2
+ c_2 = r_0 ** 2 * r_c ** 2
for point_id in range(num_points):
point = points[point_id]
@@ -871,9 +716,9 @@ def collapsed_velocities_from_line_vortices(
r_3_z = r_1_x * r_2_y - r_1_y * r_2_x
# Find the r_1, r_2, and r_3 vectors' lengths.
- r_1 = math.sqrt(r_1_x**2 + r_1_y**2 + r_1_z**2)
- r_2 = math.sqrt(r_2_x**2 + r_2_y**2 + r_2_z**2)
- r_3 = math.sqrt(r_3_x**2 + r_3_y**2 + r_3_z**2)
+ r_1 = math.sqrt(r_1_x ** 2 + r_1_y ** 2 + r_1_z ** 2)
+ r_2 = math.sqrt(r_2_x ** 2 + r_2_y ** 2 + r_2_z ** 2)
+ r_3 = math.sqrt(r_3_x ** 2 + r_3_y ** 2 + r_3_z ** 2)
c_3 = r_1_x * r_2_x + r_1_y * r_2_y + r_1_z * r_2_z
@@ -881,12 +726,11 @@ def collapsed_velocities_from_line_vortices(
# within machine epsilon), there is a removable discontinuity. In this
# case, continue to the next point because there is no velocity induced
# by the current vortex at this point.
- if r_1 < eps or r_2 < eps or r_3**2 < eps:
+ if r_1 < eps or r_2 < eps or r_3 ** 2 < eps:
continue
else:
- c_4 = (
- c_1 * (r_1 + r_2) * (r_1 * r_2 - c_3) / (r_1 * r_2 * (r_3**2 + c_2))
- )
+ c_4 = (c_1 * (r_1 + r_2) * (r_1 * r_2 - c_3) / (
+ r_1 * r_2 * (r_3 ** 2 + c_2)))
velocities[point_id, 0] += c_4 * r_3_x
velocities[point_id, 1] += c_4 * r_3_y
velocities[point_id, 2] += c_4 * r_3_z
@@ -895,14 +739,8 @@ def collapsed_velocities_from_line_vortices(
@njit(cache=True, fastmath=False)
-def expanded_velocities_from_line_vortices(
- points,
- origins,
- terminations,
- strengths,
- ages=None,
- nu=0.0,
-):
+def expanded_velocities_from_line_vortices(points, origins, terminations, strengths,
+ ages=None, nu=0.0, ):
"""This function takes in a group of points, and the attributes of a group of
line vortices. At every point, it finds the induced velocity due to each line
vortex.
@@ -978,10 +816,10 @@ def expanded_velocities_from_line_vortices(
r_0_z = termination[2] - origin[2]
# Find the r_0 vector's length.
- r_0 = math.sqrt(r_0_x**2 + r_0_y**2 + r_0_z**2)
+ r_0 = math.sqrt(r_0_x ** 2 + r_0_y ** 2 + r_0_z ** 2)
c_1 = strength / (4 * math.pi)
- c_2 = r_0**2 * r_c**2
+ c_2 = r_0 ** 2 * r_c ** 2
for point_id in range(num_points):
point = points[point_id]
@@ -1002,9 +840,9 @@ def expanded_velocities_from_line_vortices(
r_3_z = r_1_x * r_2_y - r_1_y * r_2_x
# Find the r_1, r_2, and r_3 vectors' lengths.
- r_1 = math.sqrt(r_1_x**2 + r_1_y**2 + r_1_z**2)
- r_2 = math.sqrt(r_2_x**2 + r_2_y**2 + r_2_z**2)
- r_3 = math.sqrt(r_3_x**2 + r_3_y**2 + r_3_z**2)
+ r_1 = math.sqrt(r_1_x ** 2 + r_1_y ** 2 + r_1_z ** 2)
+ r_2 = math.sqrt(r_2_x ** 2 + r_2_y ** 2 + r_2_z ** 2)
+ r_3 = math.sqrt(r_3_x ** 2 + r_3_y ** 2 + r_3_z ** 2)
c_3 = r_1_x * r_2_x + r_1_y * r_2_y + r_1_z * r_2_z
@@ -1012,12 +850,11 @@ def expanded_velocities_from_line_vortices(
# within machine epsilon), there is a removable discontinuity. In this
# case, set the velocity components to their true values, which are 0.0
# meters per second.
- if r_1 < eps or r_2 < eps or r_3**2 < eps:
+ if r_1 < eps or r_2 < eps or r_3 ** 2 < eps:
continue
else:
- c_4 = (
- c_1 * (r_1 + r_2) * (r_1 * r_2 - c_3) / (r_1 * r_2 * (r_3**2 + c_2))
- )
+ c_4 = (c_1 * (r_1 + r_2) * (r_1 * r_2 - c_3) / (
+ r_1 * r_2 * (r_3 ** 2 + c_2)))
velocities[point_id, vortex_id, 0] = c_4 * r_3_x
velocities[point_id, vortex_id, 1] = c_4 * r_3_y
velocities[point_id, vortex_id, 2] = c_4 * r_3_z
diff --git a/pterasoftware/convergence.py b/pterasoftware/convergence.py
index 9b5d04ff..385aef0d 100644
--- a/pterasoftware/convergence.py
+++ b/pterasoftware/convergence.py
@@ -256,8 +256,7 @@ def analyze_steady_convergence(
# this airplane's mesh.
s_ref=None,
c_ref=None,
- b_ref=None,
- # This value changes.
+ b_ref=None, # This value changes.
wings=these_wings,
)
)
@@ -899,8 +898,7 @@ def analyze_unsteady_convergence(
# with this airplane's mesh.
s_ref=None,
c_ref=None,
- b_ref=None,
- # This value changes.
+ b_ref=None, # This value changes.
wings=these_base_wings,
)
diff --git a/pterasoftware/functions.py b/pterasoftware/functions.py
index aeac2179..8226387d 100644
--- a/pterasoftware/functions.py
+++ b/pterasoftware/functions.py
@@ -291,7 +291,6 @@ def process_steady_solver_forces(
# Iterate through this solver's panels.
for panel_num, panel in enumerate(steady_solver.panels):
-
# Get this panel's near field forces and moments in geometry axes and wind axes.
this_force_geometry_axes = near_field_forces_geometry_axes[panel_num, :]
this_moment_geometry_axes = near_field_moments_geometry_axes[panel_num, :]
@@ -337,7 +336,6 @@ def process_steady_solver_forces(
# Iterate through the airplanes and calculate each one's coefficients.
for airplane in steady_solver.airplanes:
-
# Calculate this airplane's force coefficients.
induced_drag_coefficient = (
-airplane.total_near_field_force_wind_axes[0]
@@ -424,7 +422,6 @@ def process_unsteady_solver_forces(
# Iterate through this solver's panels.
for panel_num, panel in enumerate(unsteady_solver.panels):
-
# Get this panel's near field forces and moments in geometry axes and wind
# axes.
this_force_geometry_axes = near_field_forces_geometry_axes[panel_num, :]
@@ -471,7 +468,6 @@ def process_unsteady_solver_forces(
# Iterate through the airplanes and calculate each one's coefficients.
for airplane in unsteady_solver.current_airplanes:
-
# Calculate this airplane's force coefficients.
induced_drag_coefficient = (
-airplane.total_near_field_force_wind_axes[0]
diff --git a/pterasoftware/geometry.py b/pterasoftware/geometry.py
index c4e72698..fd5e2c97 100644
--- a/pterasoftware/geometry.py
+++ b/pterasoftware/geometry.py
@@ -46,18 +46,8 @@ class Airplane:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- name="Untitled",
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
- weight=0.0,
- wings=None,
- s_ref=None,
- c_ref=None,
- b_ref=None,
- ):
+ def __init__(self, name="Untitled", x_ref=0.0, y_ref=0.0, z_ref=0.0, weight=0.0,
+ wings=None, s_ref=None, c_ref=None, b_ref=None, ):
"""This is the initialization method.
:param name: str, optional
@@ -185,17 +175,9 @@ class Wing:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- name="Untitled Wing",
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- wing_cross_sections=None,
- symmetric=False,
- num_chordwise_panels=8,
- chordwise_spacing="cosine",
- ):
+ def __init__(self, name="Untitled Wing", x_le=0.0, y_le=0.0, z_le=0.0,
+ wing_cross_sections=None, symmetric=False, num_chordwise_panels=8,
+ chordwise_spacing="cosine", ):
"""This is the initialization method.
:param name: str, optional
@@ -289,11 +271,9 @@ def projected_area(self):
# Iterate through the wing cross sections and add the area of their
# corresponding wing sections to the total projected area.
for wing_cross_section_id, wing_cross_section in enumerate(
- self.wing_cross_sections[:-1]
- ):
+ self.wing_cross_sections[:-1]):
next_wing_cross_section = self.wing_cross_sections[
- wing_cross_section_id + 1
- ]
+ wing_cross_section_id + 1]
span = abs(next_wing_cross_section.y_le - wing_cross_section.y_le)
@@ -379,11 +359,9 @@ def mean_aerodynamic_chord(self):
# Iterate through the wing cross sections to add the contribution of their
# corresponding wing section to the piecewise integral.
for wing_cross_section_id, wing_cross_section in enumerate(
- self.wing_cross_sections[:-1]
- ):
+ self.wing_cross_sections[:-1]):
next_wing_cross_section = self.wing_cross_sections[
- wing_cross_section_id + 1
- ]
+ wing_cross_section_id + 1]
root_chord = wing_cross_section.chord
tip_chord = next_wing_cross_section.chord
@@ -393,11 +371,8 @@ def mean_aerodynamic_chord(self):
# projected on to the body-frame's XY plane). For a trapezoid,
# the integral from the cited equation can be shown to evaluate to the
# following.
- integral += (
- section_length
- * (root_chord**2 + root_chord * tip_chord + tip_chord**2)
- / 3
- )
+ integral += (section_length * (
+ root_chord ** 2 + root_chord * tip_chord + tip_chord ** 2) / 3)
# Multiply the integral's value by the coefficients from the cited equation.
if self.symmetric:
@@ -424,20 +399,10 @@ class WingCrossSection:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- chord=1.0,
- twist=0.0,
- airfoil=None,
- control_surface_type="symmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=0.0,
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
- ):
+ def __init__(self, x_le=0.0, y_le=0.0, z_le=0.0, chord=1.0, twist=0.0, airfoil=None,
+ control_surface_type="symmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=0.0, num_spanwise_panels=8,
+ spanwise_spacing="cosine", ):
"""This is the initialization method.
:param x_le: float, optional
@@ -520,9 +485,8 @@ def trailing_edge(self):
"""
# Find the rotation matrix given the cross section's twist.
- rotation_matrix = functions.angle_axis_rotation_matrix(
- self.twist * np.pi / 180, np.array([0, 1, 0])
- )
+ rotation_matrix = functions.angle_axis_rotation_matrix(self.twist * np.pi / 180,
+ np.array([0, 1, 0]))
# Use the rotation matrix and the leading edge coordinates to calculate the
# trailing edge coordinates.
@@ -576,13 +540,8 @@ class Airfoil:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- name="Untitled Airfoil",
- coordinates=None,
- repanel=True,
- n_points_per_side=400,
- ):
+ def __init__(self, name="Untitled Airfoil", coordinates=None, repanel=True,
+ n_points_per_side=400, ):
"""This is the initialization method.
:param name: str, optional
@@ -639,7 +598,8 @@ def populate_coordinates(self):
4-series airfoil, or loaded from the airfoil database (a folder named
"airfoils" in this directory, that contains a library of dat files for
airfoil coordinates). NACA 4-series airfoil generation is an adaptation of:
- https://en.wikipedia.org/wiki/NACA_airfoil#Equation_for_a_cambered_4-digit_NACA_airfoil.
+ https://en.wikipedia.org/wiki/NACA_airfoil#Equation_for_a_cambered_4
+ -digit_NACA_airfoil.
:return: None
"""
@@ -663,55 +623,29 @@ def populate_coordinates(self):
# Make uncambered coordinates and generate cosine-spaced points.
x_t = functions.cosspace(0, 1, n_points_per_side)
- y_t = (
- 5
- * thickness
- * (
- +0.2969 * np.power(x_t, 0.5)
- - 0.1260 * x_t
- - 0.3516 * np.power(x_t, 2)
- + 0.2843 * np.power(x_t, 3)
- - 0.1015 * np.power(x_t, 4)
- )
- )
+ y_t = (5 * thickness * (+0.2969 * np.power(x_t,
+ 0.5) - 0.1260 * x_t - 0.3516 * np.power(
+ x_t, 2) + 0.2843 * np.power(x_t, 3) - 0.1015 * np.power(x_t,
+ 4)))
# Prevent divide by zero errors for airfoils like the NACA 0012.
if camber_loc == 0:
camber_loc = 0.5
# Get the camber.
- y_c_piece1 = (
- max_camber
- / camber_loc**2
- * (
- 2 * camber_loc * x_t[x_t <= camber_loc]
- - x_t[x_t <= camber_loc] ** 2
- )
- )
- y_c_piece2 = (
- max_camber
- / (1 - camber_loc) ** 2
- * (
- (1 - 2 * camber_loc)
- + 2 * camber_loc * x_t[x_t > camber_loc]
- - x_t[x_t > camber_loc] ** 2
- )
- )
+ y_c_piece1 = (max_camber / camber_loc ** 2 * (
+ 2 * camber_loc * x_t[x_t <= camber_loc] - x_t[
+ x_t <= camber_loc] ** 2))
+ y_c_piece2 = (max_camber / (1 - camber_loc) ** 2 * (
+ (1 - 2 * camber_loc) + 2 * camber_loc * x_t[
+ x_t > camber_loc] - x_t[x_t > camber_loc] ** 2))
y_c = np.hstack((y_c_piece1, y_c_piece2))
# Get camber slope.
- first_piece_slope = (
- 2
- * max_camber
- / camber_loc**2
- * (camber_loc - x_t[x_t <= camber_loc])
- )
- second_piece_slope = (
- 2
- * max_camber
- / (1 - camber_loc) ** 2
- * (camber_loc - x_t[x_t > camber_loc])
- )
+ first_piece_slope = (2 * max_camber / camber_loc ** 2 * (
+ camber_loc - x_t[x_t <= camber_loc]))
+ second_piece_slope = (2 * max_camber / (1 - camber_loc) ** 2 * (
+ camber_loc - x_t[x_t > camber_loc]))
slope = np.hstack((first_piece_slope, second_piece_slope))
theta = np.arctan(slope)
@@ -740,25 +674,21 @@ def populate_coordinates(self):
try:
# Import the airfoils package as "airfoils".
- airfoils = importlib.import_module(
- name=".airfoils",
- package="pterasoftware",
- )
+ airfoils = importlib.import_module(name=".airfoils",
+ package="pterasoftware", )
# Read the text from the airfoil file.
raw_text = importlib.resources.read_text(airfoils, name + ".dat")
# Trim the text at the return characters.
- trimmed_text = raw_text[raw_text.find("\n") :]
+ trimmed_text = raw_text[raw_text.find("\n"):]
# Input the coordinates into a 1D array.
coordinates_1d = np.fromstring(trimmed_text, sep="\n")
# Check to make sure the number of elements in the array is even.
- assert len(coordinates_1d) % 2 == 0, (
- "File was found in airfoil database, "
- "but it could not be read correctly."
- )
+ assert len(coordinates_1d) % 2 == 0, ("File was found in airfoil database, "
+ "but it could not be read correctly.")
# Reshape the 1D coordinates array into an N x 2 array, where N is the
# number of rows.
@@ -834,7 +764,7 @@ def lower_coordinates(self):
"""
# Find the lower coordinates.
- lower_coordinates = self.coordinates[self.leading_edge_index() :, :]
+ lower_coordinates = self.coordinates[self.leading_edge_index():, :]
# Return the lower coordinates.
return lower_coordinates
@@ -875,32 +805,27 @@ def get_downsampled_mcl(self, mcl_fractions):
# Find the distances between points along the mean camber line, assuming
# linear interpolation.
mcl_distances_between_points = np.sqrt(
- np.power(mcl[:-1, 0] - mcl[1:, 0], 2)
- + np.power(mcl[:-1, 1] - mcl[1:, 1], 2)
- )
+ np.power(mcl[:-1, 0] - mcl[1:, 0], 2) + np.power(mcl[:-1, 1] - mcl[1:, 1],
+ 2))
# Create a horizontal 1D array that contains the distance along the mean
# camber line of each point.
mcl_distances_cumulative = np.hstack(
- (0, np.cumsum(mcl_distances_between_points))
- )
+ (0, np.cumsum(mcl_distances_between_points)))
# Normalize the 1D array so that it ranges from 0 to 1.
mcl_distances_cumulative_normalized = (
- mcl_distances_cumulative / mcl_distances_cumulative[-1]
- )
+ mcl_distances_cumulative / mcl_distances_cumulative[-1])
# Linearly interpolate to find the x coordinates of the mean camber line at
# the given mean camber line fractions.
- mcl_downsampled_x = np.interp(
- x=mcl_fractions, xp=mcl_distances_cumulative_normalized, fp=mcl[:, 0]
- )
+ mcl_downsampled_x = np.interp(x=mcl_fractions,
+ xp=mcl_distances_cumulative_normalized, fp=mcl[:, 0])
# Linearly interpolate to find the y coordinates of the mean camber line at
# the given mean camber line fractions.
- mcl_downsampled_y = np.interp(
- x=mcl_fractions, xp=mcl_distances_cumulative_normalized, fp=mcl[:, 1]
- )
+ mcl_downsampled_y = np.interp(x=mcl_fractions,
+ xp=mcl_distances_cumulative_normalized, fp=mcl[:, 1])
# Combine the x and y coordinates of the downsampled mean camber line.
mcl_downsampled = np.column_stack((mcl_downsampled_x, mcl_downsampled_y))
@@ -922,12 +847,8 @@ def get_camber_at_chord_fraction(self, chord_fraction):
# Create a function that interpolates between the x and y coordinates of the
# mean camber line.
- camber_function = sp_interp.interp1d(
- x=self.mcl_coordinates[:, 0],
- y=self.mcl_coordinates[:, 1],
- copy=False,
- fill_value="extrapolate",
- )
+ camber_function = sp_interp.interp1d(x=self.mcl_coordinates[:, 0],
+ y=self.mcl_coordinates[:, 1], copy=False, fill_value="extrapolate", )
# Find the value of the camber (the y coordinate) of the airfoil at the
# requested chord fraction.
@@ -962,23 +883,16 @@ def repanel_current_airfoil(self, n_points_per_side=100):
# surfaces as a function of the chord fractions
upper_func = sp_interp.PchipInterpolator(
x=np.flip(upper_original_coordinates[:, 0]),
- y=np.flip(upper_original_coordinates[:, 1]),
- )
- lower_func = sp_interp.PchipInterpolator(
- x=lower_original_coordinates[:, 0], y=lower_original_coordinates[:, 1]
- )
+ y=np.flip(upper_original_coordinates[:, 1]), )
+ lower_func = sp_interp.PchipInterpolator(x=lower_original_coordinates[:, 0],
+ y=lower_original_coordinates[:, 1])
# Find the x and y coordinates of the upper and lower surfaces at each of the
# cosine-spaced x values.
x_coordinates = np.hstack(
- (np.flip(cosine_spaced_x_values), cosine_spaced_x_values[1:])
- )
- y_coordinates = np.hstack(
- (
- upper_func(np.flip(cosine_spaced_x_values)),
- lower_func(cosine_spaced_x_values[1:]),
- )
- )
+ (np.flip(cosine_spaced_x_values), cosine_spaced_x_values[1:]))
+ y_coordinates = np.hstack((upper_func(np.flip(cosine_spaced_x_values)),
+ lower_func(cosine_spaced_x_values[1:]),))
# Stack the coordinates together and return them.
coordinates = np.column_stack((x_coordinates, y_coordinates))
@@ -1010,8 +924,7 @@ def add_control_surface(self, deflection=0.0, hinge_point=0.75):
# Find y coordinate at the hinge point x coordinate and make it a vector.
hinge_point = np.array(
- (hinge_point, self.get_camber_at_chord_fraction(hinge_point))
- )
+ (hinge_point, self.get_camber_at_chord_fraction(hinge_point)))
# Split the airfoil into the sections before and after the hinge.
split_index = np.where(self.mcl_coordinates[:, 0] > hinge_point[0])[0][0]
@@ -1022,31 +935,23 @@ def add_control_surface(self, deflection=0.0, hinge_point=0.75):
# Rotate the mean camber line coordinates and upper minus mean camber line
# vectors.
- new_mcl_coordinates_after = (
- np.transpose(
- rotation_matrix @ np.transpose(mcl_coordinates_after - hinge_point)
- )
- + hinge_point
- )
+ new_mcl_coordinates_after = (np.transpose(rotation_matrix @ np.transpose(
+ mcl_coordinates_after - hinge_point)) + hinge_point)
new_upper_minus_mcl_after = np.transpose(
- rotation_matrix @ np.transpose(upper_minus_mcl_after)
- )
+ rotation_matrix @ np.transpose(upper_minus_mcl_after))
# Assemble the new, flapped airfoil.
new_mcl_coordinates = np.vstack(
- (mcl_coordinates_before, new_mcl_coordinates_after)
- )
+ (mcl_coordinates_before, new_mcl_coordinates_after))
new_upper_minus_mcl = np.vstack(
- (upper_minus_mcl_before, new_upper_minus_mcl_after)
- )
+ (upper_minus_mcl_before, new_upper_minus_mcl_after))
upper_coordinates = np.flipud(new_mcl_coordinates + new_upper_minus_mcl)
lower_coordinates = new_mcl_coordinates - new_upper_minus_mcl
coordinates = np.vstack((upper_coordinates, lower_coordinates[1:, :]))
# Initialize the new, flapped airfoil and return it.
- flapped_airfoil = Airfoil(
- name=self.name + " flapped", coordinates=coordinates, repanel=False
- )
+ flapped_airfoil = Airfoil(name=self.name + " flapped", coordinates=coordinates,
+ repanel=False)
return flapped_airfoil
def draw(self):
diff --git a/pterasoftware/models/steady_horseshoe_vortex_lattice_method_solver.py b/pterasoftware/models/steady_horseshoe_vortex_lattice_method_solver.py
index bdb8c680..8decbfd6 100644
--- a/pterasoftware/models/steady_horseshoe_vortex_lattice_method_solver.py
+++ b/pterasoftware/models/steady_horseshoe_vortex_lattice_method_solver.py
@@ -6,113 +6,47 @@ def __init__(self):
var = "Variables"
def runSolver(self):
- example_airplane = ps.geometry.Airplane(
- name="Example Airplane",
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
- s_ref=None,
- b_ref=None,
- c_ref=None,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- symmetric=True,
- num_chordwise_panels=8,
- chordwise_spacing="cosine",
+ example_airplane = ps.geometry.Airplane(name="Example Airplane", x_ref=0.0,
+ y_ref=0.0, z_ref=0.0, s_ref=None, b_ref=None, c_ref=None, wings=[
+ ps.geometry.Wing(name="Main Wing", x_le=0.0, y_le=0.0, z_le=0.0,
+ symmetric=True, num_chordwise_panels=8, chordwise_spacing="cosine",
wing_cross_sections=[
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- twist=0.0,
- control_surface_type="symmetric",
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=0.0, z_le=0.0,
+ twist=0.0, control_surface_type="symmetric",
control_surface_hinge_point=0.75,
- control_surface_deflection=0.0,
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- coordinates=None,
- repanel=True,
- n_points_per_side=400,
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- z_le=1.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
- ps.geometry.Wing(
- name="V-Tail",
- x_le=6.75,
- z_le=0.25,
- symmetric=True,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- z_le=1.0,
- chord=1.0,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
- )
-
- example_operating_point = ps.operating_point.OperatingPoint(
- density=1.225,
- beta=0.0,
- velocity=10.0,
- alpha=1.0,
- )
-
- example_problem = ps.problems.SteadyProblem(
- airplanes=[example_airplane],
- operating_point=example_operating_point,
- )
+ control_surface_deflection=0.0, num_spanwise_panels=8,
+ spanwise_spacing="cosine", chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca2412",
+ coordinates=None, repanel=True,
+ n_points_per_side=400, ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, z_le=1.0,
+ chord=1.5, twist=5.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
+ ps.geometry.Wing(name="V-Tail", x_le=6.75, z_le=0.25, symmetric=True,
+ wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, z_le=1.0,
+ chord=1.0, twist=-5.0, airfoil=ps.geometry.Airfoil(
+ name="naca0012", ), ), ], ), ], )
+
+ example_operating_point = ps.operating_point.OperatingPoint(density=1.225,
+ beta=0.0, velocity=10.0, alpha=1.0, )
+
+ example_problem = ps.problems.SteadyProblem(airplanes=[example_airplane],
+ operating_point=example_operating_point, )
del example_airplane
del example_operating_point
- example_solver = ps.steady_horseshoe_vortex_lattice_method.SteadyHorseshoeVortexLatticeMethodSolver(
- steady_problem=example_problem
- )
+ example_solver = (ps.steady_horseshoe_vortex_lattice_method
+ .SteadyHorseshoeVortexLatticeMethodSolver(
+ steady_problem=example_problem))
del example_problem
- example_solver.run(
- logging_level="Warning",
- )
+ example_solver.run(logging_level="Warning", )
ps.output.print_steady_results(steady_solver=example_solver)
- ps.output.draw(
- solver=example_solver,
- scalar_type="lift",
- show_streamlines=True,
- show_wake_vortices=False,
- save=False,
- )
+ ps.output.draw(solver=example_solver, scalar_type="lift", show_streamlines=True,
+ show_wake_vortices=False, save=False, )
diff --git a/pterasoftware/models/steady_ring_vortex_lattice_method_solver.py b/pterasoftware/models/steady_ring_vortex_lattice_method_solver.py
index 926b07fa..f2ac67b2 100644
--- a/pterasoftware/models/steady_ring_vortex_lattice_method_solver.py
+++ b/pterasoftware/models/steady_ring_vortex_lattice_method_solver.py
@@ -18,187 +18,122 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- # Define the location of the leading edge of the wing relative to the
- # global coordinate system fixed front left corner of the first
- # airplane's first wing's root wing cross section. These values all
+ s_ref=None, b_ref=None, c_ref=None, wings=[ps.geometry.Wing(name="Main Wing",
+ # Define the location of the leading edge of the wing relative to the
+ # global coordinate system fixed front left corner of the first
+ # airplane's first wing's root wing cross section. These values all
+ # default to 0.0 meters.
+ x_le=0.0, y_le=0.0, z_le=0.0,
+ # Declare that this wing is symmetric. This means that the geometry will
+ # be reflected across plane of this wing's root wing cross section. Note
+ # that the geometry coordinates are defined as such: If you were riding
+ # in the airplane, the positive x direction would point behind you,
+ # the positive y direction would point out of your right wing, and the
+ # positive z direction would point upwards, out of your chair. These
+ # directions form a right-handed coordinate system. The default value of
+ # "symmetric" is false.
+ symmetric=True,
+ # Define the number of chordwise panels on the wing, and the spacing
+ # between them. The number of chordwise panels defaults to 8 panels. The
+ # spacing defaults to "cosine", which makes the panels relatively finer,
+ # in the chordwise direction, near the leading and trailing edges. The
+ # other option is "uniform".
+ num_chordwise_panels=8, chordwise_spacing="cosine",
+ # Every wing has a list of wing cross sections. In order for the geometry
+ # output to be sensible, each wing must have at least two wing cross
+ # sections.
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ # Define the location of the leading edge of the wing cross
+ # section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- # Declare that this wing is symmetric. This means that the geometry will
- # be reflected across plane of this wing's root wing cross section. Note
- # that the geometry coordinates are defined as such: If you were riding
- # in the airplane, the positive x direction would point behind you,
- # the positive y direction would point out of your right wing, and the
- # positive z direction would point upwards, out of your chair. These
- # directions form a right-handed coordinate system. The default value of
- # "symmetric" is false.
- symmetric=True,
- # Define the number of chordwise panels on the wing, and the spacing
- # between them. The number of chordwise panels defaults to 8 panels. The
- # spacing defaults to "cosine", which makes the panels relatively finer,
- # in the chordwise direction, near the leading and trailing edges. The
- # other option is "uniform".
- num_chordwise_panels=8,
- chordwise_spacing="cosine",
- # Every wing has a list of wing cross sections. In order for the geometry
- # output to be sensible, each wing must have at least two wing cross
- # sections.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- # Define the location of the leading edge of the wing cross
- # section relative to the wing's leading edge. These values all
- # default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- # Define the twist of the wing cross section in degrees. This is
- # equivalent to incidence angle of cross section. The twist is
- # about the leading edge. Note that the twist is only stable up
- # to 45.0 degrees. Values above that produce unexpected results.
- # This will be fixed in a future release. The default value is
- # 0.0 degrees. Positive twist corresponds to positive rotation
- # about the y axis, as defined by the right-hand rule.
- twist=0.0,
- # Define the type of control surface. The options are "symmetric"
- # and "asymmetric". This is only applicable if your wing is also
- # symmetric. If so, symmetric control surfaces will deflect in
- # the same direction, like flaps, while asymmetric control
- # surfaces will deflect in opposite directions, like ailerons.
- # The default value is "symmetric".
- control_surface_type="asymmetric",
- # Define the point on the airfoil where the control surface
- # hinges. This is expressed as a faction of the chord length,
- # back from the leading edge. The default value is 0.75.
- control_surface_hinge_point=0.75,
- # Define the deflection of the control surface in degrees. The
- # default is 0.0 degrees. We'll set it to 10.0 degrees to show an
- # example of an aileron deflection.
- control_surface_deflection=10.0,
- # Define the number of spanwise panels on the wing cross section,
- # and the spacing between them. The number of spanwise panels
- # defaults to 8 panels. The spacing defaults to "cosine",
- # which makes the panels relatively finer, in the spanwise
- # direction, near the cross section ends. The other option is
- # "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
- # Set the chord of this cross section to be 1.75 meters. This
- # value defaults to 1.0 meter.
- chord=1.5,
- airfoil=ps.geometry.Airfoil(
- # Give the airfoil a name. This defaults to "Untitled
- # Airfoil". This name should correspond to a name in the
- # airfoil directory or a NACA four series airfoil, unless you
- # are passing in your own coordinates.
- name="naca2412",
- # If you wish to pass in coordinates, set this to a N x 2
- # array of the airfoil's coordinates, where N is the number
- # of coordinates. Treat this as an immutable, don't edit
- # directly after initialization. If you wish to load
- # coordinates from the airfoil directory, leave this as None.
- # The default is None. Make sure that any airfoil coordinates
- # used range in x from 0 to 1.
- coordinates=None,
- # This is the variable that determines whether or not you
- # would like to repanel the airfoil coordinates. This applies
- # to coordinates passed in by the user or to the directory
- # coordinates. It is highly recommended to set this to True.
- # The default is True.
- repanel=True,
- # This is number of points to use if repaneling the airfoil.
- # It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
- # Define the next wing cross section. From here on out,
- # the declarations will not be as commented as the previous. See the
- # above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=1.5,
- y_le=6.0,
- z_le=0.5,
- chord=0.75,
- control_surface_type="asymmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=10.0,
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ x_le=0.0, y_le=0.0, z_le=0.0,
+ # Define the twist of the wing cross section in degrees. This is
+ # equivalent to incidence angle of cross section. The twist is
+ # about the leading edge. Note that the twist is only stable up
+ # to 45.0 degrees. Values above that produce unexpected results.
+ # This will be fixed in a future release. The default value is
+ # 0.0 degrees. Positive twist corresponds to positive rotation
+ # about the y axis, as defined by the right-hand rule.
+ twist=0.0, # Define the type of control surface. The options are "symmetric"
+ # and "asymmetric". This is only applicable if your wing is also
+ # symmetric. If so, symmetric control surfaces will deflect in
+ # the same direction, like flaps, while asymmetric control
+ # surfaces will deflect in opposite directions, like ailerons.
+ # The default value is "symmetric".
+ control_surface_type="asymmetric",
+ # Define the point on the airfoil where the control surface
+ # hinges. This is expressed as a faction of the chord length,
+ # back from the leading edge. The default value is 0.75.
+ control_surface_hinge_point=0.75,
+ # Define the deflection of the control surface in degrees. The
+ # default is 0.0 degrees. We'll set it to 10.0 degrees to show an
+ # example of an aileron deflection.
+ control_surface_deflection=10.0,
+ # Define the number of spanwise panels on the wing cross section,
+ # and the spacing between them. The number of spanwise panels
+ # defaults to 8 panels. The spacing defaults to "cosine",
+ # which makes the panels relatively finer, in the spanwise
+ # direction, near the cross section ends. The other option is
+ # "uniform".
+ num_spanwise_panels=8, spanwise_spacing="cosine",
+ # Set the chord of this cross section to be 1.75 meters. This
+ # value defaults to 1.0 meter.
+ chord=1.5, airfoil=ps.geometry.Airfoil(
+ # Give the airfoil a name. This defaults to "Untitled
+ # Airfoil". This name should correspond to a name in the
+ # airfoil directory or a NACA four series airfoil, unless you
+ # are passing in your own coordinates.
+ name="naca2412",
+ # If you wish to pass in coordinates, set this to a N x 2
+ # array of the airfoil's coordinates, where N is the number
+ # of coordinates. Treat this as an immutable, don't edit
+ # directly after initialization. If you wish to load
+ # coordinates from the airfoil directory, leave this as None.
+ # The default is None. Make sure that any airfoil coordinates
+ # used range in x from 0 to 1.
+ coordinates=None,
+ # This is the variable that determines whether or not you
+ # would like to repanel the airfoil coordinates. This applies
+ # to coordinates passed in by the user or to the directory
+ # coordinates. It is highly recommended to set this to True.
+ # The default is True.
+ repanel=True,
+ # This is number of points to use if repaneling the airfoil.
+ # It is ignored if the repanel is False. The default is 400.
+ n_points_per_side=400, ), ),
+ # Define the next wing cross section. From here on out,
+ # the declarations will not be as commented as the previous. See the
+ # above comments if you have questions.
+ ps.geometry.WingCrossSection(x_le=1.5, y_le=6.0, z_le=0.5, chord=0.75,
+ control_surface_type="asymmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=10.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="Horizontal Stabilizer",
- x_le=6.75,
- z_le=0.25,
- symmetric=True,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ ps.geometry.Wing(name="Horizontal Stabilizer", x_le=6.75, z_le=0.25,
+ symmetric=True, wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- chord=1.0,
- twist=-5.0,
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, chord=1.0, twist=-5.0,
# Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="Vertical Stabilizer",
- x_le=6.75,
- z_le=0.5,
- symmetric=False,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
+ ps.geometry.Wing(name="Vertical Stabilizer", x_le=6.75, z_le=0.5,
+ symmetric=False, wing_cross_sections=[
+ ps.geometry.WingCrossSection(chord=1.5,
# Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- z_le=2.0,
- chord=1.0,
+ ps.geometry.WingCrossSection(x_le=0.5, z_le=2.0, chord=1.0,
# Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Define a new operating point object. This defines the state at which the airplane
# object is operating.
@@ -214,8 +149,7 @@
velocity=10.0,
# Define the angle of attack the airplane is experiencing. This defaults to 5.0
# degrees.
- alpha=1.0,
-)
+ alpha=1.0, )
# Define a new steady problem. A steady problem contains an airplane object and an
# operating point object.
@@ -223,8 +157,7 @@
# Set this steady problem's list of airplane objects to be the one we just created.
airplanes=[example_airplane],
# Set this steady problem's operating point object ot be the one we just created.
- operating_point=example_operating_point,
-)
+ operating_point=example_operating_point, )
# Now, the airplane and operating point object exist within the steady problem
# object. I like to delete the external pointers to these objects to ease debugging.
@@ -234,10 +167,10 @@
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.steady_ring_vortex_lattice_method.SteadyRingVortexLatticeMethodSolver(
+example_solver = (ps.steady_ring_vortex_lattice_method
+.SteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- steady_problem=example_problem
-)
+ steady_problem=example_problem))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver. Again, this is unnecessary, I just like to do this to ease debugging.
@@ -248,15 +181,13 @@
# This parameter determines the detail of information that the solver's logger
# will output while running. The options are, in order of detail and severity,
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
- logging_level="Warning",
-)
+ logging_level="Warning", )
# Call this function from the output module to print the results.
ps.output.print_steady_results(steady_solver=example_solver)
# Call the software's draw function on the solver.
-ps.output.draw(
- solver=example_solver,
+ps.output.draw(solver=example_solver,
# Tell the draw function to color the aircraft's wing panels with the local
# lift coefficient. The valid arguments for this parameter are None, "induced drag",
# "side force", or "lift".
@@ -269,8 +200,7 @@
show_wake_vortices=False,
# The the draw function to not save the drawing as an image file. This way,
# the drawing will still be displayed but not saved. This value defaults to false.
- save=False,
-)
+ save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_static.py b/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_static.py
index 4c38290b..39c5d655 100644
--- a/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_static.py
+++ b/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_static.py
@@ -18,31 +18,22 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- # All airplane objects have a list of wings.
- wings=[
- # Create the first wing object in this airplane.
- ps.geometry.Wing(
- # Give the wing a name, this defaults to "Untitled Wing".
+ s_ref=None, b_ref=None, c_ref=None, # All airplane objects have a list of wings.
+ wings=[# Create the first wing object in this airplane.
+ ps.geometry.Wing(# Give the wing a name, this defaults to "Untitled Wing".
name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Declare that this wing is symmetric. This means that the geometry will
# be reflected across plane of this wing's root wing cross section. Note
# that the geometry coordinates are defined as such: If you were riding
@@ -58,20 +49,16 @@
# in the chordwise direction, near the leading and trailing edges. The
# other option is "uniform". I set this value to "uniform" here as it
# increase the accuracy of unsteady solvers.
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
+ num_chordwise_panels=6, chordwise_spacing="uniform",
# Every wing has a list of wing cross sections. In order for the geometry
# output to be sensible, each wing must have at least two wing cross
# sections.
- wing_cross_sections=[
- # Create a new wing cross section object.
+ wing_cross_sections=[# Create a new wing cross section object.
ps.geometry.WingCrossSection(
# Define the location of the leading edge of the wing cross
# section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Define the twist of the wing cross section in degrees. This is
# equivalent to incidence angle of cross section. The twist is
# about the leading edge. Note that the twist is only stable up
@@ -100,12 +87,10 @@
# which makes the panels relatively finer, in the spanwise
# direction, near the cross section ends. The other option is
# "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
+ num_spanwise_panels=8, spanwise_spacing="cosine",
# Set the chord of this cross section to be 1.75 meters. This
# value defaults to 1.0 meter.
- chord=1.75,
- # Every wing cross section has an airfoil object.
+ chord=1.75, # Every wing cross section has an airfoil object.
airfoil=ps.geometry.Airfoil(
# Give the airfoil a name. This defaults to "Untitled
# Airfoil". This name should correspond to a name in the
@@ -128,59 +113,24 @@
repanel=True,
# This is number of points to use if repaneling the airfoil.
# It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
+ n_points_per_side=400, ), ),
# Define the next wing cross section. From here on out,
# the declarations will not be as commented as the previous. See the
# above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- z_le=1.0,
- chord=1.5,
- twist=5.0,
- # Give this wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, z_le=1.0, chord=1.5,
+ twist=5.0, # Give this wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="V-Tail",
- x_le=6.75,
- z_le=0.25,
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
- symmetric=True,
+ ps.geometry.Wing(name="V-Tail", x_le=6.75, z_le=0.25, num_chordwise_panels=6,
+ chordwise_spacing="uniform", symmetric=True,
# Define this wing's root wing cross section.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- z_le=1.0,
- chord=1.0,
- twist=-5.0,
- # Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, z_le=1.0, chord=1.0,
+ twist=-5.0, # Give the tip wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the main wing's root wing cross section's movement. Cross sections can
# move in three ways: sweeping, pitching, and heaving. Sweeping is defined as the
@@ -220,39 +170,33 @@
heaving_period=0.0,
# Define the time step spacing of the heaving. This is "sine" by default. The
# options are "sine" and "uniform".
- heaving_spacing="sine",
-)
+ heaving_spacing="sine", )
# Define the main wing's tip wing cross section's movement. As the example has static
# geometry, the movement attributes can be excluded, and the default values will
# suffice.
main_wing_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1],
-)
+ base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1], )
# Define the v-tail's root wing cross section's movement. As the example has static
# geometry, the movement attributes can be excluded, and the default values will
# suffice.
v_tail_root_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0], )
# Define the v-tail's tip wing cross section's movement. As the example has static
# geometry, the movement attributes can be excluded, and the default values will
# suffice.
v_tail_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1], )
# Now define the main wing's movement. In addition to their wing cross sections'
# relative movements, wings' leading edge positions can move as well.
main_wing_movement = ps.movement.WingMovement( # Define the base wing object.
base_wing=example_airplane.wings[0],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- main_wing_root_wing_cross_section_movement,
- main_wing_tip_wing_cross_section_movement,
- ],
+ wing_cross_sections_movements=[main_wing_root_wing_cross_section_movement,
+ main_wing_tip_wing_cross_section_movement, ],
# Define the amplitude of the leading edge's change in x position. This value is
# in meters. This is set to 0.0 meters, which is the default value.
x_le_amplitude=0.0,
@@ -279,8 +223,7 @@
z_le_period=0.0,
# Define the time step spacing of the leading edge's change in z position. This
# is "sine" by default. The options are "sine" and "uniform".
- z_le_spacing="sine",
-)
+ z_le_spacing="sine", )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -289,15 +232,11 @@
del main_wing_tip_wing_cross_section_movement
# Make the v-tail's wing movement object.
-v_tail_movement = ps.movement.WingMovement(
- # Define the base wing object.
+v_tail_movement = ps.movement.WingMovement(# Define the base wing object.
base_wing=example_airplane.wings[1],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- v_tail_root_wing_cross_section_movement,
- v_tail_tip_wing_cross_section_movement,
- ],
-)
+ wing_cross_sections_movements=[v_tail_root_wing_cross_section_movement,
+ v_tail_tip_wing_cross_section_movement, ], )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -307,10 +246,8 @@
# Now define the airplane's movement object. In addition to their wing's and wing
# cross sections' relative movements, airplane's reference positions can move as well.
-airplane_movement = ps.movement.AirplaneMovement(
- # Define the base airplane object.
- base_airplane=example_airplane,
- # Add the list of wing movement objects.
+airplane_movement = ps.movement.AirplaneMovement(# Define the base airplane object.
+ base_airplane=example_airplane, # Add the list of wing movement objects.
wing_movements=[main_wing_movement, v_tail_movement],
# Define the amplitude of the reference position's change in x position. This
# value is in meters. This is set to 0.0 meters, which is the default value.
@@ -338,8 +275,7 @@
z_ref_period=0.0,
# Define the time step spacing of the reference position's change in z position.
# This is "sine" by default. The options are "sine" and "uniform".
- z_ref_spacing="sine",
-)
+ z_ref_spacing="sine", )
# Delete the extraneous wing movement objects, as these are now contained within the
# airplane movement object.
@@ -364,8 +300,7 @@
# Define the kinematic viscosity of the air in meters squared per second. This
# defaults to 15.06e-6 meters squared per second, which corresponds to an air
# temperature of 20 degrees Celsius.
- nu=15.06e-6,
-)
+ nu=15.06e-6, )
# Define the operating point's movement. The operating point's velocity can change
# with respect to time.
@@ -380,15 +315,12 @@
velocity_period=0.0,
# Define the time step spacing of the velocity's change in time. This is "sine"
# by default. The options are "sine" and "uniform".
- velocity_spacing="sine",
-)
+ velocity_spacing="sine", )
# Define the movement object. This contains the airplane movement and the operating
# point movement.
-movement = ps.movement.Movement(
- # Add the airplane movement.
- airplane_movements=[airplane_movement],
- # Add the operating point movement.
+movement = ps.movement.Movement(# Add the airplane movement.
+ airplane_movements=[airplane_movement], # Add the operating point movement.
operating_point_movement=operating_point_movement,
# Leave the number of time steps and the length of each time step unspecified.
# The solver will automatically set the length of the time steps so that the wake
@@ -398,9 +330,7 @@
# lengths back from the main wing. If the geometry isn't static, the number of
# steps will be set such that three periods of the slowest movement oscillation
# complete.
- num_steps=None,
- delta_time=None,
-)
+ num_steps=None, delta_time=None, )
# Delete the extraneous airplane and operating point movement objects, as these are
# now contained within the movement object.
@@ -408,17 +338,15 @@
del operating_point_movement
# Define the unsteady example problem.
-example_problem = ps.problems.UnsteadyProblem(
- movement=movement,
-)
+example_problem = ps.problems.UnsteadyProblem(movement=movement, )
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
+example_solver = (ps.unsteady_ring_vortex_lattice_method
+.UnsteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- unsteady_problem=example_problem,
-)
+ unsteady_problem=example_problem, ))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver.
@@ -431,13 +359,11 @@
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
logging_level="Warning",
# Use a prescribed wake model. This is faster, but may be slightly less accurate.
- prescribed_wake=True,
-)
+ prescribed_wake=True, )
# Call the software's draw function on the solver. Press "q" to close the plotter
# after it draws the output.
-ps.output.draw(
- # Set the solver to the one we just ran.
+ps.output.draw(# Set the solver to the one we just ran.
solver=example_solver,
# Tell the draw function to color the aircraft's wing panels with the local lift
# coefficient. The valid arguments for this parameter are None, "induced drag",
@@ -451,14 +377,12 @@
show_wake_vortices=False,
# The the draw function to not save the drawing as an image file. This way,
# the drawing will still be displayed but not saved. This value defaults to false.
- save=False,
-)
+ save=False, )
# Call the software's animate function on the solver. This produces a GIF of the wake
# being shed. The GIF is saved in the same directory as this script. Press "q",
# after orienting the view, to begin the animation.
-ps.output.animate(
- # Set the unsteady solver to the one we just ran.
+ps.output.animate(# Set the unsteady solver to the one we just ran.
unsteady_solver=example_solver,
# Tell the animate function to color the aircraft's wing panels with the local
# lift coefficient. The valid arguments for this parameter are None, "induced drag",
@@ -470,22 +394,18 @@
# The the animate function to not save the animation as file. This way,
# the animation will still be displayed but not saved. This value defaults to
# false.
- save=False,
-)
+ save=False, )
# Call the software's plotting function on the solver. This produces graphs of the
# output forces and moments with respect to time.
-ps.output.plot_results_versus_time(
- # Set the unsteady solver to the one we just ran.
+ps.output.plot_results_versus_time(# Set the unsteady solver to the one we just ran.
unsteady_solver=example_solver,
# Set the show attribute to True, which is the default value. With this set to
# show, some IDEs (such as PyCharm in "Scientific Mode") will display the plots
# in a sidebar. Other IDEs may not display the plots, in which case you should
# set the save attribute to True, and open the files after they've been saved to
# the current directory.
- show=True,
- save=False,
-)
+ show=True, save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable.py b/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable.py
index ba91eda7..7bcba6e4 100644
--- a/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable.py
+++ b/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable.py
@@ -18,30 +18,22 @@
# program is in SI units. Note: these values are relative to the global
# coordinate system fixed front left corner of the first airplane's first wing's
# root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
+ x_ref=0.0, y_ref=0.0, z_ref=0.0,
# Give the reference dimensions of this aircraft. "s_ref" is the reference area
# in meters squared, "b_ref" is the reference span in meters, and "c_ref" is the
# reference chord in meters. I set these values to None, which is their default,
# so that they will be populated by the first wing object's calculated
# characteristics. Note that the reference area used in this program is the
# wetted area of the wing's mean-camberline surface.
- s_ref=None,
- b_ref=None,
- c_ref=None,
- # All airplane objects have a list of wings.
- wings=[
- # Create the first wing object in this airplane.
+ s_ref=None, b_ref=None, c_ref=None, # All airplane objects have a list of wings.
+ wings=[# Create the first wing object in this airplane.
ps.geometry.Wing( # Give the wing a name, this defaults to "Untitled Wing".
name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Declare that this wing is symmetric. This means that the geometry will
# be reflected across plane of this wing's root wing cross section. Note
# that the geometry coordinates are defined as such: If you were riding
@@ -57,20 +49,16 @@
# in the chordwise direction, near the leading and trailing edges. The
# other option is "uniform". I set this value to "uniform" here as it
# increase the accuracy of unsteady solvers.
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
+ num_chordwise_panels=6, chordwise_spacing="uniform",
# Every wing has a list of wing cross sections. In order for the geometry
# output to be sensible, each wing must have at least two wing cross
# sections.
- wing_cross_sections=[
- # Create a new wing cross section object.
+ wing_cross_sections=[# Create a new wing cross section object.
ps.geometry.WingCrossSection(
# Define the location of the leading edge of the wing cross
# section relative to the wing's leading edge. These values all
# default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
+ x_le=0.0, y_le=0.0, z_le=0.0,
# Define the twist of the wing cross section in degrees. This is
# equivalent to incidence angle of cross section. The twist is
# about the leading edge. Note that the twist is only stable up
@@ -99,12 +87,10 @@
# which makes the panels relatively finer, in the spanwise
# direction, near the cross section ends. The other option is
# "uniform".
- num_spanwise_panels=8,
- spanwise_spacing="cosine",
+ num_spanwise_panels=8, spanwise_spacing="cosine",
# Set the chord of this cross section to be 1.75 meters. This
# value defaults to 1.0 meter.
- chord=1.75,
- # Every wing cross section has an airfoil object.
+ chord=1.75, # Every wing cross section has an airfoil object.
airfoil=ps.geometry.Airfoil(
# Give the airfoil a name. This defaults to "Untitled
# Airfoil". This name should correspond to a name in the
@@ -127,59 +113,24 @@
repanel=True,
# This is number of points to use if repaneling the airfoil.
# It is ignored if the repanel is False. The default is 400.
- n_points_per_side=400,
- ),
- ),
+ n_points_per_side=400, ), ),
# Define the next wing cross section. From here on out,
# the declarations will not be as commented as the previous. See the
# above comments if you have questions.
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- z_le=1.0,
- chord=1.5,
- twist=5.0,
- # Give this wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca2412",
- ),
- ),
- ],
- ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, z_le=1.0, chord=1.5,
+ twist=5.0, # Give this wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca2412", ), ), ], ),
# Define the next wing.
- ps.geometry.Wing(
- name="V-Tail",
- x_le=6.75,
- z_le=0.25,
- num_chordwise_panels=6,
- chordwise_spacing="uniform",
- symmetric=True,
+ ps.geometry.Wing(name="V-Tail", x_le=6.75, z_le=0.25, num_chordwise_panels=6,
+ chordwise_spacing="uniform", symmetric=True,
# Define this wing's root wing cross section.
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- chord=1.5,
- # Give the root wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- twist=-5.0,
- ),
+ wing_cross_sections=[ps.geometry.WingCrossSection(chord=1.5,
+ # Give the root wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), twist=-5.0, ),
# Define the wing's tip wing cross section.
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=2.0,
- z_le=1.0,
- chord=1.0,
- twist=-5.0,
- # Give the tip wing cross section an airfoil.
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
-)
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=2.0, z_le=1.0, chord=1.0,
+ twist=-5.0, # Give the tip wing cross section an airfoil.
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the main wing's root wing cross section's movement. Cross sections can
# move in three ways: sweeping, pitching, and heaving. Sweeping is defined as the
@@ -219,44 +170,32 @@
heaving_period=0.0,
# Define the time step spacing of the heaving. This is "sine" by default. The
# options are "sine" and "uniform".
- heaving_spacing="sine",
-)
+ heaving_spacing="sine", )
# Define the main wing's tip wing cross section's movement.
main_wing_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
base_wing_cross_section=example_airplane.wings[0].wing_cross_sections[1],
- sweeping_amplitude=30.0,
- sweeping_period=1.0,
- sweeping_spacing="sine",
- pitching_amplitude=15.0,
- pitching_period=1.0,
- pitching_spacing="sine",
- heaving_amplitude=0.0,
- heaving_period=0.0,
- heaving_spacing="sine",
-)
+ sweeping_amplitude=30.0, sweeping_period=1.0, sweeping_spacing="sine",
+ pitching_amplitude=15.0, pitching_period=1.0, pitching_spacing="sine",
+ heaving_amplitude=0.0, heaving_period=0.0, heaving_spacing="sine", )
# Define the v-tail's root wing cross section's movement. This wing will be static,
# so the movement attributes can be excluded, and the default values will suffice.
v_tail_root_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[0], )
# Define the v-tail's root wing cross section's movement. This wing will be static,
# so the movement attributes can be excluded, and the default values will suffice.
v_tail_tip_wing_cross_section_movement = ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1],
-)
+ base_wing_cross_section=example_airplane.wings[1].wing_cross_sections[1], )
# Now define the main wing's movement. In addition to their wing cross sections'
# relative movements, wings' leading edge positions can move as well.
main_wing_movement = ps.movement.WingMovement( # Define the base wing object.
base_wing=example_airplane.wings[0],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- main_wing_root_wing_cross_section_movement,
- main_wing_tip_wing_cross_section_movement,
- ],
+ wing_cross_sections_movements=[main_wing_root_wing_cross_section_movement,
+ main_wing_tip_wing_cross_section_movement, ],
# Define the amplitude of the leading edge's change in x position. This value is
# in meters. This is set to 0.0 meters, which is the default value.
x_le_amplitude=0.0,
@@ -283,8 +222,7 @@
z_le_period=0.0,
# Define the time step spacing of the leading edge's change in z position. This
# is "sine" by default. The options are "sine" and "uniform".
- z_le_spacing="sine",
-)
+ z_le_spacing="sine", )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -293,15 +231,11 @@
del main_wing_tip_wing_cross_section_movement
# Make the v-tail's wing movement object.
-v_tail_movement = ps.movement.WingMovement(
- # Define the base wing object.
+v_tail_movement = ps.movement.WingMovement(# Define the base wing object.
base_wing=example_airplane.wings[1],
# Add the list of wing cross section movement objects.
- wing_cross_sections_movements=[
- v_tail_root_wing_cross_section_movement,
- v_tail_tip_wing_cross_section_movement,
- ],
-)
+ wing_cross_sections_movements=[v_tail_root_wing_cross_section_movement,
+ v_tail_tip_wing_cross_section_movement, ], )
# Delete the extraneous wing cross section movement objects, as these are now
# contained within the wing movement object. This is unnecessary, but it can make
@@ -311,10 +245,8 @@
# Now define the airplane's movement object. In addition to their wing's and wing
# cross sections' relative movements, airplane's reference positions can move as well.
-airplane_movement = ps.movement.AirplaneMovement(
- # Define the base airplane object.
- base_airplane=example_airplane,
- # Add the list of wing movement objects.
+airplane_movement = ps.movement.AirplaneMovement(# Define the base airplane object.
+ base_airplane=example_airplane, # Add the list of wing movement objects.
wing_movements=[main_wing_movement, v_tail_movement],
# Define the amplitude of the reference position's change in x position. This
# value is in meters. This is set to 0.0 meters, which is the default value.
@@ -342,8 +274,7 @@
z_ref_period=0.0,
# Define the time step spacing of the reference position's change in z position.
# This is "sine" by default. The options are "sine" and "uniform".
- z_ref_spacing="sine",
-)
+ z_ref_spacing="sine", )
# Delete the extraneous wing movement objects, as these are now contained within the
# airplane movement object.
@@ -368,8 +299,7 @@
# Define the kinematic viscosity of the air in meters squared per second. This
# defaults to 15.06e-6 meters squared per second, which corresponds to an air
# temperature of 20 degrees Celsius.
- nu=15.06e-6,
-)
+ nu=15.06e-6, )
# Define the operating point's movement. The operating point's velocity can change
# with respect to time.
@@ -384,15 +314,12 @@
velocity_period=0.0,
# Define the time step spacing of the velocity's change in time. This is "sine"
# by default. The options are "sine" and "uniform".
- velocity_spacing="sine",
-)
+ velocity_spacing="sine", )
# Define the movement object. This contains the airplane movement and the operating
# point movement.
-movement = ps.movement.Movement(
- # Add the airplane movement.
- airplane_movements=[airplane_movement],
- # Add the operating point movement.
+movement = ps.movement.Movement(# Add the airplane movement.
+ airplane_movements=[airplane_movement], # Add the operating point movement.
operating_point_movement=operating_point_movement,
# Leave the number of time steps and the length of each time step unspecified.
# The solver will automatically set the length of the time steps so that the wake
@@ -402,9 +329,7 @@
# lengths back from the main wing. If the geometry isn't static, the number of
# steps will be set such that three periods of the slowest movement oscillation
# complete.
- num_steps=None,
- delta_time=None,
-)
+ num_steps=None, delta_time=None, )
# Delete the extraneous airplane and operating point movement objects, as these are
# now contained within the movement object.
@@ -412,17 +337,15 @@
del operating_point_movement
# Define the unsteady example problem.
-example_problem = ps.problems.UnsteadyProblem(
- movement=movement,
-)
+example_problem = ps.problems.UnsteadyProblem(movement=movement, )
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
-example_solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
+example_solver = (ps.unsteady_ring_vortex_lattice_method
+.UnsteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- unsteady_problem=example_problem,
-)
+ unsteady_problem=example_problem, ))
# Delete the extraneous pointer to the problem as it is now contained within the
# solver.
@@ -435,14 +358,12 @@
# "Debug", "Info", "Warning", "Error", "Critical". The default value is "Warning".
logging_level="Warning",
# Use a prescribed wake model. This is faster, but may be slightly less accurate.
- prescribed_wake=True,
-)
+ prescribed_wake=True, )
# Call the software's animate function on the solver. This produces a GIF of the wake
# being shed. The GIF is saved in the same directory as this script. Press "q",
# after orienting the view, to begin the animation.
-ps.output.animate(
- # Set the unsteady solver to the one we just ran.
+ps.output.animate(# Set the unsteady solver to the one we just ran.
unsteady_solver=example_solver,
# Tell the animate function to color the aircraft's wing panels with the local
# lift coefficient. The valid arguments for this parameter are None, "induced drag",
@@ -454,8 +375,7 @@
# The the animate function to not save the animation as file. This way,
# the animation will still be displayed but not saved. This value defaults to
# false.
- save=False,
-)
+ save=False, )
# Compare the output you see with the expected outputs saved in the "docs/examples
# expected output" directory.
diff --git a/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable_formation.py b/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable_formation.py
index 30bf280f..5a0639da 100644
--- a/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable_formation.py
+++ b/pterasoftware/models/unsteady_ring_vortex_lattice_method_solver_variable_formation.py
@@ -16,250 +16,138 @@ def runSolver(self):
y_spacing = 13
# Create the lead airplane object.
- lead_airplane = ps.geometry.Airplane(
- name="Lead Airplane",
+ lead_airplane = ps.geometry.Airplane(name="Lead Airplane",
# Specify the location of the lead airplane's center of gravity. This is the
- # point around about which the solver will calculate the moments on the airplane.
+ # point around about which the solver will calculate the moments on the
+ # airplane.
# These three values default to 0.0 meters. Note: these values are relative to
# the global coordinate system fixed front left corner of the first airplane's
# first wing's root wing cross section.
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
- # Define the location of the leading edge of the wing relative to the
- # global coordinate system fixed front left corner of the first
- # airplane's first wing's root wing cross section.
- x_le=0.0,
- y_le=0.0,
- # Declare that this wing is symmetric. This means that the geometry will
- # be reflected across plane of this wing's root wing cross section. Note
- # that the geometry coordinates are defined as such: If you were riding
- # in the airplane, the positive x direction would point behind you,
- # the positive y direction would point out of your right wing, and the
- # positive z direction would point upwards, out of your chair. These
- # directions form a right-handed coordinate system. The default value of
- # "symmetric" is false.
- symmetric=True,
- # Define the chordwise spacing of the wing panels to be "uniform" as this
- # increase the accuracy of unsteady solvers.
- chordwise_spacing="uniform",
- num_chordwise_panels=4,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- # Define the location of the leading edge of the wing cross
- # section relative to the wing's leading edge. These values all
- # default to 0.0 meters.
- x_le=0.0,
- y_le=0.0,
- # Assign the twist of this wing cross section. Note: when
- # assigning angles of attack to multiple airplanes, it is better
- # to set the operating point's angle of attack to zero, and then
- # use offset the twist values of all the wing cross sections to
- # simulate each aircraft having an angle of attack.
- twist=5.0,
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
- )
+ x_ref=0.0, y_ref=0.0, z_ref=0.0, wings=[ps.geometry.Wing(name="Main Wing",
+ # Define the location of the leading edge of the wing relative to the
+ # global coordinate system fixed front left corner of the first
+ # airplane's first wing's root wing cross section.
+ x_le=0.0, y_le=0.0,
+ # Declare that this wing is symmetric. This means that the geometry will
+ # be reflected across plane of this wing's root wing cross section. Note
+ # that the geometry coordinates are defined as such: If you were riding
+ # in the airplane, the positive x direction would point behind you,
+ # the positive y direction would point out of your right wing, and the
+ # positive z direction would point upwards, out of your chair. These
+ # directions form a right-handed coordinate system. The default value of
+ # "symmetric" is false.
+ symmetric=True,
+ # Define the chordwise spacing of the wing panels to be "uniform" as this
+ # increase the accuracy of unsteady solvers.
+ chordwise_spacing="uniform", num_chordwise_panels=4,
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ # Define the location of the leading edge of the wing cross
+ # section relative to the wing's leading edge. These values all
+ # default to 0.0 meters.
+ x_le=0.0, y_le=0.0,
+ # Assign the twist of this wing cross section. Note: when
+ # assigning angles of attack to multiple airplanes, it is better
+ # to set the operating point's angle of attack to zero, and then
+ # use offset the twist values of all the wing cross sections to
+ # simulate each aircraft having an angle of attack.
+ twist=5.0, chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, chord=1.5,
+ twist=5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ), ], ), ], )
# Now define the lead airplane's movement object.
lead_airplane_movement = ps.movement.AirplaneMovement(
base_airplane=lead_airplane,
- wing_movements=[
- # Define the main wing's movement.
- ps.movement.WingMovement(
- base_wing=lead_airplane.wings[0],
+ wing_movements=[# Define the main wing's movement.
+ ps.movement.WingMovement(base_wing=lead_airplane.wings[0],
# Add the list of wing cross section movement objects.
wing_cross_sections_movements=[
# Define the root wing cross section's movement object.
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=lead_airplane.wings[
- 0
- ].wing_cross_sections[0],
- ),
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ lead_airplane.wings[0].wing_cross_sections[0], ),
# Define the tip wing cross section's movement object.
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=lead_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_amplitude=15.0,
- sweeping_period=1.5,
- sweeping_spacing="sine",
- ),
- ],
- ),
- ],
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ lead_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=15.0, sweeping_period=1.5,
+ sweeping_spacing="sine", ), ], ), ], )
# Create the trailing right airplane object.
- right_airplane = ps.geometry.Airplane(
- name="Right Airplane",
+ right_airplane = ps.geometry.Airplane(name="Right Airplane",
# Specify the location of the right airplane's center of gravity. This is the
# point around about which the solver will calculate the moments on the airplane.
# These three values default to 0.0 meters. Note: these values are relative to
# the global coordinate system fixed front left corner of the first airplane's
# first wing's root wing cross section.
- x_ref=x_spacing,
- y_ref=y_spacing,
- z_ref=0.0,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
+ x_ref=x_spacing, y_ref=y_spacing, z_ref=0.0, wings=[
+ ps.geometry.Wing(name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section.
- x_le=x_spacing,
- y_le=y_spacing,
- symmetric=True,
- chordwise_spacing="uniform",
- num_chordwise_panels=4,
+ x_le=x_spacing, y_le=y_spacing, symmetric=True,
+ chordwise_spacing="uniform", num_chordwise_panels=4,
wing_cross_sections=[
- ps.geometry.WingCrossSection(
- twist=5.0,
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
- )
+ ps.geometry.WingCrossSection(twist=5.0, chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, chord=1.5,
+ twist=5.0, airfoil=ps.geometry.Airfoil(
+ name="naca0012", ), ), ], ), ], )
# Now define the trailing right airplane's movement object.
right_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=right_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=right_airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=right_airplane.wings[
- 0
- ].wing_cross_sections[0],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=right_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_amplitude=15.0,
- sweeping_period=1.5,
- sweeping_spacing="sine",
- ),
- ],
- ),
- ],
- )
+ base_airplane=right_airplane, wing_movements=[
+ ps.movement.WingMovement(base_wing=right_airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=
+ right_airplane.wings[0].wing_cross_sections[0], ),
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ right_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=15.0, sweeping_period=1.5,
+ sweeping_spacing="sine", ), ], ), ], )
# Create the trailing left airplane object.
- left_airplane = ps.geometry.Airplane(
- name="Left Airplane",
+ left_airplane = ps.geometry.Airplane(name="Left Airplane",
# Specify the location of the left airplane's center of gravity. This is the
# point around about which the solver will calculate the moments on the airplane.
# These three values default to 0.0 meters. Note: these values are relative to
# the global coordinate system fixed front left corner of the first airplane's
# first wing's root wing cross section.
- x_ref=x_spacing,
- y_ref=-y_spacing,
- z_ref=0.0,
- wings=[
- ps.geometry.Wing(
- name="Main Wing",
+ x_ref=x_spacing, y_ref=-y_spacing, z_ref=0.0, wings=[
+ ps.geometry.Wing(name="Main Wing",
# Define the location of the leading edge of the wing relative to the
# global coordinate system fixed front left corner of the first
# airplane's first wing's root wing cross section.
- x_le=x_spacing,
- y_le=-y_spacing,
- symmetric=True,
- chordwise_spacing="uniform",
- num_chordwise_panels=4,
+ x_le=x_spacing, y_le=-y_spacing, symmetric=True,
+ chordwise_spacing="uniform", num_chordwise_panels=4,
wing_cross_sections=[
- ps.geometry.WingCrossSection(
- twist=5.0,
- chord=1.75,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ps.geometry.WingCrossSection(
- x_le=0.75,
- y_le=6.0,
- chord=1.5,
- twist=5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0012",
- ),
- ),
- ],
- ),
- ],
- )
+ ps.geometry.WingCrossSection(twist=5.0, chord=1.75,
+ airfoil=ps.geometry.Airfoil(name="naca0012", ), ),
+ ps.geometry.WingCrossSection(x_le=0.75, y_le=6.0, chord=1.5,
+ twist=5.0, airfoil=ps.geometry.Airfoil(
+ name="naca0012", ), ), ], ), ], )
# Now define the trailing left airplane's movement object.
left_airplane_movement = ps.movement.AirplaneMovement(
- base_airplane=left_airplane,
- wing_movements=[
- ps.movement.WingMovement(
- base_wing=left_airplane.wings[0],
- wing_cross_sections_movements=[
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=left_airplane.wings[
- 0
- ].wing_cross_sections[0],
- ),
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=left_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_amplitude=15.0,
- sweeping_period=1.5,
- sweeping_spacing="sine",
- ),
- ],
- ),
- ],
- )
+ base_airplane=left_airplane, wing_movements=[
+ ps.movement.WingMovement(base_wing=left_airplane.wings[0],
+ wing_cross_sections_movements=[ps.movement.WingCrossSectionMovement(
+ base_wing_cross_section=
+ left_airplane.wings[0].wing_cross_sections[0], ),
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ left_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=15.0, sweeping_period=1.5,
+ sweeping_spacing="sine", ), ], ), ], )
# Define a new operating point object. This defines the state at which all the
# airplanes objects are operating. Note: when assigning angles of attack to multiple
# airplanes, it is better to set the operating point's angle of attack to zero,
# and then use offset the twist values of all the wing cross sections to simulate
# each aircraft having an angle of attack.
- operating_point = ps.operating_point.OperatingPoint(
- velocity=10.0,
- alpha=0.0,
- )
+ operating_point = ps.operating_point.OperatingPoint(velocity=10.0, alpha=0.0, )
# Define the operating point's movement.
operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=operating_point,
- )
+ base_operating_point=operating_point, )
# Delete the extraneous airplane and operating point objects, as these are now
# contained within their respective movement objects.
@@ -271,14 +159,9 @@ def runSolver(self):
# Define the movement object. This contains each airplane's movement and the operating
# point movement.
movement = ps.movement.Movement(
- airplane_movements=[
- lead_airplane_movement,
- right_airplane_movement,
- left_airplane_movement,
- ],
- operating_point_movement=operating_point_movement,
- num_cycles=2,
- )
+ airplane_movements=[lead_airplane_movement, right_airplane_movement,
+ left_airplane_movement, ],
+ operating_point_movement=operating_point_movement, num_cycles=2, )
# Delete the extraneous airplane and operating point movement objects, as these are
# now contained within the movement object.
@@ -288,39 +171,30 @@ def runSolver(self):
del operating_point_movement
# Define the unsteady example problem.
- problem = ps.problems.UnsteadyProblem(
- movement=movement,
- )
+ problem = ps.problems.UnsteadyProblem(movement=movement, )
# Define a new solver. The available solver objects are the steady horseshoe vortex
# lattice method solver, the steady ring vortex lattice method solver, and the
# unsteady ring vortex lattice method solver.
solver = ps.unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
# Solvers just take in one attribute: the problem they are going to solve.
- unsteady_problem=problem,
- )
+ unsteady_problem=problem, )
# Delete the extraneous pointer to the problem as it is now contained within the
# solver.
del problem
# Run the example solver.
- solver.run(
- prescribed_wake=False,
- )
+ solver.run(prescribed_wake=False, )
# Call the software's animate function on the solver. This produces a GIF of the wake
# being shed. The GIF is saved in the same directory as this script. Press "q",
# after orienting the view, to begin the animation.
- ps.output.animate(
- unsteady_solver=solver,
- scalar_type="lift",
+ ps.output.animate(unsteady_solver=solver, scalar_type="lift",
show_wake_vortices=True,
# The the animate function to not save the animation as file. This way,
# the animation will still be displayed but not saved. This value defaults to
# false.
- save=False,
- )
+ save=False, )
- # Compare the output you see with the expected outputs saved in the "docs/examples
- # expected output" directory.
+ # Compare the output you see with the expected outputs saved in the "docs/examples # expected output" directory.
diff --git a/pterasoftware/movement.py b/pterasoftware/movement.py
index 8ba9b6e6..d0043939 100644
--- a/pterasoftware/movement.py
+++ b/pterasoftware/movement.py
@@ -57,15 +57,8 @@ class Movement:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- airplane_movements,
- operating_point_movement,
- num_steps=None,
- num_cycles=None,
- num_chords=None,
- delta_time=None,
- ):
+ def __init__(self, airplane_movements, operating_point_movement, num_steps=None,
+ num_cycles=None, num_chords=None, delta_time=None, ):
"""This is the initialization method.
:param airplane_movements: list of AirplaneMovement objects
@@ -112,8 +105,7 @@ def __init__(
if num_steps is not None or self.get_max_period() == 0:
raise Exception(
"Only specify the number of cycles if you haven't specified the "
- "number of steps and the movement isn't static!"
- )
+ "number of steps and the movement isn't static!")
self.num_cycles = num_cycles
else:
self.num_cycles = None
@@ -124,8 +116,7 @@ def __init__(
if num_steps is not None or self.get_max_period() != 0:
raise Exception(
"Only specify the number of chords if you haven't specified the "
- "number of steps and the movement is static!"
- )
+ "number of steps and the movement is static!")
self.num_chords = num_chords
else:
self.num_chords = None
@@ -135,17 +126,15 @@ def __init__(
if delta_time is None:
delta_times = []
for airplane_movement in self.airplane_movements:
-
# For a given airplane object, the ideal time step length is that
# which sheds ring vortices off the main wing that have roughly the
# same chord length as the panels on the main wing. This is based on
# the base airplane's reference chord length, its main wing's number
# of chordwise panels, and its base operating point's velocity.
- delta_times.append(
- airplane_movement.base_airplane.c_ref
- / airplane_movement.base_airplane.wings[0].num_chordwise_panels
- / operating_point_movement.base_operating_point.velocity
- )
+ delta_times.append(airplane_movement.base_airplane.c_ref /
+ airplane_movement.base_airplane.wings[
+ 0].num_chordwise_panels /
+ operating_point_movement.base_operating_point.velocity)
# Set the delta time to be the average of the airplanes' ideal delta times.
delta_time = sum(delta_times) / len(delta_times)
@@ -173,9 +162,7 @@ def __init__(
# that the wake extends back by some number of reference chord lengths.
wake_length = self.num_chords * max_c_ref
panel_length = (
- delta_time
- * self.operating_point_movement.base_operating_point.velocity
- )
+ delta_time * self.operating_point_movement.base_operating_point.velocity)
num_steps = math.ceil(wake_length / panel_length)
else:
@@ -197,16 +184,13 @@ def __init__(
self.airplanes = []
for airplane_movement in self.airplane_movements:
self.airplanes.append(
- airplane_movement.generate_airplanes(
- num_steps=self.num_steps, delta_time=self.delta_time
- )
- )
+ airplane_movement.generate_airplanes(num_steps=self.num_steps,
+ delta_time=self.delta_time))
# Generate a lists of operating point objects that are the steps through the
# movement of this problem's operating point.
self.operating_points = operating_point_movement.generate_operating_points(
- num_steps=self.num_steps, delta_time=self.delta_time
- )
+ num_steps=self.num_steps, delta_time=self.delta_time)
def get_max_period(self):
"""This method returns the longest period of this movement object's sub-
@@ -224,10 +208,8 @@ def get_max_period(self):
# The global max period is the maximum of the max airplane period and the max
# operating point period.
- return max(
- max_airplane_period,
- self.operating_point_movement.get_max_period(),
- )
+ return max(max_airplane_period,
+ self.operating_point_movement.get_max_period(), )
class AirplaneMovement:
@@ -247,20 +229,10 @@ class AirplaneMovement:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- base_airplane,
- wing_movements,
- x_ref_amplitude=0.0,
- x_ref_period=0.0,
- x_ref_spacing="sine",
- y_ref_amplitude=0.0,
- y_ref_period=0.0,
- y_ref_spacing="sine",
- z_ref_amplitude=0.0,
- z_ref_period=0.0,
- z_ref_spacing="sine",
- ):
+ def __init__(self, base_airplane, wing_movements, x_ref_amplitude=0.0,
+ x_ref_period=0.0, x_ref_spacing="sine", y_ref_amplitude=0.0,
+ y_ref_period=0.0, y_ref_spacing="sine", z_ref_amplitude=0.0,
+ z_ref_period=0.0, z_ref_spacing="sine", ):
"""This is the initialization method.
:param base_airplane: Airplane
@@ -334,23 +306,15 @@ def generate_airplanes(self, num_steps=10, delta_time=0.1):
if self.x_ref_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- x_ref_list = oscillating_sinspace(
- amplitude=self.x_ref_amplitude,
- period=self.x_ref_period,
- base_value=self.x_ref_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ x_ref_list = oscillating_sinspace(amplitude=self.x_ref_amplitude,
+ period=self.x_ref_period, base_value=self.x_ref_base,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.x_ref_spacing == "uniform":
# Create an array of points with a uniform spacing.
- x_ref_list = oscillating_linspace(
- amplitude=self.x_ref_amplitude,
- period=self.x_ref_period,
- base_value=self.x_ref_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ x_ref_list = oscillating_linspace(amplitude=self.x_ref_amplitude,
+ period=self.x_ref_period, base_value=self.x_ref_base,
+ num_steps=num_steps, delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -360,23 +324,15 @@ def generate_airplanes(self, num_steps=10, delta_time=0.1):
if self.y_ref_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- y_ref_list = oscillating_sinspace(
- amplitude=self.y_ref_amplitude,
- period=self.y_ref_period,
- base_value=self.y_ref_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ y_ref_list = oscillating_sinspace(amplitude=self.y_ref_amplitude,
+ period=self.y_ref_period, base_value=self.y_ref_base,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.y_ref_spacing == "uniform":
# Create an array of points with a uniform spacing.
- y_ref_list = oscillating_linspace(
- amplitude=self.y_ref_amplitude,
- period=self.y_ref_period,
- base_value=self.y_ref_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ y_ref_list = oscillating_linspace(amplitude=self.y_ref_amplitude,
+ period=self.y_ref_period, base_value=self.y_ref_base,
+ num_steps=num_steps, delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -386,23 +342,15 @@ def generate_airplanes(self, num_steps=10, delta_time=0.1):
if self.z_ref_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- z_ref_list = oscillating_sinspace(
- amplitude=self.z_ref_amplitude,
- period=self.z_ref_period,
- base_value=self.z_ref_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ z_ref_list = oscillating_sinspace(amplitude=self.z_ref_amplitude,
+ period=self.z_ref_period, base_value=self.z_ref_base,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.z_ref_spacing == "uniform":
# Create an array of points with a uniform spacing.
- z_ref_list = oscillating_linspace(
- amplitude=self.z_ref_amplitude,
- period=self.z_ref_period,
- base_value=self.z_ref_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ z_ref_list = oscillating_linspace(amplitude=self.z_ref_amplitude,
+ period=self.z_ref_period, base_value=self.z_ref_base,
+ num_steps=num_steps, delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -414,11 +362,10 @@ def generate_airplanes(self, num_steps=10, delta_time=0.1):
# Iterate through the wing movement locations.
for wing_movement_location, wing_movement in enumerate(self.wing_movements):
-
# Generate this wing's vector of other wing's based on its movement.
this_wings_list_of_wings = np.array(
- wing_movement.generate_wings(num_steps=num_steps, delta_time=delta_time)
- )
+ wing_movement.generate_wings(num_steps=num_steps,
+ delta_time=delta_time))
# Add this vector the airplane's array of wing objects.
wings[wing_movement_location, :] = this_wings_list_of_wings
@@ -438,9 +385,8 @@ def generate_airplanes(self, num_steps=10, delta_time=0.1):
these_wings = wings[:, step]
# Make a new airplane object for this time step.
- this_airplane = geometry.Airplane(
- name=name, x_ref=x_ref, y_ref=y_ref, z_ref=z_ref, wings=these_wings
- )
+ this_airplane = geometry.Airplane(name=name, x_ref=x_ref, y_ref=y_ref,
+ z_ref=z_ref, wings=these_wings)
# Add this new object to the list of airplanes.
airplanes.append(this_airplane)
@@ -461,12 +407,8 @@ def get_max_period(self):
wing_movement_max_periods.append(wing_movement.get_max_period())
max_wing_movement_period = max(wing_movement_max_periods)
- max_period = max(
- max_wing_movement_period,
- self.x_ref_period,
- self.y_ref_period,
- self.z_ref_period,
- )
+ max_period = max(max_wing_movement_period, self.x_ref_period, self.y_ref_period,
+ self.z_ref_period, )
return max_period
@@ -488,20 +430,10 @@ class WingMovement:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- base_wing,
- wing_cross_sections_movements,
- x_le_amplitude=0.0,
- x_le_period=0.0,
- x_le_spacing="sine",
- y_le_amplitude=0.0,
- y_le_period=0.0,
- y_le_spacing="sine",
- z_le_amplitude=0.0,
- z_le_period=0.0,
- z_le_spacing="sine",
- ):
+ def __init__(self, base_wing, wing_cross_sections_movements, x_le_amplitude=0.0,
+ x_le_period=0.0, x_le_spacing="sine", y_le_amplitude=0.0, y_le_period=0.0,
+ y_le_spacing="sine", z_le_amplitude=0.0, z_le_period=0.0,
+ z_le_spacing="sine", ):
"""This is the initialization method.
:param base_wing: Wing
@@ -570,23 +502,15 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
if self.x_le_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- x_le_list = oscillating_sinspace(
- amplitude=self.x_le_amplitude,
- period=self.x_le_period,
- base_value=self.x_le_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ x_le_list = oscillating_sinspace(amplitude=self.x_le_amplitude,
+ period=self.x_le_period, base_value=self.x_le_base, num_steps=num_steps,
+ delta_time=delta_time, )
elif self.x_le_spacing == "uniform":
# Create an array of points with a uniform spacing.
- x_le_list = oscillating_linspace(
- amplitude=self.x_le_amplitude,
- period=self.x_le_period,
- base_value=self.x_le_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ x_le_list = oscillating_linspace(amplitude=self.x_le_amplitude,
+ period=self.x_le_period, base_value=self.x_le_base, num_steps=num_steps,
+ delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -596,23 +520,15 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
if self.y_le_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- y_le_list = oscillating_sinspace(
- amplitude=self.y_le_amplitude,
- period=self.y_le_period,
- base_value=self.y_le_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ y_le_list = oscillating_sinspace(amplitude=self.y_le_amplitude,
+ period=self.y_le_period, base_value=self.y_le_base, num_steps=num_steps,
+ delta_time=delta_time, )
elif self.y_le_spacing == "uniform":
# Create an array of points with a uniform spacing.
- y_le_list = oscillating_linspace(
- amplitude=self.y_le_amplitude,
- period=self.y_le_period,
- base_value=self.y_le_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ y_le_list = oscillating_linspace(amplitude=self.y_le_amplitude,
+ period=self.y_le_period, base_value=self.y_le_base, num_steps=num_steps,
+ delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -622,23 +538,15 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
if self.z_le_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- z_le_list = oscillating_sinspace(
- amplitude=self.z_le_amplitude,
- period=self.z_le_period,
- base_value=self.z_le_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ z_le_list = oscillating_sinspace(amplitude=self.z_le_amplitude,
+ period=self.z_le_period, base_value=self.z_le_base, num_steps=num_steps,
+ delta_time=delta_time, )
elif self.z_le_spacing == "uniform":
# Create an array of points with a uniform spacing.
- z_le_list = oscillating_linspace(
- amplitude=self.z_le_amplitude,
- period=self.z_le_period,
- base_value=self.z_le_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ z_le_list = oscillating_linspace(amplitude=self.z_le_amplitude,
+ period=self.z_le_period, base_value=self.z_le_base, num_steps=num_steps,
+ delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -647,18 +555,16 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
# Create an empty array that will hold each of the wing's wing cross
# section's vector of other wing cross section's based its movement.
wing_cross_sections = np.empty(
- (len(self.wing_cross_section_movements), num_steps), dtype=object
- )
+ (len(self.wing_cross_section_movements), num_steps), dtype=object)
# Initialize a variable to hold the inner wing cross section's list of wing
# cross sections for each time step.
last_wing_cross_section_time_histories = None
# Iterate through the wing cross section movement locations.
- for (
- wing_cross_section_movement_location,
- wing_cross_section_movement,
- ) in enumerate(self.wing_cross_section_movements):
+ for (wing_cross_section_movement_location,
+ wing_cross_section_movement,) in enumerate(
+ self.wing_cross_section_movements):
wing_is_vertical = False
# Check if this is this wing's root cross section.
@@ -666,17 +572,13 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
# Get the root cross section's sweeping and heaving attributes.
first_wing_cross_section_movement_sweeping_amplitude = (
- wing_cross_section_movement.sweeping_amplitude
- )
+ wing_cross_section_movement.sweeping_amplitude)
first_wing_cross_section_movement_sweeping_period = (
- wing_cross_section_movement.sweeping_period
- )
+ wing_cross_section_movement.sweeping_period)
first_wing_cross_section_movement_heaving_amplitude = (
- wing_cross_section_movement.heaving_amplitude
- )
+ wing_cross_section_movement.heaving_amplitude)
first_wing_cross_section_movement_heaving_period = (
- wing_cross_section_movement.heaving_period
- )
+ wing_cross_section_movement.heaving_period)
# Check that the root cross section is not sweeping or heaving.
assert first_wing_cross_section_movement_sweeping_amplitude == 0
@@ -696,8 +598,7 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
else:
this_base_wing_cross_section = (
- wing_cross_section_movement.base_wing_cross_section
- )
+ wing_cross_section_movement.base_wing_cross_section)
this_x_le = this_base_wing_cross_section.x_le
this_y_le = this_base_wing_cross_section.y_le
@@ -718,32 +619,22 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
# Find the span between this wing cross section and the inner wing
# cross section.
- wing_cross_section_span = np.sqrt(
- (this_x_le - last_x_les[0]) ** 2
- + (this_y_le - last_y_les[0]) ** 2
- + (this_z_le - last_z_les[0]) ** 2
- )
+ wing_cross_section_span = np.sqrt((this_x_le - last_x_les[0]) ** 2 + (
+ this_y_le - last_y_les[0]) ** 2 + (this_z_le - last_z_les[
+ 0]) ** 2)
if this_y_le != last_y_les[0]:
# Find the base sweep angle of this wing cross section compared
# to the inner wing cross section at the first time step.
- base_wing_cross_section_sweep = (
- np.arctan(
- (this_z_le - last_z_les[0]) / (this_y_le - last_y_les[0])
- )
- * 180
- / np.pi
- )
+ base_wing_cross_section_sweep = (np.arctan(
+ (this_z_le - last_z_les[0]) / (
+ this_y_le - last_y_les[0])) * 180 / np.pi)
# Find the base heave angle of this wing cross section compared
# to the inner wing cross section at the first time step.
- base_wing_cross_section_heave = (
- np.arctan(
- (this_x_le - last_x_les[0]) / (this_y_le - last_y_les[0])
- )
- * 180
- / np.pi
- )
+ base_wing_cross_section_heave = (np.arctan(
+ (this_x_le - last_x_les[0]) / (
+ this_y_le - last_y_les[0])) * 180 / np.pi)
else:
base_wing_cross_section_sweep = 0.0
base_wing_cross_section_heave = 0.0
@@ -753,28 +644,21 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
# each time step based on its movement.
this_wing_cross_sections_list_of_wing_cross_sections = np.array(
wing_cross_section_movement.generate_wing_cross_sections(
- num_steps=num_steps,
- delta_time=delta_time,
+ num_steps=num_steps, delta_time=delta_time,
cross_section_span=wing_cross_section_span,
cross_section_sweep=base_wing_cross_section_sweep,
cross_section_heave=base_wing_cross_section_heave,
- last_x_les=last_x_les,
- last_y_les=last_y_les,
- last_z_les=last_z_les,
- wing_is_vertical=wing_is_vertical,
- )
- )
+ last_x_les=last_x_les, last_y_les=last_y_les, last_z_les=last_z_les,
+ wing_is_vertical=wing_is_vertical, ))
# Add this vector the wing's array of wing cross section objects.
wing_cross_sections[wing_cross_section_movement_location, :] = (
- this_wing_cross_sections_list_of_wing_cross_sections
- )
+ this_wing_cross_sections_list_of_wing_cross_sections)
# Update the inner wing cross section's list of wing cross sections for
# each time step.
last_wing_cross_section_time_histories = (
- this_wing_cross_sections_list_of_wing_cross_sections
- )
+ this_wing_cross_sections_list_of_wing_cross_sections)
# Create an empty list of wings.
wings = []
@@ -787,7 +671,6 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
# Iterate through the time steps.
for step in range(num_steps):
-
# Get the reference position at this time step.
x_le = x_le_list[step]
y_le = y_le_list[step]
@@ -795,16 +678,10 @@ def generate_wings(self, num_steps=10, delta_time=0.1):
cross_sections = wing_cross_sections[:, step]
# Make a new wing object for this time step.
- this_wing = geometry.Wing(
- name=name,
- x_le=x_le,
- y_le=y_le,
- z_le=z_le,
- wing_cross_sections=cross_sections,
- symmetric=symmetric,
+ this_wing = geometry.Wing(name=name, x_le=x_le, y_le=y_le, z_le=z_le,
+ wing_cross_sections=cross_sections, symmetric=symmetric,
num_chordwise_panels=num_chordwise_panels,
- chordwise_spacing=chordwise_spacing,
- )
+ chordwise_spacing=chordwise_spacing, )
# Add this new object to the list of wings.
wings.append(this_wing)
@@ -823,18 +700,12 @@ def get_max_period(self):
wing_cross_section_movement_max_periods = []
for wing_cross_section_movement in self.wing_cross_section_movements:
wing_cross_section_movement_max_periods.append(
- wing_cross_section_movement.get_max_period()
- )
+ wing_cross_section_movement.get_max_period())
max_wing_cross_section_movement_period = max(
- wing_cross_section_movement_max_periods
- )
+ wing_cross_section_movement_max_periods)
- max_period = max(
- max_wing_cross_section_movement_period,
- self.x_le_period,
- self.y_le_period,
- self.z_le_period,
- )
+ max_period = max(max_wing_cross_section_movement_period, self.x_le_period,
+ self.y_le_period, self.z_le_period, )
return max_period
@@ -857,22 +728,11 @@ class WingCrossSectionMovement:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- base_wing_cross_section,
- sweeping_amplitude=0.0,
- sweeping_period=0.0,
- sweeping_spacing="sine",
- custom_sweep_function=None,
- pitching_amplitude=0.0,
- pitching_period=0.0,
- pitching_spacing="sine",
- custom_pitch_function=None,
- heaving_amplitude=0.0,
- heaving_period=0.0,
- heaving_spacing="sine",
- custom_heave_function=None,
- ):
+ def __init__(self, base_wing_cross_section, sweeping_amplitude=0.0,
+ sweeping_period=0.0, sweeping_spacing="sine", custom_sweep_function=None,
+ pitching_amplitude=0.0, pitching_period=0.0, pitching_spacing="sine",
+ custom_pitch_function=None, heaving_amplitude=0.0, heaving_period=0.0,
+ heaving_spacing="sine", custom_heave_function=None, ):
"""This is the initialization method.
:param base_wing_cross_section: WingCrossSection
@@ -967,21 +827,11 @@ def __init__(
self.z_le_base = self.base_wing_cross_section.z_le
self.twist_base = self.base_wing_cross_section.twist
self.control_surface_deflection_base = (
- self.base_wing_cross_section.control_surface_deflection
- )
-
- def generate_wing_cross_sections(
- self,
- num_steps=10,
- delta_time=0.1,
- last_x_les=None,
- last_y_les=None,
- last_z_les=None,
- wing_is_vertical=False,
- cross_section_span=0.0,
- cross_section_sweep=0.0,
- cross_section_heave=0.0,
- ):
+ self.base_wing_cross_section.control_surface_deflection)
+
+ def generate_wing_cross_sections(self, num_steps=10, delta_time=0.1,
+ last_x_les=None, last_y_les=None, last_z_les=None, wing_is_vertical=False,
+ cross_section_span=0.0, cross_section_sweep=0.0, cross_section_heave=0.0, ):
"""This method creates the wing cross section objects at each time
current_step, and groups them into a list.
@@ -1029,41 +879,28 @@ def generate_wing_cross_sections(
if self.sweeping_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- sweeping_list = oscillating_sinspace(
- amplitude=self.sweeping_amplitude,
- period=self.sweeping_period,
- base_value=cross_section_sweep,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ sweeping_list = oscillating_sinspace(amplitude=self.sweeping_amplitude,
+ period=self.sweeping_period, base_value=cross_section_sweep,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.sweeping_spacing == "uniform":
# Create an array of points with a uniform spacing.
- sweeping_list = oscillating_linspace(
- amplitude=self.sweeping_amplitude,
- period=self.sweeping_period,
- base_value=cross_section_sweep,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ sweeping_list = oscillating_linspace(amplitude=self.sweeping_amplitude,
+ period=self.sweeping_period, base_value=cross_section_sweep,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.sweeping_spacing == "custom":
# Raise an exception if the user did not declare a custom sweep function.
if self.custom_sweep_function is None:
raise Exception(
"You can't declare custom sweep spacing without providing a "
- "custom sweep function."
- )
+ "custom sweep function.")
# Create an array of points with a uniform spacing.
- sweeping_list = oscillating_customspace(
- amplitude=self.sweeping_amplitude,
- period=self.sweeping_period,
- base_value=cross_section_sweep,
- num_steps=num_steps,
- delta_time=delta_time,
- custom_function=self.custom_sweep_function,
- )
+ sweeping_list = oscillating_customspace(amplitude=self.sweeping_amplitude,
+ period=self.sweeping_period, base_value=cross_section_sweep,
+ num_steps=num_steps, delta_time=delta_time,
+ custom_function=self.custom_sweep_function, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -1073,41 +910,28 @@ def generate_wing_cross_sections(
if self.pitching_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- pitching_list = oscillating_sinspace(
- amplitude=self.pitching_amplitude,
- period=self.pitching_period,
- base_value=self.pitching_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ pitching_list = oscillating_sinspace(amplitude=self.pitching_amplitude,
+ period=self.pitching_period, base_value=self.pitching_base,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.pitching_spacing == "uniform":
# Create an array of points with a uniform spacing.
- pitching_list = oscillating_linspace(
- amplitude=self.pitching_amplitude,
- period=self.pitching_period,
- base_value=self.pitching_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ pitching_list = oscillating_linspace(amplitude=self.pitching_amplitude,
+ period=self.pitching_period, base_value=self.pitching_base,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.pitching_spacing == "custom":
# Raise an exception if the user did not declare a custom pitch function.
if self.custom_pitch_function is None:
raise Exception(
"You can't declare custom pitch spacing without providing a "
- "custom pitch function."
- )
+ "custom pitch function.")
# Create an array of points with a uniform spacing.
- pitching_list = oscillating_customspace(
- amplitude=self.pitching_amplitude,
- period=self.pitching_period,
- base_value=self.pitching_base,
- num_steps=num_steps,
- delta_time=delta_time,
- custom_function=self.custom_pitch_function,
- )
+ pitching_list = oscillating_customspace(amplitude=self.pitching_amplitude,
+ period=self.pitching_period, base_value=self.pitching_base,
+ num_steps=num_steps, delta_time=delta_time,
+ custom_function=self.custom_pitch_function, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -1117,41 +941,28 @@ def generate_wing_cross_sections(
if self.heaving_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- heaving_list = oscillating_sinspace(
- amplitude=self.heaving_amplitude,
- period=self.heaving_period,
- base_value=cross_section_heave,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ heaving_list = oscillating_sinspace(amplitude=self.heaving_amplitude,
+ period=self.heaving_period, base_value=cross_section_heave,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.heaving_spacing == "uniform":
# Create an array of points with a uniform spacing.
- heaving_list = oscillating_linspace(
- amplitude=self.heaving_amplitude,
- period=self.heaving_period,
- base_value=cross_section_heave,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ heaving_list = oscillating_linspace(amplitude=self.heaving_amplitude,
+ period=self.heaving_period, base_value=cross_section_heave,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.heaving_spacing == "custom":
# Raise an exception if the user did not declare a custom heave function.
if self.custom_heave_function is None:
raise Exception(
"You can't declare custom heave spacing without providing a "
- "custom heave function."
- )
+ "custom heave function.")
# Create an array of points with custom spacing.
- heaving_list = oscillating_customspace(
- amplitude=self.heaving_amplitude,
- period=self.heaving_period,
- base_value=cross_section_heave,
- num_steps=num_steps,
- delta_time=delta_time,
- custom_function=self.custom_heave_function,
- )
+ heaving_list = oscillating_customspace(amplitude=self.heaving_amplitude,
+ period=self.heaving_period, base_value=cross_section_heave,
+ num_steps=num_steps, delta_time=delta_time,
+ custom_function=self.custom_heave_function, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -1170,14 +981,11 @@ def generate_wing_cross_sections(
# convert the lists of sweep, pitch, and heave values to radians before
# passing them into numpy's trigonometry functions.
x_le_list = last_x_les + cross_section_span * np.cos(
- sweeping_list * np.pi / 180
- ) * np.sin(heaving_list * np.pi / 180)
+ sweeping_list * np.pi / 180) * np.sin(heaving_list * np.pi / 180)
y_le_list = last_y_les + cross_section_span * np.cos(
- sweeping_list * np.pi / 180
- ) * np.cos(heaving_list * np.pi / 180)
+ sweeping_list * np.pi / 180) * np.cos(heaving_list * np.pi / 180)
z_le_list = last_z_les + cross_section_span * np.sin(
- sweeping_list * np.pi / 180
- )
+ sweeping_list * np.pi / 180)
twist_list = pitching_list
# Create an empty list of wing cross sections.
@@ -1189,8 +997,7 @@ def generate_wing_cross_sections(
control_surface_deflection = self.control_surface_deflection_base
control_surface_type = self.base_wing_cross_section.control_surface_type
control_surface_hinge_point = (
- self.base_wing_cross_section.control_surface_hinge_point
- )
+ self.base_wing_cross_section.control_surface_hinge_point)
num_spanwise_panels = self.base_wing_cross_section.num_spanwise_panels
spanwise_spacing = self.base_wing_cross_section.spanwise_spacing
@@ -1203,19 +1010,13 @@ def generate_wing_cross_sections(
twist = twist_list[step]
# Make a new wing cross section object for this time step.
- this_wing_cross_section = geometry.WingCrossSection(
- x_le=x_le,
- y_le=y_le,
- z_le=z_le,
- chord=chord,
- twist=twist,
- airfoil=airfoil,
+ this_wing_cross_section = geometry.WingCrossSection(x_le=x_le, y_le=y_le,
+ z_le=z_le, chord=chord, twist=twist, airfoil=airfoil,
control_surface_type=control_surface_type,
control_surface_hinge_point=control_surface_hinge_point,
control_surface_deflection=control_surface_deflection,
num_spanwise_panels=num_spanwise_panels,
- spanwise_spacing=spanwise_spacing,
- )
+ spanwise_spacing=spanwise_spacing, )
# Add this new object to the list of wing cross sections.
wing_cross_sections.append(this_wing_cross_section)
@@ -1230,9 +1031,8 @@ def get_max_period(self):
The longest period in seconds.
"""
- max_period = max(
- self.sweeping_period, self.pitching_period, self.heaving_period
- )
+ max_period = max(self.sweeping_period, self.pitching_period,
+ self.heaving_period)
return max_period
@@ -1255,13 +1055,8 @@ class OperatingPointMovement:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- base_operating_point,
- velocity_amplitude=0.0,
- velocity_period=0.0,
- velocity_spacing="sine",
- ):
+ def __init__(self, base_operating_point, velocity_amplitude=0.0,
+ velocity_period=0.0, velocity_spacing="sine", ):
"""This is the initialization method.
:param base_operating_point: OperatingPoint
@@ -1303,23 +1098,15 @@ def generate_operating_points(self, num_steps=10, delta_time=0.1):
if self.velocity_spacing == "sine":
# Create an array of points with a sinusoidal spacing.
- velocity_list = oscillating_sinspace(
- amplitude=self.velocity_amplitude,
- period=self.velocity_period,
- base_value=self.velocity_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ velocity_list = oscillating_sinspace(amplitude=self.velocity_amplitude,
+ period=self.velocity_period, base_value=self.velocity_base,
+ num_steps=num_steps, delta_time=delta_time, )
elif self.velocity_spacing == "uniform":
# Create an array of points with a uniform spacing.
- velocity_list = oscillating_linspace(
- amplitude=self.velocity_amplitude,
- period=self.velocity_period,
- base_value=self.velocity_base,
- num_steps=num_steps,
- delta_time=delta_time,
- )
+ velocity_list = oscillating_linspace(amplitude=self.velocity_amplitude,
+ period=self.velocity_period, base_value=self.velocity_base,
+ num_steps=num_steps, delta_time=delta_time, )
else:
# Throw an exception if the spacing value is not "sine" or "uniform".
@@ -1339,9 +1126,8 @@ def generate_operating_points(self, num_steps=10, delta_time=0.1):
velocity = velocity_list[step]
# Make a new operating point object for this time step.
- this_operating_point = operating_point.OperatingPoint(
- density=density, velocity=velocity, alpha=alpha, beta=beta
- )
+ this_operating_point = operating_point.OperatingPoint(density=density,
+ velocity=velocity, alpha=alpha, beta=beta)
# Add this new object to the list of operating points.
operating_points.append(this_operating_point)
@@ -1437,9 +1223,8 @@ def oscillating_linspace(amplitude, period, base_value, num_steps, delta_time):
return a * signal.sawtooth((b * times + h), 0.5) + k
-def oscillating_customspace(
- amplitude, period, base_value, num_steps, delta_time, custom_function
-):
+def oscillating_customspace(amplitude, period, base_value, num_steps, delta_time,
+ custom_function):
"""This function returns a 1D array of values that are calculated by inputting a
vector of linearly spaced time steps into a custom function.
diff --git a/pterasoftware/operating_point.py b/pterasoftware/operating_point.py
index ab588815..9c8da28a 100644
--- a/pterasoftware/operating_point.py
+++ b/pterasoftware/operating_point.py
@@ -43,15 +43,8 @@ class OperatingPoint:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- density=1.225,
- velocity=10.0,
- alpha=5.0,
- beta=0.0,
- external_thrust=0.0,
- nu=15.06e-6,
- ):
+ def __init__(self, density=1.225, velocity=10.0, alpha=5.0, beta=0.0,
+ external_thrust=0.0, nu=15.06e-6, ):
"""This is the initialization method.
:param density: float, optional
@@ -95,7 +88,7 @@ def calculate_dynamic_pressure(self):
"""
# Calculate and return the freestream dynamic pressure
- dynamic_pressure = 0.5 * self.density * self.velocity**2
+ dynamic_pressure = 0.5 * self.density * self.velocity ** 2
return dynamic_pressure
def calculate_rotation_matrix_wind_to_geometry(self):
@@ -113,28 +106,19 @@ def calculate_rotation_matrix_wind_to_geometry(self):
eye = np.eye(3)
alpha_rotation = np.array(
- [[cos_alpha, 0, -sin_alpha], [0, 1, 0], [sin_alpha, 0, cos_alpha]]
- )
+ [[cos_alpha, 0, -sin_alpha], [0, 1, 0], [sin_alpha, 0, cos_alpha]])
beta_rotation = np.array(
- [[cos_beta, -sin_beta, 0], [sin_beta, cos_beta, 0], [0, 0, 1]]
- )
+ [[cos_beta, -sin_beta, 0], [sin_beta, cos_beta, 0], [0, 0, 1]])
# Flip the axes because in geometry axes x is downstream by convention,
# while in wind axes x is upstream by convention. Same with z being up/down
# respectively.
- axes_flip = np.array(
- [
- [-1, 0, 0],
- [0, 1, 0],
- [0, 0, -1],
- ]
- )
+ axes_flip = np.array([[-1, 0, 0], [0, 1, 0], [0, 0, -1], ])
# Calculate and return the rotation matrix to convert wind axes to geometry
# axes.
rotation_matrix_wind_axes_to_geometry_axes = (
- axes_flip @ alpha_rotation @ beta_rotation @ eye
- )
+ axes_flip @ alpha_rotation @ beta_rotation @ eye)
return rotation_matrix_wind_axes_to_geometry_axes
def calculate_freestream_direction_geometry_axes(self):
@@ -147,9 +131,8 @@ def calculate_freestream_direction_geometry_axes(self):
velocity_direction_wind_axes = np.array([-1, 0, 0])
velocity_direction_geometry_axes = (
- self.calculate_rotation_matrix_wind_to_geometry()
- @ velocity_direction_wind_axes
- )
+ self.calculate_rotation_matrix_wind_to_geometry() @
+ velocity_direction_wind_axes)
return velocity_direction_geometry_axes
def calculate_freestream_velocity_geometry_axes(self):
@@ -161,6 +144,5 @@ def calculate_freestream_velocity_geometry_axes(self):
"""
freestream_velocity_geometry_axes = (
- self.calculate_freestream_direction_geometry_axes() * self.velocity
- )
+ self.calculate_freestream_direction_geometry_axes() * self.velocity)
return freestream_velocity_geometry_axes
diff --git a/pterasoftware/output.py b/pterasoftware/output.py
index 0ad42110..c140e431 100644
--- a/pterasoftware/output.py
+++ b/pterasoftware/output.py
@@ -58,28 +58,9 @@
# For the figure lines, use the "Prism" qualitative color map from
# carto.com/carto-colors.
-prism = [
- "#5F4690",
- "#1D6996",
- "#38A6A5",
- "#0F8554",
- "#73AF48",
- "#EDAD08",
- "#E17C05",
- "#CC503E",
- "#94346E",
- "#6F4070",
- "#994E95",
- "#666666",
-]
-[
- drag_color,
- side_color,
- lift_color,
- roll_color,
- pitch_color,
- yaw_color,
-] = prism[3:9]
+prism = ["#5F4690", "#1D6996", "#38A6A5", "#0F8554", "#73AF48", "#EDAD08", "#E17C05",
+ "#CC503E", "#94346E", "#6F4070", "#994E95", "#666666", ]
+[drag_color, side_color, lift_color, roll_color, pitch_color, yaw_color, ] = prism[3:9]
# Set constants for the color maps, scalar bars, and text boxes.
color_map_num_sig = 3
@@ -102,13 +83,8 @@
marker_spacing = 1.0 / num_markers
-def draw(
- solver,
- scalar_type=None,
- show_streamlines=False,
- show_wake_vortices=False,
- save=False,
-):
+def draw(solver, scalar_type=None, show_streamlines=False, show_wake_vortices=False,
+ save=False, ):
"""Draw the geometry of the airplanes in a solver object.
Citation:
@@ -141,10 +117,9 @@ def draw(
plotter = pv.Plotter(window_size=window_size, lighting=None)
# Get the solver's geometry.
- if isinstance(
- solver,
- unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver,
- ):
+ if isinstance(solver,
+ unsteady_ring_vortex_lattice_method
+ .UnsteadyRingVortexLatticeMethodSolver, ):
draw_step = solver.num_steps - 1
airplanes = solver.steady_problems[draw_step].airplanes
@@ -152,22 +127,15 @@ def draw(
# plot them.
if show_wake_vortices:
wake_ring_vortex_surfaces = get_wake_ring_vortex_surfaces(solver, draw_step)
- plotter.add_mesh(
- wake_ring_vortex_surfaces,
- show_edges=True,
- smooth_shading=False,
- color=wake_vortex_color,
- )
+ plotter.add_mesh(wake_ring_vortex_surfaces, show_edges=True,
+ smooth_shading=False, color=wake_vortex_color, )
else:
airplanes = solver.airplanes
# Check if the user wants to show scalars on the wing panels.
show_scalars = False
if (
- scalar_type == "induced drag"
- or scalar_type == "side force"
- or scalar_type == "lift"
- ):
+ scalar_type == "induced drag" or scalar_type == "side force" or scalar_type == "lift"):
show_scalars = True
# Get the panel surfaces.
@@ -188,35 +156,20 @@ def draw(
color_map = sequential_color_map
c_min = max(
np.mean(these_scalars) - color_map_num_sig * np.std(these_scalars),
- np.min(these_scalars),
- )
+ np.min(these_scalars), )
c_max = min(
np.mean(these_scalars) + color_map_num_sig * np.std(these_scalars),
- np.max(these_scalars),
- )
+ np.max(these_scalars), )
else:
color_map = diverging_color_map
c_min = -color_map_num_sig * np.std(these_scalars)
c_max = color_map_num_sig * np.std(these_scalars)
- plot_scalars(
- plotter,
- these_scalars,
- scalar_type,
- min_scalar,
- max_scalar,
- color_map,
- c_min,
- c_max,
- panel_surfaces,
- )
+ plot_scalars(plotter, these_scalars, scalar_type, min_scalar, max_scalar,
+ color_map, c_min, c_max, panel_surfaces, )
else:
- plotter.add_mesh(
- panel_surfaces,
- show_edges=True,
- color=panel_color,
- smooth_shading=False,
- )
+ plotter.add_mesh(panel_surfaces, show_edges=True, color=panel_color,
+ smooth_shading=False, )
# Check if the user wants to plot streamlines.
if show_streamlines:
@@ -238,52 +191,30 @@ def draw(
last_point = streamline_point_column[point_index - 1, :]
# Add a line to make this segment of the streamline.
- plotter.add_mesh(
- pv.Line(
- last_point,
- point,
- ),
- show_edges=True,
- color=streamline_color,
- line_width=2,
- smooth_shading=False,
- )
+ plotter.add_mesh(pv.Line(last_point, point, ), show_edges=True,
+ color=streamline_color, line_width=2, smooth_shading=False, )
# Set the plotter's background color and camera position. Then show the plotter
# so the user can adjust the camera position and window. When the user closes the
# window, the plotter object won't be closed so that it can be saved as an image
# if the user wants.
plotter.set_background(color=plotter_background_color)
- plotter.show(
- cpos=(-1, -1, 1),
- full_screen=False,
- auto_close=False,
- )
+ plotter.show(cpos=(-1, -1, 1), full_screen=False, auto_close=False, )
# If the user wants to save the image, take a screenshot, convert it into an
# image object, and save it as a WebP.
if save:
image = webp.Image.fromarray(
- plotter.screenshot(
- filename=None,
- transparent_background=True,
- return_img=True,
- )
- )
- webp.save_image(
- img=image, file_path="Draw.webp", lossless=False, quality=quality
- )
+ plotter.screenshot(filename=None, transparent_background=True,
+ return_img=True, ))
+ webp.save_image(img=image, file_path="Draw.webp", lossless=False,
+ quality=quality)
# Close all the plotters.
pv.close_all()
-def animate(
- unsteady_solver,
- scalar_type=None,
- show_wake_vortices=False,
- save=False,
-):
+def animate(unsteady_solver, scalar_type=None, show_wake_vortices=False, save=False, ):
"""Create an animation of a solver's geometries.
:param unsteady_solver: UnsteadyRingVortexLatticeMethodSolver
@@ -331,21 +262,14 @@ def animate(
if save:
# Add text to the animation that display's its speed relative to the true
# speed.
- plotter.add_text(
- text="Speed: " + str(round(100 * speed)) + "%",
- position=text_speed_position,
- font_size=text_font_size,
- viewport=True,
- color=text_color,
- )
+ plotter.add_text(text="Speed: " + str(round(100 * speed)) + "%",
+ position=text_speed_position, font_size=text_font_size, viewport=True,
+ color=text_color, )
# Check if the user wants to show scalars on the wing panels.
show_scalars = False
if (
- scalar_type == "induced drag"
- or scalar_type == "side force"
- or scalar_type == "lift"
- ):
+ scalar_type == "induced drag" or scalar_type == "side force" or scalar_type == "lift"):
show_scalars = True
# Initialize variables to hold the problems' scalars and their attributes.
@@ -367,14 +291,10 @@ def animate(
# have different signs (diverging color map).
if np.sign(np.min(all_scalars)) == np.sign(np.max(all_scalars)):
color_map = sequential_color_map
- c_min = max(
- np.mean(all_scalars) - color_map_num_sig * np.std(all_scalars),
- np.min(all_scalars),
- )
- c_max = min(
- np.mean(all_scalars) + color_map_num_sig * np.std(all_scalars),
- np.max(all_scalars),
- )
+ c_min = max(np.mean(all_scalars) - color_map_num_sig * np.std(all_scalars),
+ np.min(all_scalars), )
+ c_max = min(np.mean(all_scalars) + color_map_num_sig * np.std(all_scalars),
+ np.max(all_scalars), )
else:
color_map = diverging_color_map
c_min = -color_map_num_sig * np.std(all_scalars)
@@ -391,51 +311,27 @@ def animate(
if show_scalars and first_results_step == 0:
these_scalars = get_scalars(step_airplanes[0], scalar_type)
- plot_scalars(
- plotter,
- these_scalars,
- scalar_type,
- min_scalar,
- max_scalar,
- color_map,
- c_min,
- c_max,
- panel_surfaces,
- )
+ plot_scalars(plotter, these_scalars, scalar_type, min_scalar, max_scalar,
+ color_map, c_min, c_max, panel_surfaces, )
else:
- plotter.add_mesh(
- panel_surfaces,
- show_edges=True,
- color=panel_color,
- smooth_shading=False,
- )
+ plotter.add_mesh(panel_surfaces, show_edges=True, color=panel_color,
+ smooth_shading=False, )
# Set the plotter background color and show the plotter.
plotter.set_background(color=plotter_background_color)
# Print a message to the console on how to set up the window.
print(
- 'Orient the view, then press "q" to close the window and produce the animation.'
- )
+ 'Orient the view, then press "q" to close the window and produce the animation.')
# Show the plotter so the user can set up the camera. Then, they will close the
# window, but the plotter object will stay open off-screen.
- plotter.show(
- title="Rendering speed not to scale.",
- cpos=(-1, -1, 1),
- full_screen=False,
- auto_close=False,
- )
+ plotter.show(title="Rendering speed not to scale.", cpos=(-1, -1, 1),
+ full_screen=False, auto_close=False, )
# Start a list which will hold a WebP image of each frame.
- images = [
- webp.Image.fromarray(
- plotter.screenshot(
- transparent_background=True,
- return_img=True,
- )
- )
- ]
+ images = [webp.Image.fromarray(
+ plotter.screenshot(transparent_background=True, return_img=True, ))]
# Initialize a variable to keep track of which step we are on.
current_step = 1
@@ -450,26 +346,17 @@ def animate(
panel_surfaces = get_panel_surfaces(airplanes)
if save:
- plotter.add_text(
- text="Speed: " + str(round(100 * speed)) + "%",
- position=text_speed_position,
- font_size=text_font_size,
- viewport=True,
- color=text_color,
- )
+ plotter.add_text(text="Speed: " + str(round(100 * speed)) + "%",
+ position=text_speed_position, font_size=text_font_size, viewport=True,
+ color=text_color, )
# If the user wants to show the wake ring vortices, then get their surfaces
# and plot them.
if show_wake_vortices:
- wake_ring_vortex_surfaces = get_wake_ring_vortex_surfaces(
- unsteady_solver, current_step
- )
- plotter.add_mesh(
- wake_ring_vortex_surfaces,
- show_edges=True,
- smooth_shading=False,
- color=wake_vortex_color,
- )
+ wake_ring_vortex_surfaces = get_wake_ring_vortex_surfaces(unsteady_solver,
+ current_step)
+ plotter.add_mesh(wake_ring_vortex_surfaces, show_edges=True,
+ smooth_shading=False, color=wake_vortex_color, )
# Check if the user wants to plot scalars and this step is equal to or
# greater than the first step with calculated results. If so, add the panel
@@ -478,37 +365,18 @@ def animate(
these_scalars = get_scalars(airplanes, scalar_type)
- plot_scalars(
- plotter,
- these_scalars,
- scalar_type,
- min_scalar,
- max_scalar,
- color_map,
- c_min,
- c_max,
- panel_surfaces,
- )
+ plot_scalars(plotter, these_scalars, scalar_type, min_scalar, max_scalar,
+ color_map, c_min, c_max, panel_surfaces, )
else:
- plotter.add_mesh(
- panel_surfaces,
- show_edges=True,
- color=panel_color,
- smooth_shading=False,
- )
+ plotter.add_mesh(panel_surfaces, show_edges=True, color=panel_color,
+ smooth_shading=False, )
# Append a WebP image of this frame to the list of frame images if the user
# wants to save an animation.
if save:
- images.append(
- webp.Image.fromarray(
- plotter.screenshot(
- filename=None,
- transparent_background=True,
- return_img=True,
- )
- )
- )
+ images.append(webp.Image.fromarray(
+ plotter.screenshot(filename=None, transparent_background=True,
+ return_img=True, )))
# Increment the step number tracker.
current_step += 1
@@ -516,9 +384,8 @@ def animate(
# If the user wants to save the file, save the list of images as an animated WebP.
if save:
# Convert the list of WebP images to a WebP animation.
- webp.save_images(
- images, "Animate.webp", fps=actual_fps, lossless=False, quality=quality
- )
+ webp.save_images(images, "Animate.webp", fps=actual_fps, lossless=False,
+ quality=quality)
# Close all the plotters.
pv.close_all()
@@ -554,27 +421,19 @@ def plot_results_versus_time(unsteady_solver, show=True, save=False):
# Create a 1D array with the time at each time step where results have been
# calculated.
- times = np.linspace(
- first_results_time_step_time,
- final_time_step_time,
- num_steps_to_average,
- endpoint=True,
- )
+ times = np.linspace(first_results_time_step_time, final_time_step_time,
+ num_steps_to_average, endpoint=True, )
# Initialize matrices to hold the forces, moments, and coefficients at each time
# step which has results.
total_near_field_force_wind_axes = np.zeros(
- (num_airplanes, 3, num_steps_to_average)
- )
+ (num_airplanes, 3, num_steps_to_average))
total_near_field_force_coefficients_wind_axes = np.zeros(
- (num_airplanes, 3, num_steps_to_average)
- )
+ (num_airplanes, 3, num_steps_to_average))
total_near_field_moment_wind_axes = np.zeros(
- (num_airplanes, 3, num_steps_to_average)
- )
+ (num_airplanes, 3, num_steps_to_average))
total_near_field_moment_coefficients_wind_axes = np.zeros(
- (num_airplanes, 3, num_steps_to_average)
- )
+ (num_airplanes, 3, num_steps_to_average))
# Initialize a variable to track position in the results arrays.
results_step = 0
@@ -588,17 +447,13 @@ def plot_results_versus_time(unsteady_solver, show=True, save=False):
# Iterate through this step's airplanes.
for airplane_id, airplane in enumerate(airplanes):
total_near_field_force_wind_axes[airplane_id, :, results_step] = (
- airplane.total_near_field_force_wind_axes
- )
- total_near_field_force_coefficients_wind_axes[
- airplane_id, :, results_step
- ] = airplane.total_near_field_force_coefficients_wind_axes
+ airplane.total_near_field_force_wind_axes)
+ total_near_field_force_coefficients_wind_axes[airplane_id, :,
+ results_step] = airplane.total_near_field_force_coefficients_wind_axes
total_near_field_moment_wind_axes[airplane_id, :, results_step] = (
- airplane.total_near_field_moment_wind_axes
- )
- total_near_field_moment_coefficients_wind_axes[
- airplane_id, :, results_step
- ] = airplane.total_near_field_moment_coefficients_wind_axes
+ airplane.total_near_field_moment_wind_axes)
+ total_near_field_moment_coefficients_wind_axes[airplane_id, :,
+ results_step] = airplane.total_near_field_moment_coefficients_wind_axes
results_step += 1
@@ -660,114 +515,60 @@ def plot_results_versus_time(unsteady_solver, show=True, save=False):
moment_coefficients_axes.set_facecolor(figure_background_color)
# Populate the plots.
- force_axes.plot(
- times,
- total_near_field_force_wind_axes[airplane_id, 0],
- label="Induced Drag",
- color=drag_color,
- marker=".",
+ force_axes.plot(times, total_near_field_force_wind_axes[airplane_id, 0],
+ label="Induced Drag", color=drag_color, marker=".",
markevery=(marker_spacing * 0 / 3, marker_spacing),
- markersize=marker_size,
- )
- force_axes.plot(
- times,
- total_near_field_force_wind_axes[airplane_id, 1],
- label="Side Force",
- color=side_color,
- marker=".",
+ markersize=marker_size, )
+ force_axes.plot(times, total_near_field_force_wind_axes[airplane_id, 1],
+ label="Side Force", color=side_color, marker=".",
markevery=(marker_spacing * 1 / 3, marker_spacing),
- markersize=marker_size,
- )
- force_axes.plot(
- times,
- total_near_field_force_wind_axes[airplane_id, 2],
- label="Lift",
- color=lift_color,
- marker=".",
+ markersize=marker_size, )
+ force_axes.plot(times, total_near_field_force_wind_axes[airplane_id, 2],
+ label="Lift", color=lift_color, marker=".",
markevery=(marker_spacing * 2 / 3, marker_spacing),
- markersize=marker_size,
- )
- force_coefficients_axes.plot(
- times,
+ markersize=marker_size, )
+ force_coefficients_axes.plot(times,
total_near_field_force_coefficients_wind_axes[airplane_id, 0],
- label="Induced Drag",
- color=drag_color,
- marker=".",
+ label="Induced Drag", color=drag_color, marker=".",
markevery=(marker_spacing * 0 / 3, marker_spacing),
- markersize=marker_size,
- )
- force_coefficients_axes.plot(
- times,
+ markersize=marker_size, )
+ force_coefficients_axes.plot(times,
total_near_field_force_coefficients_wind_axes[airplane_id, 1],
- label="Side Force",
- color=side_color,
- marker=".",
+ label="Side Force", color=side_color, marker=".",
markevery=(marker_spacing * 1 / 3, marker_spacing),
- markersize=marker_size,
- )
- force_coefficients_axes.plot(
- times,
- total_near_field_force_coefficients_wind_axes[airplane_id, 2],
- label="Lift",
- color=lift_color,
- marker=".",
+ markersize=marker_size, )
+ force_coefficients_axes.plot(times,
+ total_near_field_force_coefficients_wind_axes[airplane_id, 2], label="Lift",
+ color=lift_color, marker=".",
markevery=(marker_spacing * 2 / 3, marker_spacing),
- markersize=marker_size,
- )
- moment_axes.plot(
- times,
- total_near_field_moment_wind_axes[airplane_id, 0],
- label="Roll",
- color=roll_color,
- marker=".",
+ markersize=marker_size, )
+ moment_axes.plot(times, total_near_field_moment_wind_axes[airplane_id, 0],
+ label="Roll", color=roll_color, marker=".",
markevery=(marker_spacing * 0 / 3, marker_spacing),
- markersize=marker_size,
- )
- moment_axes.plot(
- times,
- total_near_field_moment_wind_axes[airplane_id, 1],
- label="Pitch",
- color=pitch_color,
- marker=".",
+ markersize=marker_size, )
+ moment_axes.plot(times, total_near_field_moment_wind_axes[airplane_id, 1],
+ label="Pitch", color=pitch_color, marker=".",
markevery=(marker_spacing * 1 / 3, marker_spacing),
- markersize=marker_size,
- )
- moment_axes.plot(
- times,
- total_near_field_moment_wind_axes[airplane_id, 2],
- label="Yaw",
- color=yaw_color,
- marker=".",
+ markersize=marker_size, )
+ moment_axes.plot(times, total_near_field_moment_wind_axes[airplane_id, 2],
+ label="Yaw", color=yaw_color, marker=".",
markevery=(marker_spacing * 2 / 3, marker_spacing),
- markersize=marker_size,
- )
- moment_coefficients_axes.plot(
- times,
+ markersize=marker_size, )
+ moment_coefficients_axes.plot(times,
total_near_field_moment_coefficients_wind_axes[airplane_id, 0],
- label="Roll",
- color=roll_color,
- marker=".",
+ label="Roll", color=roll_color, marker=".",
markevery=(marker_spacing * 0 / 3, marker_spacing),
- markersize=marker_size,
- )
- moment_coefficients_axes.plot(
- times,
+ markersize=marker_size, )
+ moment_coefficients_axes.plot(times,
total_near_field_moment_coefficients_wind_axes[airplane_id, 1],
- label="Pitch",
- color=pitch_color,
- marker=".",
+ label="Pitch", color=pitch_color, marker=".",
markevery=(marker_spacing * 1 / 3, marker_spacing),
- markersize=marker_size,
- )
- moment_coefficients_axes.plot(
- times,
- total_near_field_moment_coefficients_wind_axes[airplane_id, 2],
- label="Yaw",
- color=yaw_color,
- marker=".",
+ markersize=marker_size, )
+ moment_coefficients_axes.plot(times,
+ total_near_field_moment_coefficients_wind_axes[airplane_id, 2], label="Yaw",
+ color=yaw_color, marker=".",
markevery=(marker_spacing * 2 / 3, marker_spacing),
- markersize=marker_size,
- )
+ markersize=marker_size, )
# Find and format this airplane's name for use in the plot titles.
airplane_name = unsteady_solver.steady_problems[0].airplanes[airplane_id].name
@@ -791,45 +592,23 @@ def plot_results_versus_time(unsteady_solver, show=True, save=False):
moment_coefficients_axes.set_title(moment_coefficient_title, color=text_color)
# Format the plots' legends.
- force_axes.legend(
- facecolor=figure_background_color,
- edgecolor=figure_background_color,
- labelcolor=text_color,
- )
- force_coefficients_axes.legend(
- facecolor=figure_background_color,
- edgecolor=figure_background_color,
- labelcolor=text_color,
- )
- moment_axes.legend(
- facecolor=figure_background_color,
- edgecolor=figure_background_color,
- labelcolor=text_color,
- )
- moment_coefficients_axes.legend(
- facecolor=figure_background_color,
- edgecolor=figure_background_color,
- labelcolor=text_color,
- )
+ force_axes.legend(facecolor=figure_background_color,
+ edgecolor=figure_background_color, labelcolor=text_color, )
+ force_coefficients_axes.legend(facecolor=figure_background_color,
+ edgecolor=figure_background_color, labelcolor=text_color, )
+ moment_axes.legend(facecolor=figure_background_color,
+ edgecolor=figure_background_color, labelcolor=text_color, )
+ moment_coefficients_axes.legend(facecolor=figure_background_color,
+ edgecolor=figure_background_color, labelcolor=text_color, )
# Save the figures as PNGs if the user wants to do so.
if save:
- force_figure.savefig(
- airplane_name + " Forces.png",
- dpi=300,
- )
- force_coefficients_figure.savefig(
- airplane_name + " Force Coefficients.png",
- dpi=300,
- )
- moment_figure.savefig(
- airplane_name + " Moments.png",
- dpi=300,
- )
+ force_figure.savefig(airplane_name + " Forces.png", dpi=300, )
+ force_coefficients_figure.savefig(airplane_name + " Force Coefficients.png",
+ dpi=300, )
+ moment_figure.savefig(airplane_name + " Moments.png", dpi=300, )
moment_coefficients_figure.savefig(
- airplane_name + " Moment Coefficients.png",
- dpi=300,
- )
+ airplane_name + " Moment Coefficients.png", dpi=300, )
# If the user wants to show the plots, do so.
if show:
@@ -856,81 +635,45 @@ def print_steady_results(steady_solver):
# Print out this airplane's forces.
print("\tForces in Wind Axes:")
- print(
- "\t\tInduced Drag:\t\t\t",
- np.round(airplane.total_near_field_force_wind_axes[0], 3),
- " N",
- sep="",
- )
- print(
- "\t\tSide Force:\t\t\t\t",
- np.round(airplane.total_near_field_force_wind_axes[1], 3),
- " N",
- sep="",
- )
- print(
- "\t\tLift:\t\t\t\t\t",
- np.round(airplane.total_near_field_force_wind_axes[2], 3),
- " N",
- sep="",
- )
+ print("\t\tInduced Drag:\t\t\t",
+ np.round(airplane.total_near_field_force_wind_axes[0], 3), " N", sep="", )
+ print("\t\tSide Force:\t\t\t\t",
+ np.round(airplane.total_near_field_force_wind_axes[1], 3), " N", sep="", )
+ print("\t\tLift:\t\t\t\t\t",
+ np.round(airplane.total_near_field_force_wind_axes[2], 3), " N", sep="", )
# Print out this airplane's moments.
print("\n\tMoments in Wind Axes:")
- print(
- "\t\tRolling Moment:\t\t\t",
- np.round(airplane.total_near_field_moment_wind_axes[0], 3),
- " Nm",
- sep="",
- )
- print(
- "\t\tPitching Moment:\t\t",
- np.round(airplane.total_near_field_moment_wind_axes[1], 3),
- " Nm",
- sep="",
- )
- print(
- "\t\tYawing Moment:\t\t\t",
- np.round(airplane.total_near_field_moment_wind_axes[2], 3),
- " Nm",
- sep="",
- )
+ print("\t\tRolling Moment:\t\t\t",
+ np.round(airplane.total_near_field_moment_wind_axes[0], 3), " Nm", sep="", )
+ print("\t\tPitching Moment:\t\t",
+ np.round(airplane.total_near_field_moment_wind_axes[1], 3), " Nm", sep="", )
+ print("\t\tYawing Moment:\t\t\t",
+ np.round(airplane.total_near_field_moment_wind_axes[2], 3), " Nm", sep="", )
# Print out this airplane's force coefficients.
print("\n\tForce Coefficients in Wind Axes:")
- print(
- "\t\tCDi:\t\t\t\t\t",
+ print("\t\tCDi:\t\t\t\t\t",
np.round(airplane.total_near_field_force_coefficients_wind_axes[0], 3),
- sep="",
- )
- print(
- "\t\tCY:\t\t\t\t\t\t",
+ sep="", )
+ print("\t\tCY:\t\t\t\t\t\t",
np.round(airplane.total_near_field_force_coefficients_wind_axes[1], 3),
- sep="",
- )
- print(
- "\t\tCL:\t\t\t\t\t\t",
+ sep="", )
+ print("\t\tCL:\t\t\t\t\t\t",
np.round(airplane.total_near_field_force_coefficients_wind_axes[2], 3),
- sep="",
- )
+ sep="", )
# Print out this airplane's moment coefficients.
print("\n\tMoment Coefficients in Wind Axes:")
- print(
- "\t\tCl:\t\t\t\t\t\t",
+ print("\t\tCl:\t\t\t\t\t\t",
np.round(airplane.total_near_field_moment_coefficients_wind_axes[0], 3),
- sep="",
- )
- print(
- "\t\tCm:\t\t\t\t\t\t",
+ sep="", )
+ print("\t\tCm:\t\t\t\t\t\t",
np.round(airplane.total_near_field_moment_coefficients_wind_axes[1], 3),
- sep="",
- )
- print(
- "\t\tCn:\t\t\t\t\t\t",
+ sep="", )
+ print("\t\tCn:\t\t\t\t\t\t",
np.round(airplane.total_near_field_moment_coefficients_wind_axes[2], 3),
- sep="",
- )
+ sep="", )
# If the results from more airplanes are going to be printed, print new line
# to separate them.
@@ -949,17 +692,14 @@ def print_unsteady_results(unsteady_solver):
forces = unsteady_solver.unsteady_problem.final_mean_near_field_forces_wind_axes
moments = unsteady_solver.unsteady_problem.final_mean_near_field_moments_wind_axes
force_coefficients = (
- unsteady_solver.unsteady_problem.final_mean_near_field_force_coefficients_wind_axes
- )
+ unsteady_solver.unsteady_problem.final_mean_near_field_force_coefficients_wind_axes)
moment_coefficients = (
- unsteady_solver.unsteady_problem.final_mean_near_field_moment_coefficients_wind_axes
- )
+ unsteady_solver.unsteady_problem.final_mean_near_field_moment_coefficients_wind_axes)
# For each airplane object, calculate and print the average force, moment,
# force coefficient, and moment coefficient values.
for airplane_id, airplane in enumerate(
- unsteady_solver.steady_problems[0].airplanes
- ):
+ unsteady_solver.steady_problems[0].airplanes):
these_forces = forces[airplane_id]
these_moments = moments[airplane_id]
these_force_coefficients = force_coefficients[airplane_id]
@@ -983,81 +723,34 @@ def print_unsteady_results(unsteady_solver):
# Print out this airplane's average forces.
print("\tFinal Forces in Wind Axes:")
- print(
- "\t\tInduced Drag:\t\t\t",
- np.round(this_induced_drag, 3),
- " N",
- sep="",
- )
- print(
- "\t\tSide Force:\t\t\t\t",
- np.round(this_side_force, 3),
- " N",
- sep="",
- )
- print(
- "\t\tLift:\t\t\t\t\t",
- np.round(this_lift, 3),
- " N",
- sep="",
- )
+ print("\t\tInduced Drag:\t\t\t", np.round(this_induced_drag, 3), " N", sep="", )
+ print("\t\tSide Force:\t\t\t\t", np.round(this_side_force, 3), " N", sep="", )
+ print("\t\tLift:\t\t\t\t\t", np.round(this_lift, 3), " N", sep="", )
# Print out this airplane's average moments.
print("\n\tFinal Moments in Wind Axes:")
- print(
- "\t\tRolling Moment:\t\t\t",
- np.round(this_rolling_moment, 3),
- " Nm",
- sep="",
- )
- print(
- "\t\tPitching Moment:\t\t",
- np.round(this_pitching_moment, 3),
- " Nm",
- sep="",
- )
- print(
- "\t\tYawing Moment:\t\t\t",
- np.round(this_yawing_moment, 3),
- " Nm",
- sep="",
- )
+ print("\t\tRolling Moment:\t\t\t", np.round(this_rolling_moment, 3), " Nm",
+ sep="", )
+ print("\t\tPitching Moment:\t\t", np.round(this_pitching_moment, 3), " Nm",
+ sep="", )
+ print("\t\tYawing Moment:\t\t\t", np.round(this_yawing_moment, 3), " Nm",
+ sep="", )
# Print out this airplane's average force coefficients.
print("\n\tFinal Force Coefficients in Wind Axes:")
- print(
- "\t\tCDi:\t\t\t\t\t",
- np.round(this_induced_drag_coefficient, 3),
- sep="",
- )
- print(
- "\t\tCY:\t\t\t\t\t\t",
- np.round(this_side_force_coefficient, 3),
- sep="",
- )
- print(
- "\t\tCL:\t\t\t\t\t\t",
- np.round(this_lift_coefficient, 3),
- sep="",
- )
+ print("\t\tCDi:\t\t\t\t\t", np.round(this_induced_drag_coefficient, 3),
+ sep="", )
+ print("\t\tCY:\t\t\t\t\t\t", np.round(this_side_force_coefficient, 3), sep="", )
+ print("\t\tCL:\t\t\t\t\t\t", np.round(this_lift_coefficient, 3), sep="", )
# Print out this airplane's average moment coefficients.
print("\n\tFinal Moment Coefficients in Wind Axes:")
- print(
- "\t\tCl:\t\t\t\t\t\t",
- np.round(this_rolling_moment_coefficient, 3),
- sep="",
- )
- print(
- "\t\tCm:\t\t\t\t\t\t",
- np.round(this_pitching_moment_coefficient, 3),
- sep="",
- )
- print(
- "\t\tCn:\t\t\t\t\t\t",
- np.round(this_yawing_moment_coefficient, 3),
- sep="",
- )
+ print("\t\tCl:\t\t\t\t\t\t", np.round(this_rolling_moment_coefficient, 3),
+ sep="", )
+ print("\t\tCm:\t\t\t\t\t\t", np.round(this_pitching_moment_coefficient, 3),
+ sep="", )
+ print("\t\tCn:\t\t\t\t\t\t", np.round(this_yawing_moment_coefficient, 3),
+ sep="", )
# If the results from more airplanes are going to be printed, print new line
# to separate them.
@@ -1065,9 +758,7 @@ def print_unsteady_results(unsteady_solver):
print("")
-def get_panel_surfaces(
- airplanes,
-):
+def get_panel_surfaces(airplanes, ):
"""This function returns a PolyData representation of the wing panel surfaces
associated with all the airplanes in a given list.
@@ -1093,23 +784,12 @@ def get_panel_surfaces(
for panel in panels:
# Stack this panel's vertices and faces. Look through the PolyData
# documentation for more details.
- panel_vertices_to_add = np.vstack(
- (
- panel.front_left_vertex,
- panel.front_right_vertex,
- panel.back_right_vertex,
- panel.back_left_vertex,
- )
- )
+ panel_vertices_to_add = np.vstack((
+ panel.front_left_vertex, panel.front_right_vertex,
+ panel.back_right_vertex, panel.back_left_vertex,))
panel_face_to_add = np.array(
- [
- 4,
- (panel_num * 4),
- (panel_num * 4) + 1,
- (panel_num * 4) + 2,
- (panel_num * 4) + 3,
- ]
- )
+ [4, (panel_num * 4), (panel_num * 4) + 1, (panel_num * 4) + 2,
+ (panel_num * 4) + 3, ])
# Stack this panel's vertices and faces with the array of all the
# vertices and faces.
@@ -1137,17 +817,13 @@ def get_wake_ring_vortex_surfaces(solver, step):
"""
num_wake_ring_vortices = solver.num_wake_ring_vortices_list[step]
wake_ring_vortex_front_right_vertices = (
- solver.wake_ring_vortex_front_right_vertices_list[step]
- )
+ solver.wake_ring_vortex_front_right_vertices_list[step])
wake_ring_vortex_front_left_vertices = (
- solver.wake_ring_vortex_front_left_vertices_list[step]
- )
+ solver.wake_ring_vortex_front_left_vertices_list[step])
wake_ring_vortex_back_left_vertices = (
- solver.wake_ring_vortex_back_left_vertices_list[step]
- )
+ solver.wake_ring_vortex_back_left_vertices_list[step])
wake_ring_vortex_back_right_vertices = (
- solver.wake_ring_vortex_back_right_vertices_list[step]
- )
+ solver.wake_ring_vortex_back_right_vertices_list[step])
# Initialize empty arrays to hold each wake ring vortex's vertices and its face.
wake_ring_vortex_vertices = np.zeros((0, 3), dtype=int)
@@ -1155,43 +831,27 @@ def get_wake_ring_vortex_surfaces(solver, step):
for wake_ring_vortex_num in range(num_wake_ring_vortices):
this_front_right_vertex = wake_ring_vortex_front_right_vertices[
- wake_ring_vortex_num
- ]
+ wake_ring_vortex_num]
this_front_left_vertex = wake_ring_vortex_front_left_vertices[
- wake_ring_vortex_num
- ]
+ wake_ring_vortex_num]
this_back_left_vertex = wake_ring_vortex_back_left_vertices[
- wake_ring_vortex_num
- ]
+ wake_ring_vortex_num]
this_back_right_vertex = wake_ring_vortex_back_right_vertices[
- wake_ring_vortex_num
- ]
-
- wake_ring_vortex_vertices_to_add = np.vstack(
- (
- this_front_left_vertex,
- this_front_right_vertex,
- this_back_right_vertex,
- this_back_left_vertex,
- )
- )
+ wake_ring_vortex_num]
+
+ wake_ring_vortex_vertices_to_add = np.vstack((
+ this_front_left_vertex, this_front_right_vertex, this_back_right_vertex,
+ this_back_left_vertex,))
wake_ring_vortex_face_to_add = np.array(
- [
- 4,
- (wake_ring_vortex_num * 4),
- (wake_ring_vortex_num * 4) + 1,
- (wake_ring_vortex_num * 4) + 2,
- (wake_ring_vortex_num * 4) + 3,
- ]
- )
+ [4, (wake_ring_vortex_num * 4), (wake_ring_vortex_num * 4) + 1,
+ (wake_ring_vortex_num * 4) + 2,
+ (wake_ring_vortex_num * 4) + 3, ])
# Stack this wake ring vortex's vertices and faces.
wake_ring_vortex_vertices = np.vstack(
- (wake_ring_vortex_vertices, wake_ring_vortex_vertices_to_add)
- )
+ (wake_ring_vortex_vertices, wake_ring_vortex_vertices_to_add))
wake_ring_vortex_faces = np.hstack(
- (wake_ring_vortex_faces, wake_ring_vortex_face_to_add)
- )
+ (wake_ring_vortex_faces, wake_ring_vortex_face_to_add))
# Increment the wake ring vortex counter.
wake_ring_vortex_num += 1
@@ -1200,10 +860,7 @@ def get_wake_ring_vortex_surfaces(solver, step):
return pv.PolyData(wake_ring_vortex_vertices, wake_ring_vortex_faces)
-def get_scalars(
- airplanes,
- scalar_type,
-):
+def get_scalars(airplanes, scalar_type, ):
"""This function gets the coefficient values from a problem's airplane objects,
and puts them into a 1D array to be used as scalars for display by other output
methods.
@@ -1241,17 +898,8 @@ def get_scalars(
return scalars
-def plot_scalars(
- plotter,
- these_scalars,
- scalar_type,
- min_scalar,
- max_scalar,
- color_map,
- c_min,
- c_max,
- panel_surfaces,
-):
+def plot_scalars(plotter, these_scalars, scalar_type, min_scalar, max_scalar, color_map,
+ c_min, c_max, panel_surfaces, ):
"""This function plots a scalar bars, the mesh panels with a particular set of
scalars, and labels for the minimum and maximum scalar values.
@@ -1266,38 +914,15 @@ def plot_scalars(
:param panel_surfaces:
:return:
"""
- scalar_bar_args = dict(
- title=scalar_type.title() + " Coefficient",
- title_font_size=bar_title_font_size,
- label_font_size=bar_label_font_size,
- width=bar_width,
- position_x=bar_position_x,
- position_y=bar_position_y,
- n_labels=bar_n_labels,
- fmt="%.2f",
- color=text_color,
- )
- plotter.add_mesh(
- panel_surfaces,
- show_edges=True,
- cmap=color_map,
- clim=[c_min, c_max],
- scalars=these_scalars,
- smooth_shading=False,
- scalar_bar_args=scalar_bar_args,
- )
- plotter.add_text(
- text="Max: " + str(max_scalar),
- position=text_max_position,
- font_size=text_font_size,
- viewport=True,
- color=text_color,
- )
- plotter.add_text(
- text="Min: " + str(min_scalar),
- position=text_min_position,
- font_size=text_font_size,
- viewport=True,
- color=text_color,
- )
+ scalar_bar_args = dict(title=scalar_type.title() + " Coefficient",
+ title_font_size=bar_title_font_size, label_font_size=bar_label_font_size,
+ width=bar_width, position_x=bar_position_x, position_y=bar_position_y,
+ n_labels=bar_n_labels, fmt="%.2f", color=text_color, )
+ plotter.add_mesh(panel_surfaces, show_edges=True, cmap=color_map,
+ clim=[c_min, c_max], scalars=these_scalars, smooth_shading=False,
+ scalar_bar_args=scalar_bar_args, )
+ plotter.add_text(text="Max: " + str(max_scalar), position=text_max_position,
+ font_size=text_font_size, viewport=True, color=text_color, )
+ plotter.add_text(text="Min: " + str(min_scalar), position=text_min_position,
+ font_size=text_font_size, viewport=True, color=text_color, )
plotter.update_scalars(these_scalars)
diff --git a/pterasoftware/panel.py b/pterasoftware/panel.py
index 59e9dc0f..b3ebf232 100644
--- a/pterasoftware/panel.py
+++ b/pterasoftware/panel.py
@@ -39,15 +39,8 @@ class Panel:
This class is not meant to be subclassed.
"""
- def __init__(
- self,
- front_right_vertex,
- front_left_vertex,
- back_left_vertex,
- back_right_vertex,
- is_leading_edge,
- is_trailing_edge,
- ):
+ def __init__(self, front_right_vertex, front_left_vertex, back_left_vertex,
+ back_right_vertex, is_leading_edge, is_trailing_edge, ):
"""This is the initialization method.
:param front_right_vertex: 1D array with three elements
@@ -141,8 +134,7 @@ def collocation_point(self):
# Find the vector between the points three quarters of the way down the left
# and right legs of the panel.
three_quarter_chord_vector = (
- left_three_quarter_chord_mark - right_three_quarter_chord_mark
- )
+ left_three_quarter_chord_mark - right_three_quarter_chord_mark)
# Find the collocation point, which is halfway between the points three
# quarters of the way down the left and right legs of the panel. Then
@@ -222,12 +214,11 @@ def calculate_normalized_induced_velocity(self, point):
if self.ring_vortex is not None:
normalized_induced_velocity += (
- self.ring_vortex.calculate_normalized_induced_velocity(point=point)
- )
+ self.ring_vortex.calculate_normalized_induced_velocity(point=point))
if self.horseshoe_vortex is not None:
normalized_induced_velocity += (
- self.horseshoe_vortex.calculate_normalized_induced_velocity(point=point)
- )
+ self.horseshoe_vortex.calculate_normalized_induced_velocity(
+ point=point))
return normalized_induced_velocity
@@ -251,8 +242,7 @@ def calculate_induced_velocity(self, point):
induced_velocity += self.ring_vortex.calculate_induced_velocity(point=point)
if self.horseshoe_vortex is not None:
induced_velocity += self.horseshoe_vortex.calculate_induced_velocity(
- point=point
- )
+ point=point)
return induced_velocity
diff --git a/pterasoftware/problems.py b/pterasoftware/problems.py
index e22758bb..779eb426 100644
--- a/pterasoftware/problems.py
+++ b/pterasoftware/problems.py
@@ -82,9 +82,8 @@ def __init__(self, movement, only_final_results=False):
if self.max_period == 0:
self.first_averaging_step = self.num_steps - 1
else:
- self.first_averaging_step = max(
- 0, math.floor(self.num_steps - (self.max_period / self.delta_time))
- )
+ self.first_averaging_step = max(0,
+ math.floor(self.num_steps - (self.max_period / self.delta_time)))
# If the user only wants to calculate forces and moments for the final cycle
# (for cyclic motion) or for the final time step (for static movement) set
@@ -135,9 +134,8 @@ def __init__(self, movement, only_final_results=False):
this_operating_point = movement.operating_points[step_id]
# Initialize the steady problem object at this time step.
- this_steady_problem = SteadyProblem(
- airplanes=these_airplanes, operating_point=this_operating_point
- )
+ this_steady_problem = SteadyProblem(airplanes=these_airplanes,
+ operating_point=this_operating_point)
# Append this steady problem to the list of steady problems.
self.steady_problems.append(this_steady_problem)
diff --git a/pterasoftware/steady_horseshoe_vortex_lattice_method.py b/pterasoftware/steady_horseshoe_vortex_lattice_method.py
index 3f58f53b..0df4ebf4 100644
--- a/pterasoftware/steady_horseshoe_vortex_lattice_method.py
+++ b/pterasoftware/steady_horseshoe_vortex_lattice_method.py
@@ -78,8 +78,7 @@ def __init__(self, steady_problem):
# Initialize attributes to hold aerodynamic data that pertains to this problem.
self.wing_wing_influences = np.zeros((self.num_panels, self.num_panels))
self.freestream_velocity = (
- self.operating_point.calculate_freestream_velocity_geometry_axes()
- )
+ self.operating_point.calculate_freestream_velocity_geometry_axes())
self.freestream_wing_influences = np.zeros(self.num_panels)
self.vortex_strengths = np.zeros(self.num_panels)
self.panel_normal_directions = np.zeros((self.num_panels, 3))
@@ -111,8 +110,7 @@ def run(self, logging_level="Warning"):
"""
# Configure the problem's logger.
logging_level_value = functions.convert_logging_level_name_to_value(
- logging_level
- )
+ logging_level)
logging.basicConfig(level=logging_level_value)
# Initialize this problem's panels to have vortices congruent with this
@@ -158,8 +156,7 @@ def initialize_panel_vortices(self):
"""
# Find the freestream direction in geometry axes.
freestream_direction = (
- self.operating_point.calculate_freestream_direction_geometry_axes()
- )
+ self.operating_point.calculate_freestream_direction_geometry_axes())
# Iterate through each airplane's wings.
for airplane in self.airplanes:
@@ -185,10 +182,8 @@ def initialize_panel_vortices(self):
panel.horseshoe_vortex = aerodynamics.HorseshoeVortex(
finite_leg_origin=front_right_vortex_vertex,
finite_leg_termination=front_left_vortex_vertex,
- strength=None,
- infinite_leg_direction=freestream_direction,
- infinite_leg_length=infinite_leg_length,
- )
+ strength=None, infinite_leg_direction=freestream_direction,
+ infinite_leg_length=infinite_leg_length, )
def collapse_geometry(self):
"""This method converts attributes of the problem's geometry into 1D arrays.
@@ -214,46 +209,32 @@ def collapse_geometry(self):
# attributes.
self.panels[global_panel_position] = panel
self.panel_normal_directions[global_panel_position, :] = (
- panel.unit_normal
- )
+ panel.unit_normal)
self.panel_areas[global_panel_position] = panel.area
self.panel_collocation_points[global_panel_position, :] = (
- panel.collocation_point
- )
+ panel.collocation_point)
self.panel_back_right_vortex_vertices[global_panel_position, :] = (
- panel.horseshoe_vortex.right_leg.origin
- )
+ panel.horseshoe_vortex.right_leg.origin)
self.panel_front_right_vortex_vertices[global_panel_position, :] = (
- panel.horseshoe_vortex.right_leg.termination
- )
+ panel.horseshoe_vortex.right_leg.termination)
self.panel_front_left_vortex_vertices[global_panel_position, :] = (
- panel.horseshoe_vortex.left_leg.origin
- )
+ panel.horseshoe_vortex.left_leg.origin)
self.panel_back_left_vortex_vertices[global_panel_position, :] = (
- panel.horseshoe_vortex.left_leg.termination
- )
+ panel.horseshoe_vortex.left_leg.termination)
self.panel_bound_vortex_centers[global_panel_position, :] = (
- panel.horseshoe_vortex.finite_leg.center
- )
+ panel.horseshoe_vortex.finite_leg.center)
self.panel_bound_vortex_vectors[global_panel_position, :] = (
- panel.horseshoe_vortex.finite_leg.vector
- )
+ panel.horseshoe_vortex.finite_leg.vector)
self.panel_moment_references[global_panel_position, :] = (
- airplane.xyz_ref
- )
+ airplane.xyz_ref)
# Check if this panel is on the trailing edge.
if panel.is_trailing_edge:
# If it is, calculate it's streamline seed point and add it
# to the solver's array of seed points.
- self.seed_points = np.vstack(
- (
- self.seed_points,
- panel.back_left_vertex
- + 0.5
- * (panel.back_right_vertex - panel.back_left_vertex),
- )
- )
+ self.seed_points = np.vstack((self.seed_points,
+ panel.back_left_vertex + 0.5 * (
+ panel.back_right_vertex - panel.back_left_vertex),))
# Increment the global panel position.
global_panel_position += 1
@@ -272,17 +253,13 @@ def calculate_wing_wing_influences(self):
front_right_vortex_vertices=self.panel_front_right_vortex_vertices,
front_left_vortex_vertices=self.panel_front_left_vortex_vertices,
back_left_vortex_vertices=self.panel_back_left_vortex_vertices,
- strengths=np.ones(self.num_panels),
- )
+ strengths=np.ones(self.num_panels), )
# Take the batch dot product of the normalized velocities with each panel's
# normal direction. This is now the problem's matrix of wing-wing influence
# coefficients.
- self.wing_wing_influences = np.einsum(
- "...k,...k->...",
- induced_velocities,
- np.expand_dims(self.panel_normal_directions, axis=1),
- )
+ self.wing_wing_influences = np.einsum("...k,...k->...", induced_velocities,
+ np.expand_dims(self.panel_normal_directions, axis=1), )
def calculate_vortex_strengths(self):
"""Solve for each panel's vortex strengths.
@@ -290,13 +267,11 @@ def calculate_vortex_strengths(self):
:return: None
"""
# Solve for the strength of each panel's vortex.
- self.vortex_strengths = np.linalg.solve(
- self.wing_wing_influences, -self.freestream_wing_influences
- )
+ self.vortex_strengths = np.linalg.solve(self.wing_wing_influences,
+ -self.freestream_wing_influences)
# Iterate through the panels and update their vortex strengths.
for panel_num, panel in enumerate(self.panels):
-
# Update this panel's horseshoe vortex strength.
panel.horseshoe_vortex.update_strength(self.vortex_strengths[panel_num])
@@ -328,8 +303,7 @@ def calculate_solution_velocity(self, points):
front_right_vortex_vertices=self.panel_front_right_vortex_vertices,
front_left_vortex_vertices=self.panel_front_left_vortex_vertices,
back_left_vortex_vertices=self.panel_back_left_vortex_vertices,
- strengths=self.vortex_strengths,
- )
+ strengths=self.vortex_strengths, )
return induced_velocities + self.freestream_velocity
@@ -344,27 +318,21 @@ def calculate_near_field_forces_and_moments(self):
"""
# Calculate the total velocity at every panel's bound vortex center.
total_velocities = self.calculate_solution_velocity(
- points=self.panel_bound_vortex_centers
- )
+ points=self.panel_bound_vortex_centers)
# Calculate the near field force, in geometry axes, on each panel's bound
# vortex.
near_field_forces_geometry_axes = (
- self.operating_point.density
- * np.expand_dims(self.vortex_strengths, axis=1)
- * np.cross(total_velocities, self.panel_bound_vortex_vectors, axis=-1)
- )
+ self.operating_point.density * np.expand_dims(self.vortex_strengths,
+ axis=1) * np.cross(
+ total_velocities, self.panel_bound_vortex_vectors, axis=-1))
# Calculate the near field moments, in geometry axes, on each panel's bound
# vortex.
near_field_moments_geometry_axes = np.cross(
self.panel_bound_vortex_centers - self.panel_moment_references,
- near_field_forces_geometry_axes,
- axis=-1,
- )
+ near_field_forces_geometry_axes, axis=-1, )
- functions.process_steady_solver_forces(
- steady_solver=self,
+ functions.process_steady_solver_forces(steady_solver=self,
near_field_forces_geometry_axes=near_field_forces_geometry_axes,
- near_field_moments_geometry_axes=near_field_moments_geometry_axes,
- )
+ near_field_moments_geometry_axes=near_field_moments_geometry_axes, )
diff --git a/pterasoftware/steady_ring_vortex_lattice_method.py b/pterasoftware/steady_ring_vortex_lattice_method.py
index 2d1e86cd..ea03cf30 100644
--- a/pterasoftware/steady_ring_vortex_lattice_method.py
+++ b/pterasoftware/steady_ring_vortex_lattice_method.py
@@ -79,8 +79,7 @@ def __init__(self, steady_problem):
# Initialize attributes to hold aerodynamic data that pertains to this problem.
self.wing_wing_influences = np.zeros((self.num_panels, self.num_panels))
self.freestream_velocity = (
- self.operating_point.calculate_freestream_velocity_geometry_axes()
- )
+ self.operating_point.calculate_freestream_velocity_geometry_axes())
self.freestream_wing_influences = np.zeros(self.num_panels)
self.vortex_strengths = np.ones(self.num_panels)
self.panel_normal_directions = np.zeros((self.num_panels, 3))
@@ -133,8 +132,7 @@ def run(self, logging_level="Warning"):
"""
# Configure the problem's logger.
logging_level_value = functions.convert_logging_level_name_to_value(
- logging_level
- )
+ logging_level)
logging.basicConfig(level=logging_level_value)
# Initialize this problem's panels to have vortices congruent with this
@@ -191,8 +189,7 @@ def initialize_panel_vortices(self):
"""
# Find the freestream direction in geometry axes.
freestream_direction = (
- self.operating_point.calculate_freestream_direction_geometry_axes()
- )
+ self.operating_point.calculate_freestream_direction_geometry_axes())
# Iterate through each airplane's wings.
for airplane in self.airplanes:
@@ -219,21 +216,16 @@ def initialize_panel_vortices(self):
# whether the panel is along the trailing edge or not.
if not panel.is_trailing_edge:
next_chordwise_panel = wing.panels[
- chordwise_position + 1, spanwise_position
- ]
+ chordwise_position + 1, spanwise_position]
back_left_vortex_vertex = (
- next_chordwise_panel.front_left_vortex_vertex
- )
+ next_chordwise_panel.front_left_vortex_vertex)
back_right_vortex_vertex = (
- next_chordwise_panel.front_right_vortex_vertex
- )
+ next_chordwise_panel.front_right_vortex_vertex)
else:
back_left_vortex_vertex = front_left_vortex_vertex + (
- panel.back_left_vertex - panel.front_left_vertex
- )
+ panel.back_left_vertex - panel.front_left_vertex)
back_right_vortex_vertex = front_right_vortex_vertex + (
- panel.back_right_vertex - panel.front_right_vertex
- )
+ panel.back_right_vertex - panel.front_right_vertex)
# If the panel is along the trailing edge, initialize its
# horseshoe vortex.
@@ -242,17 +234,14 @@ def initialize_panel_vortices(self):
finite_leg_termination=back_left_vortex_vertex,
strength=None,
infinite_leg_direction=freestream_direction,
- infinite_leg_length=infinite_leg_length,
- )
+ infinite_leg_length=infinite_leg_length, )
# Initialize the panel's ring vortex.
panel.ring_vortex = aerodynamics.RingVortex(
front_right_vertex=front_right_vortex_vertex,
front_left_vertex=front_left_vortex_vertex,
back_left_vertex=back_left_vortex_vertex,
- back_right_vertex=back_right_vortex_vertex,
- strength=None,
- )
+ back_right_vertex=back_right_vortex_vertex, strength=None, )
def collapse_geometry(self):
"""This method converts attributes of the problem's geometry into 1D
@@ -276,30 +265,23 @@ def collapse_geometry(self):
# Update the solver's list of attributes with this panel's
# attributes.
- functions.update_ring_vortex_solvers_panel_attributes(
- solver=self,
- global_panel_position=global_panel_position,
- panel=panel,
- airplane=airplane,
- )
+ functions.update_ring_vortex_solvers_panel_attributes(solver=self,
+ global_panel_position=global_panel_position, panel=panel,
+ airplane=airplane, )
if panel.is_trailing_edge:
-
# Also, update the attribute lists horseshoe vortex
# attributes at this position with this panel's horseshoe
# vortex attributes
self.horseshoe_vortex_back_right_vertex[
- global_panel_position
- ] = panel.horseshoe_vortex.right_leg.origin
+ global_panel_position] = (
+ panel.horseshoe_vortex.right_leg.origin)
self.horseshoe_vortex_front_right_vertex[
- global_panel_position
- ] = panel.horseshoe_vortex.right_leg.termination
+ global_panel_position] = panel.horseshoe_vortex.right_leg.termination
self.horseshoe_vortex_front_left_vertex[
- global_panel_position
- ] = panel.horseshoe_vortex.left_leg.origin
+ global_panel_position] = panel.horseshoe_vortex.left_leg.origin
self.horseshoe_vortex_back_left_vertex[
- global_panel_position
- ] = panel.horseshoe_vortex.left_leg.termination
+ global_panel_position] = panel.horseshoe_vortex.left_leg.termination
# Set the horseshoe vortex strength at this position to 1.0.
# This will be updated after the correct vortex strengths are
@@ -325,8 +307,7 @@ def calculate_wing_wing_influences(self):
front_right_vortex_vertices=self.panel_front_right_vortex_vertices,
front_left_vortex_vertices=self.panel_front_left_vortex_vertices,
back_left_vortex_vertices=self.panel_back_left_vortex_vertices,
- strengths=self.vortex_strengths,
- )
+ strengths=self.vortex_strengths, )
# Find the matrix of normalized velocities induced at every panel's
# collocation point by every panel's horseshoe vortex. The answer is
@@ -342,9 +323,7 @@ def calculate_wing_wing_influences(self):
front_right_vortex_vertices=self.horseshoe_vortex_front_right_vertex,
front_left_vortex_vertices=self.horseshoe_vortex_front_left_vertex,
back_left_vortex_vertices=self.horseshoe_vortex_back_left_vertex,
- strengths=self.horseshoe_vortex_strengths,
- )
- )
+ strengths=self.horseshoe_vortex_strengths, ))
# Calculate the total normalized influences, which is the sum of the
# influences by the ring vortices and by the horseshoe vortices.
@@ -353,11 +332,8 @@ def calculate_wing_wing_influences(self):
# Take the batch dot product of the normalized velocities with each panel's
# normal direction. This is now the problem's matrix of wing-wing influence
# coefficients.
- self.wing_wing_influences = np.einsum(
- "...k,...k->...",
- total_influences,
- np.expand_dims(self.panel_normal_directions, axis=1),
- )
+ self.wing_wing_influences = np.einsum("...k,...k->...", total_influences,
+ np.expand_dims(self.panel_normal_directions, axis=1), )
def calculate_vortex_strengths(self):
"""Solve for each panel's vortex strengths.
@@ -365,9 +341,8 @@ def calculate_vortex_strengths(self):
:return: None
"""
# Solve for the strength of each panel's vortex.
- self.vortex_strengths = np.linalg.solve(
- self.wing_wing_influences, -self.freestream_wing_influences
- )
+ self.vortex_strengths = np.linalg.solve(self.wing_wing_influences,
+ -self.freestream_wing_influences)
# Iterate through the panels and update their vortex strengths.
for panel_num in range(self.panels.size):
@@ -383,8 +358,7 @@ def calculate_vortex_strengths(self):
# Update the panel's horseshoe vortex strength.
panel.horseshoe_vortex.update_strength(self.vortex_strengths[panel_num])
self.horseshoe_vortex_strengths[panel_num] = self.vortex_strengths[
- panel_num
- ]
+ panel_num]
def calculate_solution_velocity(self, points):
"""This function takes in a group of points. At every point, it finds the
@@ -416,8 +390,7 @@ def calculate_solution_velocity(self, points):
front_right_vortex_vertices=self.panel_front_right_vortex_vertices,
front_left_vortex_vertices=self.panel_front_left_vortex_vertices,
back_left_vortex_vertices=self.panel_back_left_vortex_vertices,
- strengths=self.vortex_strengths,
- )
+ strengths=self.vortex_strengths, )
# Find the matrix of velocities induced at every panel's collocation point by
# every panel's horseshoe vortex. This can be called in a batch fashion,
@@ -426,15 +399,12 @@ def calculate_solution_velocity(self, points):
# zero, which eliminates their effects. The effect of every horseshoe vortex
# on each point will be summed.
horseshoe_vortex_influences = (
- aerodynamics.collapsed_velocities_from_horseshoe_vortices(
- points=points,
+ aerodynamics.collapsed_velocities_from_horseshoe_vortices(points=points,
back_right_vortex_vertices=self.horseshoe_vortex_back_right_vertex,
front_right_vortex_vertices=self.horseshoe_vortex_front_right_vertex,
front_left_vortex_vertices=self.horseshoe_vortex_front_left_vertex,
back_left_vortex_vertices=self.horseshoe_vortex_back_left_vertex,
- strengths=self.horseshoe_vortex_strengths,
- )
- )
+ strengths=self.horseshoe_vortex_strengths, ))
# Find the total influence of the vortices, which is the sum of the influence
# due to the ring vortices and the horseshoe vortices.
@@ -483,25 +453,21 @@ def calculate_near_field_forces_and_moments(self):
# Change the effective right vortex line strength from zero
# to this panel's ring vortex's strength.
effective_right_vortex_line_strengths[global_panel_position] = (
- self.vortex_strengths[global_panel_position]
- )
+ self.vortex_strengths[global_panel_position])
else:
# Get the panel directly to the right of this panel.
panel_to_right = wing.panels[
- panel.local_chordwise_position,
- panel.local_spanwise_position + 1,
- ]
+ panel.local_chordwise_position, panel.local_spanwise_position + 1,]
# Change the effective right vortex line strength from zero
# to the difference between this panel's ring vortex's
# strength, and the ring vortex strength of the panel to the
# right of it.
effective_right_vortex_line_strengths[global_panel_position] = (
- self.vortex_strengths[global_panel_position]
- - panel_to_right.ring_vortex.strength
- )
+ self.vortex_strengths[
+ global_panel_position] - panel_to_right.ring_vortex.strength)
# Check if this panel is on its wing's leading edge.
if panel.is_leading_edge:
@@ -509,24 +475,20 @@ def calculate_near_field_forces_and_moments(self):
# Change the effective front vortex line strength from zero
# to this panel's ring vortex's strength.
effective_front_vortex_line_strengths[global_panel_position] = (
- self.vortex_strengths[global_panel_position]
- )
+ self.vortex_strengths[global_panel_position])
else:
# Get the panel directly in front of this panel.
panel_to_front = wing.panels[
- panel.local_chordwise_position - 1,
- panel.local_spanwise_position,
- ]
+ panel.local_chordwise_position - 1, panel.local_spanwise_position,]
# Change the effective front vortex line strength from zero
# to the difference between this panel's ring vortex's
# strength, and the ring vortex strength of the panel in
# front of it.
effective_front_vortex_line_strengths[global_panel_position] = (
- self.vortex_strengths[global_panel_position]
- - panel_to_front.ring_vortex.strength
- )
+ self.vortex_strengths[
+ global_panel_position] - panel_to_front.ring_vortex.strength)
# Check if this panel is on its wing's left edge.
if panel.is_left_edge:
@@ -534,23 +496,19 @@ def calculate_near_field_forces_and_moments(self):
# Change the effective left vortex line strength from zero to
# this panel's ring vortex's strength.
effective_left_vortex_line_strengths[global_panel_position] = (
- self.vortex_strengths[global_panel_position]
- )
+ self.vortex_strengths[global_panel_position])
else:
# Get the panel directly to the left of this panel.
panel_to_left = wing.panels[
- panel.local_chordwise_position,
- panel.local_spanwise_position - 1,
- ]
+ panel.local_chordwise_position, panel.local_spanwise_position - 1,]
# Change the effective left vortex line strength from zero to
# the difference between this panel's ring vortex's strength,
# and the ring vortex strength of the panel to the left of it.
effective_left_vortex_line_strengths[global_panel_position] = (
- self.vortex_strengths[global_panel_position]
- - panel_to_left.ring_vortex.strength
- )
+ self.vortex_strengths[
+ global_panel_position] - panel_to_left.ring_vortex.strength)
# Increment the global panel position.
global_panel_position += 1
@@ -558,82 +516,53 @@ def calculate_near_field_forces_and_moments(self):
# Calculate the solution velocities at the centers of the panel's front leg,
# left leg, and right leg.
velocities_at_ring_vortex_front_leg_centers = self.calculate_solution_velocity(
- points=self.panel_front_vortex_centers
- )
+ points=self.panel_front_vortex_centers)
velocities_at_ring_vortex_left_leg_centers = self.calculate_solution_velocity(
- points=self.panel_left_vortex_centers
- )
+ points=self.panel_left_vortex_centers)
velocities_at_ring_vortex_right_leg_centers = self.calculate_solution_velocity(
- points=self.panel_right_vortex_centers
- )
+ points=self.panel_right_vortex_centers)
# Using the effective line vortex strengths, and the Kutta-Joukowski theorem
# to find the near field force in geometry axes on the front leg, left leg,
# and right leg.
near_field_forces_on_ring_vortex_right_legs_geometry_axes = (
- self.operating_point.density
- * np.expand_dims(effective_right_vortex_line_strengths, axis=1)
- * np.cross(
- velocities_at_ring_vortex_right_leg_centers,
- self.panel_right_vortex_vectors,
- axis=-1,
- )
- )
+ self.operating_point.density * np.expand_dims(
+ effective_right_vortex_line_strengths, axis=1) * np.cross(
+ velocities_at_ring_vortex_right_leg_centers,
+ self.panel_right_vortex_vectors, axis=-1, ))
near_field_forces_on_ring_vortex_front_legs_geometry_axes = (
- self.operating_point.density
- * np.expand_dims(effective_front_vortex_line_strengths, axis=1)
- * np.cross(
- velocities_at_ring_vortex_front_leg_centers,
- self.panel_front_vortex_vectors,
- axis=-1,
- )
- )
+ self.operating_point.density * np.expand_dims(
+ effective_front_vortex_line_strengths, axis=1) * np.cross(
+ velocities_at_ring_vortex_front_leg_centers,
+ self.panel_front_vortex_vectors, axis=-1, ))
near_field_forces_on_ring_vortex_left_legs_geometry_axes = (
- self.operating_point.density
- * np.expand_dims(effective_left_vortex_line_strengths, axis=1)
- * np.cross(
- velocities_at_ring_vortex_left_leg_centers,
- self.panel_left_vortex_vectors,
- axis=-1,
- )
- )
+ self.operating_point.density * np.expand_dims(
+ effective_left_vortex_line_strengths, axis=1) * np.cross(
+ velocities_at_ring_vortex_left_leg_centers, self.panel_left_vortex_vectors,
+ axis=-1, ))
# Sum the forces on the legs to calculate the total near field force,
# in geometry axes, on each panel.
near_field_forces_geometry_axes = (
- near_field_forces_on_ring_vortex_front_legs_geometry_axes
- + near_field_forces_on_ring_vortex_left_legs_geometry_axes
- + near_field_forces_on_ring_vortex_right_legs_geometry_axes
- )
+ near_field_forces_on_ring_vortex_front_legs_geometry_axes + near_field_forces_on_ring_vortex_left_legs_geometry_axes + near_field_forces_on_ring_vortex_right_legs_geometry_axes)
# Find the near field moment in geometry axes on the front leg, left leg,
# and right leg.
near_field_moments_on_ring_vortex_front_legs_geometry_axes = np.cross(
self.panel_front_vortex_centers - self.panel_moment_references,
- near_field_forces_on_ring_vortex_front_legs_geometry_axes,
- axis=-1,
- )
+ near_field_forces_on_ring_vortex_front_legs_geometry_axes, axis=-1, )
near_field_moments_on_ring_vortex_left_legs_geometry_axes = np.cross(
self.panel_left_vortex_centers - self.panel_moment_references,
- near_field_forces_on_ring_vortex_left_legs_geometry_axes,
- axis=-1,
- )
+ near_field_forces_on_ring_vortex_left_legs_geometry_axes, axis=-1, )
near_field_moments_on_ring_vortex_right_legs_geometry_axes = np.cross(
self.panel_right_vortex_centers - self.panel_moment_references,
- near_field_forces_on_ring_vortex_right_legs_geometry_axes,
- axis=-1,
- )
+ near_field_forces_on_ring_vortex_right_legs_geometry_axes, axis=-1, )
# Sum the moments on the legs to calculate the total near field moment,
# in geometry axes, on each panel.
near_field_moments_geometry_axes = (
- near_field_moments_on_ring_vortex_front_legs_geometry_axes
- + near_field_moments_on_ring_vortex_left_legs_geometry_axes
- + near_field_moments_on_ring_vortex_right_legs_geometry_axes
- )
+ near_field_moments_on_ring_vortex_front_legs_geometry_axes + near_field_moments_on_ring_vortex_left_legs_geometry_axes + near_field_moments_on_ring_vortex_right_legs_geometry_axes)
- functions.process_steady_solver_forces(
- steady_solver=self,
+ functions.process_steady_solver_forces(steady_solver=self,
near_field_forces_geometry_axes=near_field_forces_geometry_axes,
- near_field_moments_geometry_axes=near_field_moments_geometry_axes,
- )
+ near_field_moments_geometry_axes=near_field_moments_geometry_axes, )
diff --git a/pterasoftware/trim.py b/pterasoftware/trim.py
index dd4d33b2..9d558f88 100644
--- a/pterasoftware/trim.py
+++ b/pterasoftware/trim.py
@@ -31,21 +31,13 @@
from . import movement
from . import problems
-
trim_logger = logging.getLogger("trim")
trim_logger.setLevel(logging.DEBUG)
# ToDo: Document this function.
-def analyze_steady_trim(
- problem,
- velocity_bounds,
- alpha_bounds,
- beta_bounds,
- external_thrust_bounds,
- objective_cut_off=0.01,
- num_calls=100,
-):
+def analyze_steady_trim(problem, velocity_bounds, alpha_bounds, beta_bounds,
+ external_thrust_bounds, objective_cut_off=0.01, num_calls=100, ):
"""This function attempts to calculate a trim condition of a steady solver by
varying the operating point's velocity, angle of attack, angle of sideslip,
and external thrust until the net force and net moment on the aircraft are
@@ -56,8 +48,7 @@ def analyze_steady_trim(
"""
if len(problem.airplanes) != 1:
trim_logger.error(
- "The problem objects for trim analyses must have only one airplane."
- )
+ "The problem objects for trim analyses must have only one airplane.")
weight = problem.airplanes[0].weight
base_velocity = problem.operating_point.velocity
@@ -68,24 +59,18 @@ def analyze_steady_trim(
if base_velocity < velocity_bounds[0] or base_velocity > velocity_bounds[1]:
raise Exception(
"The operating point's velocity must be within the specified velocity "
- "bounds."
- )
+ "bounds.")
if base_alpha < alpha_bounds[0] or base_alpha > alpha_bounds[1]:
raise Exception(
- "The operating point's alpha must be within the specified alpha bounds."
- )
+ "The operating point's alpha must be within the specified alpha bounds.")
if base_beta < beta_bounds[0] or base_beta > beta_bounds[1]:
raise Exception(
- "The operating point's beta must be within the specified beta bounds."
- )
- if (
- base_external_thrust < external_thrust_bounds[0]
- or base_external_thrust > external_thrust_bounds[1]
- ):
+ "The operating point's beta must be within the specified beta bounds.")
+ if (base_external_thrust < external_thrust_bounds[0] or base_external_thrust >
+ external_thrust_bounds[1]):
raise Exception(
"The operating point's external thrust must be within the specified "
- "external thrust bounds."
- )
+ "external thrust bounds.")
current_arguments = [np.nan, np.nan, np.nan, np.nan]
@@ -111,21 +96,18 @@ def objective_function(arguments):
external_forces = np.array([external_thrust, 0, weight])
external_force_coefficients = external_forces / dynamic_pressure / s_ref
- solver = steady_horseshoe_vortex_lattice_method.SteadyHorseshoeVortexLatticeMethodSolver(
- steady_problem=problem
- )
+ solver = (steady_horseshoe_vortex_lattice_method
+ .SteadyHorseshoeVortexLatticeMethodSolver(
+ steady_problem=problem))
solver.run()
airplane = solver.airplanes[0]
net_force_coefficient = np.linalg.norm(
- airplane.total_near_field_force_coefficients_wind_axes
- - external_force_coefficients
- )
+ airplane.total_near_field_force_coefficients_wind_axes - external_force_coefficients)
net_moment_coefficient = np.linalg.norm(
- airplane.total_near_field_moment_coefficients_wind_axes
- )
+ airplane.total_near_field_moment_coefficients_wind_axes)
objective = (abs(net_force_coefficient) + abs(net_moment_coefficient)) / 2
@@ -136,15 +118,7 @@ def objective_function(arguments):
o_str = str(round(objective, 3))
state_msg = (
- "State: velocity="
- + v_str
- + ", alpha="
- + a_str
- + ", beta="
- + b_str
- + ", external thrust="
- + t_str
- )
+ "State: velocity=" + v_str + ", alpha=" + a_str + ", beta=" + b_str + ", external thrust=" + t_str)
obj_msg = "Objective: " + o_str
trim_logger.info(state_msg)
@@ -159,58 +133,36 @@ def objective_function(arguments):
return objective
initial_guess = np.array(
- [base_velocity, base_alpha, base_beta, base_external_thrust]
- )
+ [base_velocity, base_alpha, base_beta, base_external_thrust])
bounds = (velocity_bounds, alpha_bounds, beta_bounds, external_thrust_bounds)
trim_logger.info("Starting local search.")
try:
- scipy.optimize.minimize(
- fun=objective_function,
- x0=initial_guess,
- bounds=bounds,
- method="L-BFGS-B",
- options={"maxfun": num_calls, "eps": 0.01},
- )
+ scipy.optimize.minimize(fun=objective_function, x0=initial_guess, bounds=bounds,
+ method="L-BFGS-B", options={"maxfun": num_calls, "eps": 0.01}, )
except StopIteration:
trim_logger.info("Acceptable value reached with local search.")
return current_arguments
trim_logger.warning(
- "No acceptable value reached with local search. Starting global search."
- )
+ "No acceptable value reached with local search. Starting global search.")
try:
- scipy.optimize.dual_annealing(
- func=objective_function,
- bounds=bounds,
- x0=initial_guess,
- maxfun=num_calls,
- minimizer_kwargs={
- "method": "L-BFGS-B",
- "options": {"maxfun": num_calls, "eps": 0.01},
- },
- )
+ scipy.optimize.dual_annealing(func=objective_function, bounds=bounds,
+ x0=initial_guess, maxfun=num_calls, minimizer_kwargs={"method": "L-BFGS-B",
+ "options": {"maxfun": num_calls, "eps": 0.01}, }, )
except StopIteration:
trim_logger.info("Acceptable global minima found.")
return current_arguments
trim_logger.critical(
"No trim condition found. Try increasing the bounds and the maximum number of "
- "iterations."
- )
+ "iterations.")
return [np.nan, np.nan, np.nan, np.nan]
# ToDo: Document this function.
-def analyze_unsteady_trim(
- airplane_movement,
- operating_point,
- velocity_bounds,
- alpha_bounds,
- beta_bounds,
- objective_cut_off=0.01,
- num_calls=100,
-):
+def analyze_unsteady_trim(airplane_movement, operating_point, velocity_bounds,
+ alpha_bounds, beta_bounds, objective_cut_off=0.01, num_calls=100, ):
"""This function attempts to calculate a trim condition of an unsteady solver by
varying the operating point's velocity, angle of attack, angle of sideslip,
and external thrust until the net cycle-averaged force and net cycle-averaged
@@ -227,16 +179,13 @@ def analyze_unsteady_trim(
if base_velocity < velocity_bounds[0] or base_velocity > velocity_bounds[1]:
trim_logger.error(
"The operating point's velocity must be within the specified velocity "
- "bounds."
- )
+ "bounds.")
if base_alpha < alpha_bounds[0] or base_alpha > alpha_bounds[1]:
trim_logger.error(
- "The operating point's alpha must be within the specified alpha bounds."
- )
+ "The operating point's alpha must be within the specified alpha bounds.")
if base_beta < beta_bounds[0] or base_beta > beta_bounds[1]:
trim_logger.error(
- "The operating point's beta must be within the specified beta bounds."
- )
+ "The operating point's beta must be within the specified beta bounds.")
current_arguments = [np.nan, np.nan, np.nan]
@@ -263,36 +212,27 @@ def objective_function(arguments):
external_force_coefficients = external_forces / dynamic_pressure / s_ref
operating_point_movement = movement.OperatingPointMovement(
- base_operating_point=operating_point
- )
+ base_operating_point=operating_point)
- this_movement = movement.Movement(
- airplane_movements=[airplane_movement],
- operating_point_movement=operating_point_movement,
- )
+ this_movement = movement.Movement(airplane_movements=[airplane_movement],
+ operating_point_movement=operating_point_movement, )
- this_problem = problems.UnsteadyProblem(
- movement=this_movement, only_final_results=True
- )
+ this_problem = problems.UnsteadyProblem(movement=this_movement,
+ only_final_results=True)
this_solver = (
unsteady_ring_vortex_lattice_method.UnsteadyRingVortexLatticeMethodSolver(
- unsteady_problem=this_problem
- )
- )
+ unsteady_problem=this_problem))
this_solver.run(logging_level="Critical")
force_coefficients = (
- this_solver.unsteady_problem.final_total_near_field_force_coefficients_wind_axes
- )
+ this_solver.unsteady_problem.final_total_near_field_force_coefficients_wind_axes)
moment_coefficients = (
- this_solver.unsteady_problem.final_total_near_field_moment_coefficients_wind_axes
- )
+ this_solver.unsteady_problem.final_total_near_field_moment_coefficients_wind_axes)
net_force_coefficients = np.linalg.norm(
- force_coefficients - external_force_coefficients
- )
+ force_coefficients - external_force_coefficients)
net_moment_coefficients = np.linalg.norm(moment_coefficients)
objective = (abs(net_force_coefficients) + abs(net_moment_coefficients)) / 2
@@ -321,37 +261,23 @@ def objective_function(arguments):
trim_logger.info("Starting local search.")
try:
- scipy.optimize.minimize(
- fun=objective_function,
- x0=initial_guess,
- bounds=bounds,
- method="L-BFGS-B",
- options={"maxfun": num_calls, "eps": 0.01},
- )
+ scipy.optimize.minimize(fun=objective_function, x0=initial_guess, bounds=bounds,
+ method="L-BFGS-B", options={"maxfun": num_calls, "eps": 0.01}, )
except StopIteration:
trim_logger.info("Acceptable value reached with local search.")
return current_arguments
trim_logger.warning(
- "No acceptable value reached with local search. Starting global search."
- )
+ "No acceptable value reached with local search. Starting global search.")
try:
- scipy.optimize.dual_annealing(
- func=objective_function,
- bounds=bounds,
- x0=initial_guess,
- maxfun=num_calls,
- minimizer_kwargs={
- "method": "L-BFGS-B",
- "options": {"maxfun": num_calls, "eps": 0.01},
- },
- )
+ scipy.optimize.dual_annealing(func=objective_function, bounds=bounds,
+ x0=initial_guess, maxfun=num_calls, minimizer_kwargs={"method": "L-BFGS-B",
+ "options": {"maxfun": num_calls, "eps": 0.01}, }, )
except StopIteration:
trim_logger.info("Acceptable global minima found.")
return current_arguments
trim_logger.critical(
"No trim condition found. Try increasing the bounds and the maximum number of "
- "iterations."
- )
+ "iterations.")
return [np.nan, np.nan, np.nan]
diff --git a/pterasoftware/ui_resources/main_window.py b/pterasoftware/ui_resources/main_window.py
index 653360a6..a8450c28 100644
--- a/pterasoftware/ui_resources/main_window.py
+++ b/pterasoftware/ui_resources/main_window.py
@@ -1208,7 +1208,8 @@ def retranslateUi(self, MainWindowDesign):
self.Logo.setText(
QCoreApplication.translate(
"MainWindowDesign",
- '
![](docs/Black_Text_Logo.png)
',
+ "![]()
',
None,
)
)
diff --git a/pterasoftware/ui_resources/main_window.ui b/pterasoftware/ui_resources/main_window.ui
index 8ce09d1a..5ada5e78 100644
--- a/pterasoftware/ui_resources/main_window.ui
+++ b/pterasoftware/ui_resources/main_window.ui
@@ -1,1362 +1,1788 @@
- MainWindowDesign
-
-
-
- 0
- 0
- 1145
- 880
-
-
-
-
- 0
- 0
-
-
-
-
- 1052
- 880
-
-
-
- MainWindow
-
-
-
- -
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- -1
-
-
- 0
-
-
-
- Aircraft Parameters
-
-
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 12
- 75
- true
-
+ MainWindowDesign
+
+
+
+ 0
+ 0
+ 1145
+ 880
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 1052
+ 880
+
+
+
+ MainWindow
+
+
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ -1
+
+
+ 0
+
+
+
+ Aircraft Parameters
+
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Aircraft
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Name
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ CofG Position
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 10
+
+
+
+ x
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 149
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 10
+
+
+
+ y
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 149
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Z
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 149
+ 0
+
+
+
+
+ -
+
+
+ Other Options go here
+
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Save Aircraft
+
+
+
+
+
+ -
+
+
+
+
+
+
-
+
+
+ x
+
+
+
+ -
+
+
+ y
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Leading Edge Location
+
+
+
+
+ -
+
+
+ -33.000000000000000
+
+
+
+ 45.000000000000000
+
+
+
+
+ -
+
+
+
+
+
+ 49.000000000000000
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Number of Panels
+
+
+
+
+ -
+
+
+ 49.000000000000000
+
+
+
+
+ -
+
+
+ Symmetric?
+
+
+
+ -
+
+
+ Panel Spacing Option
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Chord-wise Panels
+
+
+
+
+ -
+
+
-
+
+ Uniform
+
+
+ -
+
+ Cosine
+
+
+ -
+
+ Reverse Cosine
+
+
+
+
+
+ -
+
+
+ <html><head/><body><p>z</p></body></html>
+
+
+
+ -
+
+
+ -50.000000000000000
+
+
+
+ 44.000000000000000
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Qt::PreventContextMenu
+
+
+
+ QFrame::Sunken
+
+
+ 1
+
+
+ Main Wing
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 1
+
+
+
+
+ 318
+ 0
+
+
+
+ Wing Root Cross Section
+
+
+
-
+
+
+
+
+
+
-
+
+
+
+ 49.000000000000000
+
+
+
+
+ -
+
+
+
+ -50.000000000000000
+
+
+
+
+ 44.000000000000000
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+ 0
+
+ 0
+
+
+
+
+ Number
+ of Panels
+
+
+
+
+ -
+
+
+ x
+
+
+
+
+ -
+
+
+
+
+ 10
+
+ 75
+
+ true
+
+
+
+
+ Chord
+ and Control
+ Surface
+
+
+
+
+ -
+
+
+ Chord
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+ Control
+ Surface
+ Deflection
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ y
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ 10
+
+ 75
+
+ true
+
+
+
+
+
+ Span-wise
+ panels
+
+
+
+
+ -
+
+
+ <html><head/><body><p>z</p></body></html>
+
+
+
+ -
+
+
+ Panel
+ Spacing
+ Option
+
+
+
+
+ -
+
+
+
+ -33.000000000000000
+
+
+
+
+ 45.000000000000000
+
+
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ 10
+
+ 75
+
+ true
+
+
+
+
+ Leading
+ Edge
+ Location
+
+
+
+
+ -
+
+
+ Control
+ Surface
+ Hinge Point
+
+
+
+
+ -
+
+
+
+
+
+
+ 49.000000000000000
+
+
+
+
+ -
+
+
-
+
+
+ Uniform
+
+
+
+ -
+
+
+ Cosine
+
+
+
+ -
+
+
+ Reverse
+ Cosine
+
+
+
+
+
+ -
+
+
+
+ Symmetric?
+
+
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ 12
+
+ 75
+
+ true
+
+
+
+
+
+ Qt::PreventContextMenu
+
+
+
+
+ QFrame::Sunken
+
+
+
+ 1
+
+
+
+ Root
+ Cross
+ Section
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+ 0
+
+
+
+
+ Aerofoil
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
+ Wing Tip Cross Section
+
+
+ -
+
+
+
+
+
+
-
+
+
+ -
+
+
+
+ 49.000000000000000
+
+
+
+
+ -
+
+
+ y
+
+
+
+
+ -
+
+
+ Panel
+ Spacing
+ Option
+
+
+
+
+ -
+
+
+
+
+
+
+ 49.000000000000000
+
+
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+ 0
+
+ 0
+
+
+
+
+ Number
+ of Panels
+
+
+
+
+ -
+
+
-
+
+
+ Uniform
+
+
+
+ -
+
+
+ Cosine
+
+
+
+ -
+
+
+ Reverse
+ Cosine
+
+
+
+
+
+ -
+
+
+
+
+ 10
+
+ 75
+
+ true
+
+
+
+
+ Chord
+ and Control
+ Surface
+
+
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ 12
+
+ 75
+
+ true
+
+
+
+
+
+ Qt::PreventContextMenu
+
+
+
+
+ QFrame::Sunken
+
+
+
+ 1
+
+
+
+ Root
+ Cross
+ Section
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+ -
+
+
+ Control
+ Surface
+ Hinge Point
+
+
+
+
+ -
+
+
+
+ -50.000000000000000
+
+
+
+
+ 44.000000000000000
+
+
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ 10
+
+ 75
+
+ true
+
+
+
+
+ Leading
+ Edge
+ Location
+
+
+
+
+ -
+
+
+
+ Symmetric?
+
+
+
+
+ -
+
+
+ x
+
+
+
+
+ -
+
+
+ Chord
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ 10
+
+ 75
+
+ true
+
+
+
+
+
+ Span-wise
+ Panels
+
+
+
+
+ -
+
+
+ <html><head/><body><p>z</p></body></html>
+
+
+
+ -
+
+
+ -
+
+
+
+ -33.000000000000000
+
+
+
+
+ 45.000000000000000
+
+
+
+
+ -
+
+
+ -
+
+
+ Control
+ Surface
+ Deflection
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+ -
+
+
+
+ Aerofoil
+
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Model
+
+
+ -
+
+
+ Controller
+
+
+
+
+
+
+
+
+ Materials
+
+
+
+
+ Boundary Conditions
+
+
+
+
+ Solution
+
+
+
+
+ Visualiser Settings
+
+
+
+
+ 0
+ 0
+ 331
+ 235
+
+
+
+
+
+
+ -
+
+
+ Move
+
+
+
+ -
+
+
+ 49.000000000000000
+
+
+
+ -
+
+
+ Homing
+
+
+
+ -
+
+
+ -50.000000000000000
+
+
+ 44.000000000000000
+
+
+
+ -
+
+
+ -33.000000000000000
+
+
+ 45.000000000000000
+
+
+
+ -
+
+
+
+
+
+ 49.000000000000000
+
+
+
+ -
+
+
+ -45.000000000000000
+
+
+ 0.000000000000000
+
+
+
+ -
+
+
+ Injection
+
+
+
+ -
+
+
+ x
+
+
+
+ -
+
+
+ y
+
+
+
+ -
+
+
+ <html><head/><body><p>z</p></body></html>
+
+
+
+ -
+
+
+ <html><head/><body><p>β</p></body></html>
+
+
+
+ -
+
+
+ d
+
+
+
+
+
+
+
+
+ -
+
+
+ false
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ <html><head/><body><p><img
+ src="docs/Black_Text_Logo.png"/></p></body></html>
+
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 24
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Qt::NoContextMenu
+
+
+ Generate Results
+
+
+
+ -
+
+
+ Plot Visualisation
+
+
+
+ -
+
+
+ Terminal Output
+
+
+
+ -
+
+
+
+ 5
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
- Aircraft
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
+ About
+
+
- Name
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
+ Manual
+
+
- CofG Position
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
-
+ Quit
+
+
- x
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 149
- 0
-
+ Import Data
-
-
- -
-
-
-
- 0
- 0
-
+
+
+
+ Export Data
-
-
- 10
-
+
+
+
+ Preset Aircraft List
+
+
- y
+ Example 1: Analyze steady trim example
-
-
- -
-
-
-
- 0
- 0
-
+
+
+
+ Example 2: Analyze unsteady trim example
-
-
- 149
- 0
-
+
+
+
+ Example 3: Steady convergence example
-
-
- -
-
-
-
- 0
- 0
-
+
+
+
+ Example 4: Steady horseshoe vortex lattice method solver
+
+
+
- Z
+ Example 5: Steady ring vortex lattice method solver static
+
-
-
- -
-
-
-
- 0
- 0
-
+
+
+
+ Example 6: Unsteady ring vortex lattice method solver static
+
-
-
- 149
- 0
-
+
+
+
+ Example 7: Unsteady ring vortex lattice method solver variable
+
-
-
- -
-
+
+
- Other Options go here
+ Example 8: Unsteady ring vortex lattice method solver variable
+ formation
+
-
- Qt::AlignCenter
+
+
+
+ Example 9: Unsteady static convergence example
-
-
- -
-
+
+
- Save Aircraft
+ Example 10: Unsteady variable convergence example
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
- x
-
-
-
- -
-
-
- y
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
-
-
- Leading Edge Location
-
-
-
- -
-
-
- -33.000000000000000
-
-
- 45.000000000000000
-
-
-
- -
-
-
-
-
-
- 49.000000000000000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Number of Panels
-
-
-
- -
-
-
- 49.000000000000000
-
-
-
- -
-
-
- Symmetric?
-
-
-
- -
-
-
- Panel Spacing Option
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
-
-
- Chord-wise Panels
-
-
-
- -
-
-
-
-
- Uniform
-
-
- -
-
- Cosine
-
-
- -
-
- Reverse Cosine
-
-
-
-
- -
-
-
- <html><head/><body><p>z</p></body></html>
-
-
-
- -
-
-
- -50.000000000000000
-
-
- 44.000000000000000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 12
- 75
- true
-
-
-
- Qt::PreventContextMenu
-
-
- QFrame::Sunken
-
-
- 1
-
-
- Main Wing
-
-
- Qt::AlignCenter
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- 1
-
-
-
-
- 318
- 0
-
-
-
- Wing Root Cross Section
-
-
-
-
-
-
-
-
-
-
-
-
-
- 49.000000000000000
-
-
-
- -
-
-
- -50.000000000000000
-
-
- 44.000000000000000
-
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Number of Panels
-
-
-
- -
-
-
- x
-
-
-
- -
-
-
-
- 10
- 75
- true
-
-
-
- Chord and Control Surface
-
-
-
- -
-
-
- Chord
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- -
-
-
- Control Surface Deflection
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- y
-
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
-
-
- Span-wise panels
-
-
-
- -
-
-
- <html><head/><body><p>z</p></body></html>
-
-
-
- -
-
-
- Panel Spacing Option
-
-
-
- -
-
-
- -33.000000000000000
-
-
- 45.000000000000000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
-
-
- Leading Edge Location
-
-
-
- -
-
-
- Control Surface Hinge Point
-
-
-
- -
-
-
-
-
-
- 49.000000000000000
-
-
-
- -
-
-
-
-
- Uniform
-
-
- -
-
- Cosine
-
-
- -
-
- Reverse Cosine
-
-
-
-
- -
-
-
- Symmetric?
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 12
- 75
- true
-
-
-
- Qt::PreventContextMenu
-
-
- QFrame::Sunken
-
-
- 1
-
-
- Root Cross Section
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
- 0
-
-
- Aerofoil
-
-
- Qt::AlignCenter
-
-
-
-
-
-
-
-
-
-
- Wing Tip Cross Section
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
- 49.000000000000000
-
-
-
- -
-
-
- y
-
-
-
- -
-
-
- Panel Spacing Option
-
-
-
- -
-
-
-
-
-
- 49.000000000000000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Number of Panels
-
-
-
- -
-
-
-
-
- Uniform
-
-
- -
-
- Cosine
-
-
- -
-
- Reverse Cosine
-
-
-
-
- -
-
-
-
- 10
- 75
- true
-
-
-
- Chord and Control Surface
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 12
- 75
- true
-
-
-
- Qt::PreventContextMenu
-
-
- QFrame::Sunken
-
-
- 1
-
-
- Root Cross Section
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- -
-
-
- Control Surface Hinge Point
-
-
-
- -
-
-
- -50.000000000000000
-
-
- 44.000000000000000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
-
-
- Leading Edge Location
-
-
-
- -
-
-
- Symmetric?
-
-
-
- -
-
-
- x
-
-
-
- -
-
-
- Chord
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 10
- 75
- true
-
-
-
- Span-wise Panels
-
-
-
- -
-
-
- <html><head/><body><p>z</p></body></html>
-
-
-
- -
-
-
- -
-
-
- -33.000000000000000
-
-
- 45.000000000000000
-
-
-
- -
-
-
- -
-
-
- Control Surface Deflection
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Aerofoil
-
-
- Qt::AlignCenter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Model
-
-
- -
-
-
- Controller
-
-
-
-
-
-
-
-
- Materials
-
-
-
-
- Boundary Conditions
-
-
-
-
- Solution
-
-
-
-
- Visualiser Settings
-
-
-
-
- 0
- 0
- 331
- 235
-
-
-
-
-
-
- -
-
-
- Move
-
-
-
- -
-
-
- 49.000000000000000
-
-
-
- -
-
-
- Homing
-
-
-
- -
-
-
- -50.000000000000000
-
-
- 44.000000000000000
-
-
-
- -
-
-
- -33.000000000000000
-
-
- 45.000000000000000
-
-
-
- -
-
-
-
-
-
- 49.000000000000000
-
-
-
- -
-
-
- -45.000000000000000
-
-
- 0.000000000000000
-
-
-
- -
-
-
- Injection
-
-
-
- -
-
-
- x
-
-
-
- -
-
-
- y
-
-
-
- -
-
-
- <html><head/><body><p>z</p></body></html>
-
-
-
- -
-
-
- <html><head/><body><p>β</p></body></html>
-
-
-
- -
-
-
- d
-
-
-
-
-
-
-
-
- -
-
-
- false
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
-
-
-
- <html><head/><body><p><img src="docs/Black_Text_Logo.png"/></p></body></html>
-
-
- Qt::AlignCenter
-
-
-
-
-
-
- -
-
-
- 0
-
-
- 24
-
-
-
- -
-
-
- QFrame::StyledPanel
-
-
- QFrame::Raised
-
-
-
-
-
-
- Qt::NoContextMenu
-
-
- Generate Results
-
-
-
- -
-
-
- Plot Visualisation
-
-
-
- -
-
-
- Terminal Output
-
-
-
- -
-
-
-
- 5
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
- About
-
-
-
-
- Manual
-
-
-
-
- Quit
-
-
-
-
- Import Data
-
-
-
-
- Export Data
-
-
-
-
- Preset Aircraft List
-
-
-
-
- Example 1: Analyze steady trim example
-
-
-
-
- Example 2: Analyze unsteady trim example
-
-
-
-
- Example 3: Steady convergence example
-
-
-
-
- Example 4: Steady horseshoe vortex lattice method solver
-
-
-
-
- Example 5: Steady ring vortex lattice method solver static
-
-
-
-
- Example 6: Unsteady ring vortex lattice method solver static
-
-
-
-
- Example 7: Unsteady ring vortex lattice method solver variable
-
-
-
-
- Example 8: Unsteady ring vortex lattice method solver variable formation
-
-
-
-
- Example 9: Unsteady static convergence example
-
-
-
-
- Example 10: Unsteady variable convergence example
-
-
-
-
-
-
+
+
+
diff --git a/pterasoftware/ui_resources/textdialog.py b/pterasoftware/ui_resources/textdialog.py
index 32985163..b6c7315c 100644
--- a/pterasoftware/ui_resources/textdialog.py
+++ b/pterasoftware/ui_resources/textdialog.py
@@ -5,10 +5,8 @@ class Ui_TextAboutDialog(object):
def setupUi(self, TextAboutDialog):
TextAboutDialog.setObjectName("TextAboutDialog")
TextAboutDialog.resize(1000, 900)
- sizePolicy = QtWidgets.QSizePolicy(
- QtWidgets.QSizePolicy.MinimumExpanding,
- QtWidgets.QSizePolicy.MinimumExpanding,
- )
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding,
+ QtWidgets.QSizePolicy.MinimumExpanding, )
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(TextAboutDialog.sizePolicy().hasHeightForWidth())
@@ -19,10 +17,8 @@ def setupUi(self, TextAboutDialog):
self.textEdit = QtWidgets.QTextEdit(TextAboutDialog)
self.textEdit.setEnabled(True)
self.textEdit.setGeometry(QtCore.QRect(0, 0, 1000, 900))
- sizePolicy = QtWidgets.QSizePolicy(
- QtWidgets.QSizePolicy.MinimumExpanding,
- QtWidgets.QSizePolicy.MinimumExpanding,
- )
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding,
+ QtWidgets.QSizePolicy.MinimumExpanding, )
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.textEdit.sizePolicy().hasHeightForWidth())
@@ -38,5 +34,4 @@ def setupUi(self, TextAboutDialog):
def retranslateUi(self, TextAboutDialog):
TextAboutDialog.setWindowTitle(
- QtWidgets.QApplication.translate("TextAboutDialog", "Dialog", None, -1)
- )
+ QtWidgets.QApplication.translate("TextAboutDialog", "Dialog", None, -1))
diff --git a/pterasoftware/unsteady_ring_vortex_lattice_method.py b/pterasoftware/unsteady_ring_vortex_lattice_method.py
index ab6250a6..5ae9fe27 100644
--- a/pterasoftware/unsteady_ring_vortex_lattice_method.py
+++ b/pterasoftware/unsteady_ring_vortex_lattice_method.py
@@ -177,12 +177,8 @@ def __init__(self, unsteady_problem):
self.current_wake_ring_vortex_ages = None
self.num_panels = None
- def run(
- self,
- logging_level="Warning",
- prescribed_wake=True,
- calculate_streamlines=True,
- ):
+ def run(self, logging_level="Warning", prescribed_wake=True,
+ calculate_streamlines=True, ):
"""This method runs the solver on the unsteady problem.
:param logging_level: str, optional
@@ -201,8 +197,7 @@ def run(
"""
# Configure the problem's logger.
logging_level_value = functions.convert_logging_level_name_to_value(
- logging_level
- )
+ logging_level)
logging.basicConfig(level=logging_level_value)
# The following loop iterates through the steps to populate currently empty
@@ -233,34 +228,26 @@ def run(
this_wake_ring_vortex_strengths = np.zeros(this_num_wake_ring_vortices)
this_wake_ring_vortex_ages = np.zeros(this_num_wake_ring_vortices)
this_wake_ring_vortex_front_right_vertices = np.zeros(
- (this_num_wake_ring_vortices, 3)
- )
+ (this_num_wake_ring_vortices, 3))
this_wake_ring_vortex_front_left_vertices = np.zeros(
- (this_num_wake_ring_vortices, 3)
- )
+ (this_num_wake_ring_vortices, 3))
this_wake_ring_vortex_back_left_vertices = np.zeros(
- (this_num_wake_ring_vortices, 3)
- )
+ (this_num_wake_ring_vortices, 3))
this_wake_ring_vortex_back_right_vertices = np.zeros(
- (this_num_wake_ring_vortices, 3)
- )
+ (this_num_wake_ring_vortices, 3))
# Append this step's arrays to the list of arrays.
self.num_wake_ring_vortices_list.append(this_num_wake_ring_vortices)
self.wake_ring_vortex_strengths_list.append(this_wake_ring_vortex_strengths)
self.wake_ring_vortex_ages_list.append(this_wake_ring_vortex_ages)
self.wake_ring_vortex_front_right_vertices_list.append(
- this_wake_ring_vortex_front_right_vertices
- )
+ this_wake_ring_vortex_front_right_vertices)
self.wake_ring_vortex_front_left_vertices_list.append(
- this_wake_ring_vortex_front_left_vertices
- )
+ this_wake_ring_vortex_front_left_vertices)
self.wake_ring_vortex_back_left_vertices_list.append(
- this_wake_ring_vortex_back_left_vertices
- )
+ this_wake_ring_vortex_back_left_vertices)
self.wake_ring_vortex_back_right_vertices_list.append(
- this_wake_ring_vortex_back_right_vertices
- )
+ this_wake_ring_vortex_back_right_vertices)
# The following loop attempts to predict how much time each step will take,
# relative to the other steps. This data will be used to generate estimates
@@ -301,16 +288,10 @@ def run(
# Unless the logging level is at or above Warning, run the simulation with a
# progress bar.
- with tqdm(
- total=approx_total_time,
- unit="",
- unit_scale=True,
- ncols=100,
- desc="Simulating",
- disable=logging_level_value != logging.WARNING,
- bar_format="{desc}:{percentage:3.0f}% |{bar}| Elapsed: {elapsed}, "
- "Remaining: {remaining}",
- ) as bar:
+ with tqdm(total=approx_total_time, unit="", unit_scale=True, ncols=100,
+ desc="Simulating", disable=logging_level_value != logging.WARNING,
+ bar_format="{desc}:{percentage:3.0f}% |{bar}| Elapsed: {elapsed}, "
+ "Remaining: {remaining}", ) as bar:
# Initialize all the airplanes' panels' vortices.
logging.info("Initializing all airplanes' panel vortices.")
@@ -327,21 +308,14 @@ def run(
# point.
self.current_step = step
self.current_airplanes = self.steady_problems[
- self.current_step
- ].airplanes
+ self.current_step].airplanes
self.current_operating_point = self.steady_problems[
- self.current_step
- ].operating_point
+ self.current_step].operating_point
self.current_freestream_velocity_geometry_axes = (
- self.current_operating_point.calculate_freestream_velocity_geometry_axes()
- )
+ self.current_operating_point.calculate_freestream_velocity_geometry_axes())
logging.info(
- "Beginning time step "
- + str(self.current_step)
- + " out of "
- + str(self.num_steps - 1)
- + "."
- )
+ "Beginning time step " + str(self.current_step) + " out of " + str(
+ self.num_steps - 1) + ".")
# Calculate the number of panels for this time step.
self.num_panels = 0
@@ -351,11 +325,9 @@ def run(
# Initialize attributes to hold aerodynamic data that pertains to this
# problem.
self.current_wing_wing_influences = np.zeros(
- (self.num_panels, self.num_panels)
- )
+ (self.num_panels, self.num_panels))
self.current_freestream_velocity_geometry_axes = (
- self.current_operating_point.calculate_freestream_velocity_geometry_axes()
- )
+ self.current_operating_point.calculate_freestream_velocity_geometry_axes())
self.current_freestream_wing_influences = np.zeros(self.num_panels)
self.current_wake_wing_influences = np.zeros(self.num_panels)
self.current_vortex_strengths = np.ones(self.num_panels)
@@ -393,17 +365,13 @@ def run(
self.last_panel_collocation_points = np.zeros((self.num_panels, 3))
self.last_panel_vortex_strengths = np.zeros(self.num_panels)
self.last_panel_back_right_vortex_vertices = np.zeros(
- (self.num_panels, 3)
- )
+ (self.num_panels, 3))
self.last_panel_front_right_vortex_vertices = np.zeros(
- (self.num_panels, 3)
- )
+ (self.num_panels, 3))
self.last_panel_front_left_vortex_vertices = np.zeros(
- (self.num_panels, 3)
- )
+ (self.num_panels, 3))
self.last_panel_back_left_vortex_vertices = np.zeros(
- (self.num_panels, 3)
- )
+ (self.num_panels, 3))
self.last_panel_right_vortex_centers = np.zeros((self.num_panels, 3))
self.last_panel_front_vortex_centers = np.zeros((self.num_panels, 3))
self.last_panel_left_vortex_centers = np.zeros((self.num_panels, 3))
@@ -412,23 +380,17 @@ def run(
# Get the pre-allocated (but still all zero) arrays of wake
# information that are associated with this time step.
self.current_wake_ring_vortex_strengths = (
- self.wake_ring_vortex_strengths_list[step]
- )
+ self.wake_ring_vortex_strengths_list[step])
self.current_wake_ring_vortex_ages = self.wake_ring_vortex_ages_list[
- step
- ]
+ step]
self.current_wake_ring_vortex_front_right_vertices = (
- self.wake_ring_vortex_front_right_vertices_list[step]
- )
+ self.wake_ring_vortex_front_right_vertices_list[step])
self.current_wake_ring_vortex_front_left_vertices = (
- self.wake_ring_vortex_front_left_vertices_list[step]
- )
+ self.wake_ring_vortex_front_left_vertices_list[step])
self.current_wake_ring_vortex_back_left_vertices = (
- self.wake_ring_vortex_back_left_vertices_list[step]
- )
+ self.wake_ring_vortex_back_left_vertices_list[step])
self.current_wake_ring_vortex_back_right_vertices = (
- self.wake_ring_vortex_back_right_vertices_list[step]
- )
+ self.wake_ring_vortex_back_right_vertices_list[step])
# Collapse this problem's geometry matrices into 1D arrays of
# attributes.
@@ -494,8 +456,8 @@ def initialize_panel_vortices(self):
# Get the freestream velocity at this time step's problem.
this_freestream_velocity_geometry_axes = (
- steady_problem.operating_point.calculate_freestream_velocity_geometry_axes()
- )
+ steady_problem.operating_point
+ .calculate_freestream_velocity_geometry_axes())
# Iterate through this problem's airplanes' wings.
for airplane in steady_problem.airplanes:
@@ -517,14 +479,11 @@ def initialize_panel_vortices(self):
# whether the panel is along the trailing edge or not.
if not panel.is_trailing_edge:
next_chordwise_panel = wing.panels[
- chordwise_position + 1, spanwise_position
- ]
+ chordwise_position + 1, spanwise_position]
back_left_vortex_vertex = (
- next_chordwise_panel.front_left_vortex_vertex
- )
+ next_chordwise_panel.front_left_vortex_vertex)
back_right_vortex_vertex = (
- next_chordwise_panel.front_right_vortex_vertex
- )
+ next_chordwise_panel.front_right_vortex_vertex)
else:
# As these vertices are directly behind the trailing
# edge, they are spaced back from their panel's
@@ -534,23 +493,11 @@ def initialize_panel_vortices(self):
# of "Modeling of aerodynamic forces in flapping
# flight with the Unsteady Vortex Lattice Method" by
# Thomas Lambert.
- back_left_vortex_vertex = (
- front_left_vortex_vertex
- + (panel.back_left_vertex - panel.front_left_vertex)
- + this_freestream_velocity_geometry_axes
- * self.delta_time
- * 0.25
- )
+ back_left_vortex_vertex = (front_left_vortex_vertex + (
+ panel.back_left_vertex - panel.front_left_vertex) + this_freestream_velocity_geometry_axes * self.delta_time * 0.25)
back_right_vortex_vertex = (
- front_right_vortex_vertex
- + (
- panel.back_right_vertex
- - panel.front_right_vertex
- )
- + this_freestream_velocity_geometry_axes
- * self.delta_time
- * 0.25
- )
+ front_right_vortex_vertex + (
+ panel.back_right_vertex - panel.front_right_vertex) + this_freestream_velocity_geometry_axes * self.delta_time * 0.25)
# Initialize the panel's ring vortex.
panel.ring_vortex = aerodynamics.RingVortex(
@@ -558,8 +505,7 @@ def initialize_panel_vortices(self):
front_left_vertex=front_left_vortex_vertex,
back_left_vertex=back_left_vortex_vertex,
back_right_vertex=back_right_vortex_vertex,
- strength=None,
- )
+ strength=None, )
def collapse_geometry(self):
"""This method converts attributes of the problem's geometry into 1D
@@ -582,38 +528,32 @@ def collapse_geometry(self):
# Iterate through the 1D array of this wing's panels.
for panel in panels:
-
# Update the solver's list of attributes with this panel's
# attributes.
- functions.update_ring_vortex_solvers_panel_attributes(
- solver=self,
- global_panel_position=global_panel_position,
- panel=panel,
- airplane=airplane,
- )
+ functions.update_ring_vortex_solvers_panel_attributes(solver=self,
+ global_panel_position=global_panel_position, panel=panel,
+ airplane=airplane, )
# Increment the global panel position.
global_panel_position += 1
for wake_ring_vortex in wake_ring_vortices:
self.current_wake_ring_vortex_strengths[
- global_wake_ring_vortex_position
- ] = wake_ring_vortex.strength
+ global_wake_ring_vortex_position] = wake_ring_vortex.strength
self.current_wake_ring_vortex_ages[
- global_wake_ring_vortex_position
- ] = wake_ring_vortex.age
+ global_wake_ring_vortex_position] = wake_ring_vortex.age
self.current_wake_ring_vortex_front_right_vertices[
- global_wake_ring_vortex_position, :
- ] = wake_ring_vortex.front_right_vertex
+ global_wake_ring_vortex_position,
+ :] = wake_ring_vortex.front_right_vertex
self.current_wake_ring_vortex_front_left_vertices[
- global_wake_ring_vortex_position, :
- ] = wake_ring_vortex.front_left_vertex
+ global_wake_ring_vortex_position,
+ :] = wake_ring_vortex.front_left_vertex
self.current_wake_ring_vortex_back_left_vertices[
- global_wake_ring_vortex_position, :
- ] = wake_ring_vortex.back_left_vertex
+ global_wake_ring_vortex_position,
+ :] = wake_ring_vortex.back_left_vertex
self.current_wake_ring_vortex_back_right_vertices[
- global_wake_ring_vortex_position, :
- ] = wake_ring_vortex.back_right_vertex
+ global_wake_ring_vortex_position,
+ :] = wake_ring_vortex.back_right_vertex
global_wake_ring_vortex_position += 1
@@ -634,39 +574,29 @@ def collapse_geometry(self):
# Iterate through the 1D array of this wing's panels.
for panel in panels:
-
# Update the solver's list of attributes with this panel's
# attributes.
self.last_panel_collocation_points[global_panel_position, :] = (
- panel.collocation_point
- )
+ panel.collocation_point)
self.last_panel_vortex_strengths[global_panel_position] = (
- panel.ring_vortex.strength
- )
+ panel.ring_vortex.strength)
self.last_panel_back_right_vortex_vertices[
- global_panel_position, :
- ] = panel.ring_vortex.right_leg.origin
+ global_panel_position, :] = panel.ring_vortex.right_leg.origin
self.last_panel_front_right_vortex_vertices[
- global_panel_position, :
- ] = panel.ring_vortex.right_leg.termination
+ global_panel_position,
+ :] = panel.ring_vortex.right_leg.termination
self.last_panel_front_left_vortex_vertices[
- global_panel_position, :
- ] = panel.ring_vortex.left_leg.origin
- self.last_panel_back_left_vortex_vertices[
- global_panel_position, :
- ] = panel.ring_vortex.left_leg.termination
- self.last_panel_right_vortex_centers[
- global_panel_position, :
- ] = panel.ring_vortex.right_leg.center
- self.last_panel_front_vortex_centers[
- global_panel_position, :
- ] = panel.ring_vortex.front_leg.center
- self.last_panel_left_vortex_centers[
- global_panel_position, :
- ] = panel.ring_vortex.left_leg.center
- self.last_panel_back_vortex_centers[
- global_panel_position, :
- ] = panel.ring_vortex.back_leg.center
+ global_panel_position, :] = panel.ring_vortex.left_leg.origin
+ self.last_panel_back_left_vortex_vertices[global_panel_position,
+ :] = panel.ring_vortex.left_leg.termination
+ self.last_panel_right_vortex_centers[global_panel_position,
+ :] = panel.ring_vortex.right_leg.center
+ self.last_panel_front_vortex_centers[global_panel_position,
+ :] = panel.ring_vortex.front_leg.center
+ self.last_panel_left_vortex_centers[global_panel_position,
+ :] = panel.ring_vortex.left_leg.center
+ self.last_panel_back_vortex_centers[global_panel_position,
+ :] = panel.ring_vortex.back_leg.center
# Increment the global panel position.
global_panel_position += 1
@@ -687,19 +617,14 @@ def calculate_wing_wing_influences(self):
front_right_vortex_vertices=self.panel_front_right_vortex_vertices,
front_left_vortex_vertices=self.panel_front_left_vortex_vertices,
back_left_vortex_vertices=self.panel_back_left_vortex_vertices,
- strengths=self.current_vortex_strengths,
- ages=None,
- nu=self.current_operating_point.nu,
- )
+ strengths=self.current_vortex_strengths, ages=None,
+ nu=self.current_operating_point.nu, )
# Take the batch dot product of the normalized velocities with each panel's
# normal direction. This is now the problem's matrix of wing-wing influence
# coefficients.
- self.current_wing_wing_influences = np.einsum(
- "...k,...k->...",
- total_influences,
- np.expand_dims(self.panel_normal_directions, axis=1),
- )
+ self.current_wing_wing_influences = np.einsum("...k,...k->...",
+ total_influences, np.expand_dims(self.panel_normal_directions, axis=1), )
def calculate_freestream_wing_influences(self):
"""This method finds the vector of freestream-wing influence coefficients
@@ -712,30 +637,22 @@ def calculate_freestream_wing_influences(self):
"""
# Find the normal components of the freestream velocity on every panel by
# taking a batch dot product.
- freestream_influences = np.einsum(
- "ij,j->i",
- self.panel_normal_directions,
- self.current_freestream_velocity_geometry_axes,
- )
+ freestream_influences = np.einsum("ij,j->i", self.panel_normal_directions,
+ self.current_freestream_velocity_geometry_axes, )
# Get the current flapping velocities at every collocation point.
current_flapping_velocities_at_collocation_points = (
- self.calculate_current_flapping_velocities_at_collocation_points()
- )
+ self.calculate_current_flapping_velocities_at_collocation_points())
# Find the normal components of every panel's flapping velocities at their
# collocation points by taking a batch dot product.
- flapping_influences = np.einsum(
- "ij,ij->i",
- self.panel_normal_directions,
- current_flapping_velocities_at_collocation_points,
- )
+ flapping_influences = np.einsum("ij,ij->i", self.panel_normal_directions,
+ current_flapping_velocities_at_collocation_points, )
# Calculate the total current freestream-wing influences by summing the
# freestream influences and the flapping influences.
self.current_freestream_wing_influences = (
- freestream_influences + flapping_influences
- )
+ freestream_influences + flapping_influences)
def calculate_wake_wing_influences(self):
"""This method finds the vector of the wake-wing influences associated with
@@ -761,14 +678,12 @@ def calculate_wake_wing_influences(self):
back_left_vortex_vertices=self.current_wake_ring_vortex_back_left_vertices,
strengths=self.current_wake_ring_vortex_strengths,
ages=self.current_wake_ring_vortex_ages,
- nu=self.current_operating_point.nu,
- )
+ nu=self.current_operating_point.nu, )
# Set the current wake-wing influences to the normal component of the
# wake induced velocities at each panel.
- self.current_wake_wing_influences = np.einsum(
- "ij,ij->i", velocities_from_wake, self.panel_normal_directions
- )
+ self.current_wake_wing_influences = np.einsum("ij,ij->i",
+ velocities_from_wake, self.panel_normal_directions)
else:
@@ -784,9 +699,7 @@ def calculate_vortex_strengths(self):
# Solve for the strength of each panel's vortex.
self.current_vortex_strengths = np.linalg.solve(
self.current_wing_wing_influences,
- -self.current_wake_wing_influences
- - self.current_freestream_wing_influences,
- )
+ -self.current_wake_wing_influences - self.current_freestream_wing_influences, )
# Iterate through the panels and update their vortex strengths.
for panel_num in range(self.panels.size):
@@ -828,10 +741,8 @@ def calculate_solution_velocity(self, points):
front_right_vortex_vertices=self.panel_front_right_vortex_vertices,
front_left_vortex_vertices=self.panel_front_left_vortex_vertices,
back_left_vortex_vertices=self.panel_back_left_vortex_vertices,
- strengths=self.current_vortex_strengths,
- ages=None,
- nu=self.current_operating_point.nu,
- )
+ strengths=self.current_vortex_strengths, ages=None,
+ nu=self.current_operating_point.nu, )
# Find the vector of velocities induced at every point by every wake ring
# vortex. The effect of every wake ring vortex on each point will be summed.
@@ -843,8 +754,7 @@ def calculate_solution_velocity(self, points):
back_left_vortex_vertices=self.current_wake_ring_vortex_back_left_vertices,
strengths=self.current_wake_ring_vortex_strengths,
ages=self.current_wake_ring_vortex_ages,
- nu=self.current_operating_point.nu,
- )
+ nu=self.current_operating_point.nu, )
# Find the total influence of the vortices, which is the sum of the influence
# due to the bound ring vortices and the wake ring vortices.
@@ -893,25 +803,21 @@ def calculate_near_field_forces_and_moments(self):
# Change the effective right vortex line strength from zero
# to this panel's ring vortex's strength.
effective_right_vortex_line_strengths[global_panel_position] = (
- self.current_vortex_strengths[global_panel_position]
- )
+ self.current_vortex_strengths[global_panel_position])
else:
# Get the panel directly to the right of this panel.
panel_to_right = wing.panels[
- panel.local_chordwise_position,
- panel.local_spanwise_position + 1,
- ]
+ panel.local_chordwise_position, panel.local_spanwise_position + 1,]
# Change the effective right vortex line strength from zero
# to the difference between this panel's ring vortex's
# strength, and the ring vortex strength of the panel to the
# right of it.
effective_right_vortex_line_strengths[global_panel_position] = (
- self.current_vortex_strengths[global_panel_position]
- - panel_to_right.ring_vortex.strength
- )
+ self.current_vortex_strengths[
+ global_panel_position] - panel_to_right.ring_vortex.strength)
# Check if this panel is on its wing's leading edge.
if panel.is_leading_edge:
@@ -919,24 +825,20 @@ def calculate_near_field_forces_and_moments(self):
# Change the effective front vortex line strength from zero
# to this panel's ring vortex's strength.
effective_front_vortex_line_strengths[global_panel_position] = (
- self.current_vortex_strengths[global_panel_position]
- )
+ self.current_vortex_strengths[global_panel_position])
else:
# Get the panel directly in front of this panel.
panel_to_front = wing.panels[
- panel.local_chordwise_position - 1,
- panel.local_spanwise_position,
- ]
+ panel.local_chordwise_position - 1, panel.local_spanwise_position,]
# Change the effective front vortex line strength from zero
# to the difference between this panel's ring vortex's
# strength, and the ring vortex strength of the panel in
# front of it.
effective_front_vortex_line_strengths[global_panel_position] = (
- self.current_vortex_strengths[global_panel_position]
- - panel_to_front.ring_vortex.strength
- )
+ self.current_vortex_strengths[
+ global_panel_position] - panel_to_front.ring_vortex.strength)
# Check if this panel is on its wing's left edge.
if panel.is_left_edge:
@@ -944,129 +846,91 @@ def calculate_near_field_forces_and_moments(self):
# Change the effective left vortex line strength from zero to
# this panel's ring vortex's strength.
effective_left_vortex_line_strengths[global_panel_position] = (
- self.current_vortex_strengths[global_panel_position]
- )
+ self.current_vortex_strengths[global_panel_position])
else:
# Get the panel directly to the left of this panel.
panel_to_left = wing.panels[
- panel.local_chordwise_position,
- panel.local_spanwise_position - 1,
- ]
+ panel.local_chordwise_position, panel.local_spanwise_position - 1,]
# Change the effective left vortex line strength from zero to
# the difference between this panel's ring vortex's strength,
# and the ring vortex strength of the panel to the left of it.
effective_left_vortex_line_strengths[global_panel_position] = (
- self.current_vortex_strengths[global_panel_position]
- - panel_to_left.ring_vortex.strength
- )
+ self.current_vortex_strengths[
+ global_panel_position] - panel_to_left.ring_vortex.strength)
# Increment the global panel position.
global_panel_position += 1
# Calculate the solution velocities at the centers of the panel's front leg,
# left leg, and right leg.
- velocities_at_ring_vortex_front_leg_centers = (
- self.calculate_solution_velocity(points=self.panel_front_vortex_centers)
- + self.calculate_current_flapping_velocities_at_front_leg_centers()
- )
- velocities_at_ring_vortex_left_leg_centers = (
- self.calculate_solution_velocity(points=self.panel_left_vortex_centers)
- + self.calculate_current_flapping_velocities_at_left_leg_centers()
- )
- velocities_at_ring_vortex_right_leg_centers = (
- self.calculate_solution_velocity(points=self.panel_right_vortex_centers)
- + self.calculate_current_flapping_velocities_at_right_leg_centers()
- )
+ velocities_at_ring_vortex_front_leg_centers = (self.calculate_solution_velocity(
+ points=self.panel_front_vortex_centers) + self.calculate_current_flapping_velocities_at_front_leg_centers())
+ velocities_at_ring_vortex_left_leg_centers = (self.calculate_solution_velocity(
+ points=self.panel_left_vortex_centers) + self.calculate_current_flapping_velocities_at_left_leg_centers())
+ velocities_at_ring_vortex_right_leg_centers = (self.calculate_solution_velocity(
+ points=self.panel_right_vortex_centers) + self.calculate_current_flapping_velocities_at_right_leg_centers())
# Using the effective line vortex strengths, and the Kutta-Joukowski theorem
# to find the near field force in geometry axes on the front leg, left leg,
# and right leg. Also calculate the unsteady component of the force on each
# panel, which is derived from the unsteady Bernoulli equation.
near_field_forces_on_ring_vortex_right_legs_geometry_axes = (
- self.current_operating_point.density
- * np.expand_dims(effective_right_vortex_line_strengths, axis=1)
- * functions.numba_1d_explicit_cross(
- velocities_at_ring_vortex_right_leg_centers,
- self.panel_right_vortex_vectors,
- )
- )
+ self.current_operating_point.density * np.expand_dims(
+ effective_right_vortex_line_strengths,
+ axis=1) * functions.numba_1d_explicit_cross(
+ velocities_at_ring_vortex_right_leg_centers,
+ self.panel_right_vortex_vectors, ))
near_field_forces_on_ring_vortex_front_legs_geometry_axes = (
- self.current_operating_point.density
- * np.expand_dims(effective_front_vortex_line_strengths, axis=1)
- * functions.numba_1d_explicit_cross(
- velocities_at_ring_vortex_front_leg_centers,
- self.panel_front_vortex_vectors,
- )
- )
+ self.current_operating_point.density * np.expand_dims(
+ effective_front_vortex_line_strengths,
+ axis=1) * functions.numba_1d_explicit_cross(
+ velocities_at_ring_vortex_front_leg_centers,
+ self.panel_front_vortex_vectors, ))
near_field_forces_on_ring_vortex_left_legs_geometry_axes = (
- self.current_operating_point.density
- * np.expand_dims(effective_left_vortex_line_strengths, axis=1)
- * functions.numba_1d_explicit_cross(
- velocities_at_ring_vortex_left_leg_centers,
- self.panel_left_vortex_vectors,
- )
- )
+ self.current_operating_point.density * np.expand_dims(
+ effective_left_vortex_line_strengths,
+ axis=1) * functions.numba_1d_explicit_cross(
+ velocities_at_ring_vortex_left_leg_centers,
+ self.panel_left_vortex_vectors, ))
unsteady_near_field_forces_geometry_axes = (
- self.current_operating_point.density
- * np.expand_dims(
- (self.current_vortex_strengths - self.last_panel_vortex_strengths),
- axis=1,
- )
- * np.expand_dims(self.panel_areas, axis=1)
- * self.panel_normal_directions
- / self.delta_time
- )
+ self.current_operating_point.density * np.expand_dims(
+ (self.current_vortex_strengths - self.last_panel_vortex_strengths),
+ axis=1, ) * np.expand_dims(self.panel_areas,
+ axis=1) * self.panel_normal_directions / self.delta_time)
# Sum the forces on the legs, and the unsteady force, to calculate the total
# near field force, in geometry axes, on each panel.
near_field_forces_geometry_axes = (
- near_field_forces_on_ring_vortex_front_legs_geometry_axes
- + near_field_forces_on_ring_vortex_left_legs_geometry_axes
- + near_field_forces_on_ring_vortex_right_legs_geometry_axes
- + unsteady_near_field_forces_geometry_axes
- )
+ near_field_forces_on_ring_vortex_front_legs_geometry_axes + near_field_forces_on_ring_vortex_left_legs_geometry_axes + near_field_forces_on_ring_vortex_right_legs_geometry_axes + unsteady_near_field_forces_geometry_axes)
# Find the near field moment in geometry axes on the front leg, left leg,
# and right leg. Also find the moment on each panel due to the unsteady force.
near_field_moments_on_ring_vortex_front_legs_geometry_axes = (
functions.numba_1d_explicit_cross(
self.panel_front_vortex_centers - self.panel_moment_references,
- near_field_forces_on_ring_vortex_front_legs_geometry_axes,
- )
- )
+ near_field_forces_on_ring_vortex_front_legs_geometry_axes, ))
near_field_moments_on_ring_vortex_left_legs_geometry_axes = (
functions.numba_1d_explicit_cross(
self.panel_left_vortex_centers - self.panel_moment_references,
- near_field_forces_on_ring_vortex_left_legs_geometry_axes,
- )
- )
+ near_field_forces_on_ring_vortex_left_legs_geometry_axes, ))
near_field_moments_on_ring_vortex_right_legs_geometry_axes = (
functions.numba_1d_explicit_cross(
self.panel_right_vortex_centers - self.panel_moment_references,
- near_field_forces_on_ring_vortex_right_legs_geometry_axes,
- )
- )
+ near_field_forces_on_ring_vortex_right_legs_geometry_axes, ))
unsteady_near_field_moments_geometry_axes = functions.numba_1d_explicit_cross(
self.panel_collocation_points - self.panel_moment_references,
- unsteady_near_field_forces_geometry_axes,
- )
+ unsteady_near_field_forces_geometry_axes, )
# Sum the moments on the legs, and the unsteady moment, to calculate the
# total near field moment, in geometry axes, on each panel.
near_field_moments_geometry_axes = (
- near_field_moments_on_ring_vortex_front_legs_geometry_axes
- + near_field_moments_on_ring_vortex_left_legs_geometry_axes
- + near_field_moments_on_ring_vortex_right_legs_geometry_axes
- + unsteady_near_field_moments_geometry_axes
- )
-
- functions.process_unsteady_solver_forces(
- unsteady_solver=self,
+ near_field_moments_on_ring_vortex_front_legs_geometry_axes + near_field_moments_on_ring_vortex_left_legs_geometry_axes + near_field_moments_on_ring_vortex_right_legs_geometry_axes + unsteady_near_field_moments_geometry_axes)
+
+ functions.process_unsteady_solver_forces(unsteady_solver=self,
near_field_forces_geometry_axes=near_field_forces_geometry_axes,
- near_field_moments_geometry_axes=near_field_moments_geometry_axes,
- )
+ near_field_moments_geometry_axes=near_field_moments_geometry_axes, )
def populate_next_airplanes_wake(self, prescribed_wake=True):
"""This method updates the next time step's airplanes' wakes.
@@ -1079,8 +943,7 @@ def populate_next_airplanes_wake(self, prescribed_wake=True):
"""
# Populate the locations of the next step's airplanes' wake vortex vertices:
self.populate_next_airplanes_wake_vortex_vertices(
- prescribed_wake=prescribed_wake
- )
+ prescribed_wake=prescribed_wake)
# Populate the locations of the next step's airplanes' wake vortices.
self.populate_next_airplanes_wake_vortices()
@@ -1132,50 +995,42 @@ def populate_next_airplanes_wake_vortex_vertices(self, prescribed_wake=True):
# Initialize a matrix to hold the vertices of the new row of
# wake ring vortices.
first_row_of_wake_ring_vortex_vertices = np.zeros(
- (1, num_spanwise_panels + 1, 3)
- )
+ (1, num_spanwise_panels + 1, 3))
# Iterate through the spanwise panel positions.
for spanwise_position in range(num_spanwise_panels):
# Get the next wing's panel object at this location.
next_panel = next_wing.panels[
- chordwise_position, spanwise_position
- ]
+ chordwise_position, spanwise_position]
# The position of the next front left wake ring vortex
# vertex is the next panel's ring vortex's back left
# vertex.
next_front_left_vertex = (
- next_panel.ring_vortex.back_left_vertex
- )
+ next_panel.ring_vortex.back_left_vertex)
# Add this to the new row of wake ring vortex vertices.
first_row_of_wake_ring_vortex_vertices[
- 0, spanwise_position
- ] = next_front_left_vertex
+ 0, spanwise_position] = next_front_left_vertex
# Check if this panel is on the right edge of the wing.
if spanwise_position == (num_spanwise_panels - 1):
-
# The position of the next front right wake ring
# vortex vertex is the next panel's ring vortex's
# back right vertex.
next_front_right_vertex = (
- next_panel.ring_vortex.back_right_vertex
- )
+ next_panel.ring_vortex.back_right_vertex)
# Add this to the new row of wake ring vortex vertices.
first_row_of_wake_ring_vortex_vertices[
- 0, spanwise_position + 1
- ] = next_front_right_vertex
+ 0, spanwise_position + 1] = next_front_right_vertex
# Set the next wing's matrix of wake ring vortex vertices to
# a copy of the row of new wake ring vortex vertices. This is
# correct because this is the first time step.
next_wing.wake_ring_vortex_vertices = np.copy(
- first_row_of_wake_ring_vortex_vertices
- )
+ first_row_of_wake_ring_vortex_vertices)
# Initialize variables to hold the number of spanwise vertices.
num_spanwise_vertices = num_spanwise_panels + 1
@@ -1183,8 +1038,7 @@ def populate_next_airplanes_wake_vortex_vertices(self, prescribed_wake=True):
# Initialize a new matrix to hold the second row of wake ring
# vortex vertices.
second_row_of_wake_ring_vortex_vertices = np.zeros(
- (1, num_spanwise_panels + 1, 3)
- )
+ (1, num_spanwise_panels + 1, 3))
# Iterate through the spanwise vertex positions.
for spanwise_vertex_position in range(num_spanwise_vertices):
@@ -1192,45 +1046,34 @@ def populate_next_airplanes_wake_vortex_vertices(self, prescribed_wake=True):
# Get the corresponding vertex from the first row.
wake_ring_vortex_vertex = (
next_wing.wake_ring_vortex_vertices[
- 0, spanwise_vertex_position
- ]
- )
+ 0, spanwise_vertex_position])
if prescribed_wake:
# If the wake is prescribed, set the velocity at this
# vertex to the freestream velocity.
velocity_at_first_row_wake_ring_vortex_vertex = (
- self.current_freestream_velocity_geometry_axes
- )
+ self.current_freestream_velocity_geometry_axes)
else:
# If the wake is not prescribed, set the velocity at
# this vertex to the solution velocity at this point.
velocity_at_first_row_wake_ring_vortex_vertex = (
self.calculate_solution_velocity(
- np.expand_dims(wake_ring_vortex_vertex, axis=0)
- )
- )
+ np.expand_dims(wake_ring_vortex_vertex,
+ axis=0)))
# Update the second row with the interpolated position of
# the first vertex.
second_row_of_wake_ring_vortex_vertices[
- 0, spanwise_vertex_position
- ] = (
- wake_ring_vortex_vertex
- + velocity_at_first_row_wake_ring_vortex_vertex
- * self.delta_time
- )
+ 0, spanwise_vertex_position] = (
+ wake_ring_vortex_vertex + velocity_at_first_row_wake_ring_vortex_vertex * self.delta_time)
# Update the wing's wake ring vortex vertex matrix by
# vertically stacking the second row below it.
- next_wing.wake_ring_vortex_vertices = np.vstack(
- (
- next_wing.wake_ring_vortex_vertices,
- second_row_of_wake_ring_vortex_vertices,
- )
- )
+ next_wing.wake_ring_vortex_vertices = np.vstack((
+ next_wing.wake_ring_vortex_vertices,
+ second_row_of_wake_ring_vortex_vertices,))
# If this isn't the first step, then do this.
else:
@@ -1238,61 +1081,45 @@ def populate_next_airplanes_wake_vortex_vertices(self, prescribed_wake=True):
# Set the next wing's wake ring vortex vertex matrix to a
# copy of this wing's wake ring vortex vertex matrix.
next_wing.wake_ring_vortex_vertices = np.copy(
- this_wing.wake_ring_vortex_vertices
- )
+ this_wing.wake_ring_vortex_vertices)
# Get the number of chordwise and spanwise vertices.
num_chordwise_vertices = (
- next_wing.wake_ring_vortex_vertices.shape[0]
- )
+ next_wing.wake_ring_vortex_vertices.shape[0])
num_spanwise_vertices = (
- next_wing.wake_ring_vortex_vertices.shape[1]
- )
+ next_wing.wake_ring_vortex_vertices.shape[1])
# Iterate through the chordwise and spanwise vertex positions.
for chordwise_vertex_position in range(num_chordwise_vertices):
for spanwise_vertex_position in range(
- num_spanwise_vertices
- ):
+ num_spanwise_vertices):
# Get the wake ring vortex vertex at this position.
wake_ring_vortex_vertex = (
next_wing.wake_ring_vortex_vertices[
- chordwise_vertex_position,
- spanwise_vertex_position,
- ]
- )
+ chordwise_vertex_position, spanwise_vertex_position,])
if prescribed_wake:
# If the wake is prescribed, set the velocity at
# this vertex to the freestream velocity.
velocity_at_first_row_wake_vortex_vertex = (
- self.current_freestream_velocity_geometry_axes
- )
+ self.current_freestream_velocity_geometry_axes)
else:
# If the wake is not prescribed, set the velocity
# at this vertex to the solution velocity at this
# point.
velocity_at_first_row_wake_vortex_vertex = (
- np.squeeze(
- self.calculate_solution_velocity(
- np.expand_dims(
- wake_ring_vortex_vertex, axis=0
- )
- )
- )
- )
+ np.squeeze(self.calculate_solution_velocity(
+ np.expand_dims(wake_ring_vortex_vertex,
+ axis=0))))
# Update the vertex at this point with its
# interpolated position.
next_wing.wake_ring_vortex_vertices[
- chordwise_vertex_position, spanwise_vertex_position
- ] += (
- velocity_at_first_row_wake_vortex_vertex
- * self.delta_time
- )
+ chordwise_vertex_position, spanwise_vertex_position] += (
+ velocity_at_first_row_wake_vortex_vertex * self.delta_time)
# Set the chordwise position to the trailing edge.
chordwise_position = this_wing.num_chordwise_panels - 1
@@ -1300,8 +1127,7 @@ def populate_next_airplanes_wake_vortex_vertices(self, prescribed_wake=True):
# Initialize a new matrix to hold the new first row of wake
# ring vortex vertices.
first_row_of_wake_ring_vortex_vertices = np.zeros(
- (1, this_wing.num_spanwise_panels + 1, 3)
- )
+ (1, this_wing.num_spanwise_panels + 1, 3))
# Iterate spanwise through the trailing edge panels.
for spanwise_position in range(this_wing.num_spanwise_panels):
@@ -1309,32 +1135,25 @@ def populate_next_airplanes_wake_vortex_vertices(self, prescribed_wake=True):
# Get the panel object at this location on the next
# airplane's wing object.
next_panel = next_wing.panels[
- chordwise_position, spanwise_position
- ]
+ chordwise_position, spanwise_position]
# Add the panel object's back left ring vortex vertex to
# the matrix of new wake ring vortex vertices.
first_row_of_wake_ring_vortex_vertices[
- 0, spanwise_position
- ] = next_panel.ring_vortex.back_left_vertex
+ 0, spanwise_position] = next_panel.ring_vortex.back_left_vertex
if spanwise_position == (this_wing.num_spanwise_panels - 1):
-
# If the panel object is at the right edge of the
# wing, add its back right ring vortex vertex to the
# matrix of new wake ring vortex vertices.
first_row_of_wake_ring_vortex_vertices[
- 0, spanwise_position + 1
- ] = next_panel.ring_vortex.back_right_vertex
+ 0, spanwise_position + 1] = next_panel.ring_vortex.back_right_vertex
# Stack the new first row of wake ring vortex vertices above
# the wing's matrix of wake ring vortex vertices.
- next_wing.wake_ring_vortex_vertices = np.vstack(
- (
- first_row_of_wake_ring_vortex_vertices,
- next_wing.wake_ring_vortex_vertices,
- )
- )
+ next_wing.wake_ring_vortex_vertices = np.vstack((
+ first_row_of_wake_ring_vortex_vertices,
+ next_wing.wake_ring_vortex_vertices,))
def populate_next_airplanes_wake_vortices(self):
"""This method populates the locations of the next airplanes' wake vortices.
@@ -1355,39 +1174,32 @@ def populate_next_airplanes_wake_vortices(self):
# Iterate through the copy of the current airplane's wing positions.
for wing_id, this_wing in enumerate(
- self.current_airplanes[airplane_id].wings
- ):
+ self.current_airplanes[airplane_id].wings):
next_wing = next_airplane.wings[wing_id]
# Get the next wing's matrix of wake ring vortex vertices.
next_wing_wake_ring_vortex_vertices = (
- next_wing.wake_ring_vortex_vertices
- )
+ next_wing.wake_ring_vortex_vertices)
this_wing_wake_ring_vortices = (
- self.current_airplanes[airplane_id]
- .wings[wing_id]
- .wake_ring_vortices
- )
+ self.current_airplanes[airplane_id].wings[
+ wing_id].wake_ring_vortices)
# Find the number of chordwise and spanwise vertices in the next
# wing's matrix of wake ring vortex vertices.
num_chordwise_vertices = next_wing_wake_ring_vortex_vertices.shape[
- 0
- ]
+ 0]
num_spanwise_vertices = next_wing_wake_ring_vortex_vertices.shape[1]
# Initialize a new matrix to hold the new row of wake ring
# vortices.
new_row_of_wake_ring_vortices = np.empty(
- (1, num_spanwise_vertices - 1), dtype=object
- )
+ (1, num_spanwise_vertices - 1), dtype=object)
# Stack the new matrix on top of the copy of this wing's matrix
# and assign it to the next wing.
next_wing.wake_ring_vortices = np.vstack(
- (new_row_of_wake_ring_vortices, this_wing_wake_ring_vortices)
- )
+ (new_row_of_wake_ring_vortices, this_wing_wake_ring_vortices))
# Iterate through the vertex positions.
for chordwise_vertex_position in range(num_chordwise_vertices):
@@ -1396,11 +1208,9 @@ def populate_next_airplanes_wake_vortices(self):
# Set booleans to determine if this vertex is on the
# right and/or trailing edge of the wake.
has_right_vertex = (
- spanwise_vertex_position + 1
- ) < num_spanwise_vertices
+ spanwise_vertex_position + 1) < num_spanwise_vertices
has_back_vertex = (
- chordwise_vertex_position + 1
- ) < num_chordwise_vertices
+ chordwise_vertex_position + 1) < num_chordwise_vertices
if has_right_vertex and has_back_vertex:
@@ -1409,72 +1219,51 @@ def populate_next_airplanes_wake_vortices(self):
# be associated with the corresponding ring vortex at
# this position.
front_left_vertex = next_wing_wake_ring_vortex_vertices[
- chordwise_vertex_position, spanwise_vertex_position
- ]
+ chordwise_vertex_position, spanwise_vertex_position]
front_right_vertex = (
next_wing_wake_ring_vortex_vertices[
- chordwise_vertex_position,
- spanwise_vertex_position + 1,
- ]
- )
+ chordwise_vertex_position, spanwise_vertex_position + 1,])
back_left_vertex = next_wing_wake_ring_vortex_vertices[
- chordwise_vertex_position + 1,
- spanwise_vertex_position,
- ]
+ chordwise_vertex_position + 1, spanwise_vertex_position,]
back_right_vertex = next_wing_wake_ring_vortex_vertices[
- chordwise_vertex_position + 1,
- spanwise_vertex_position + 1,
- ]
+ chordwise_vertex_position + 1, spanwise_vertex_position + 1,]
if chordwise_vertex_position > 0:
# If this isn't the front of the wake, update the
# position of the ring vortex at this location.
next_wing.wake_ring_vortices[
- chordwise_vertex_position,
- spanwise_vertex_position,
- ].update_position(
+ chordwise_vertex_position, spanwise_vertex_position,].update_position(
front_left_vertex=front_left_vertex,
front_right_vertex=front_right_vertex,
back_left_vertex=back_left_vertex,
- back_right_vertex=back_right_vertex,
- )
+ back_right_vertex=back_right_vertex, )
# Also, update the age of this ring vortex.
if self.current_step == 0:
next_wing.wake_ring_vortices[
- chordwise_vertex_position,
- spanwise_vertex_position,
- ].age = self.delta_time
+ chordwise_vertex_position, spanwise_vertex_position,].age = self.delta_time
else:
next_wing.wake_ring_vortices[
- chordwise_vertex_position,
- spanwise_vertex_position,
- ].age += self.delta_time
+ chordwise_vertex_position, spanwise_vertex_position,].age += self.delta_time
if chordwise_vertex_position == 0:
-
# If this is the front of the wake, get the
# vortex strength from the wing panel's ring
# vortex direction in front of it.
this_strength_copy = this_wing.panels[
- this_wing.num_chordwise_panels - 1,
- spanwise_vertex_position,
- ].ring_vortex.strength
+ this_wing.num_chordwise_panels - 1, spanwise_vertex_position,].ring_vortex.strength
# Then, make a new ring vortex at this location,
# with the panel's ring vortex's strength,
# and add it to the matrix of ring vortices.
next_wing.wake_ring_vortices[
- chordwise_vertex_position,
- spanwise_vertex_position,
- ] = aerodynamics.RingVortex(
+ chordwise_vertex_position, spanwise_vertex_position,] = aerodynamics.RingVortex(
front_left_vertex=front_left_vertex,
front_right_vertex=front_right_vertex,
back_left_vertex=back_left_vertex,
back_right_vertex=back_right_vertex,
- strength=this_strength_copy,
- )
+ strength=this_strength_copy, )
def calculate_current_flapping_velocities_at_collocation_points(self):
"""This method finds the apparent flow velocity due to flapping at the
@@ -1492,7 +1281,6 @@ def calculate_current_flapping_velocities_at_collocation_points(self):
"""
# Check if the current step is the first step.
if self.current_step < 1:
-
# Set the flapping velocities to be zero for all points. Then, return the
# flapping velocities.
return np.zeros((self.num_panels, 3))
@@ -1521,7 +1309,6 @@ def calculate_current_flapping_velocities_at_right_leg_centers(self):
"""
# Check if the current step is the first step.
if self.current_step < 1:
-
# Set the flapping velocities to be zero for all points. Then, return the
# flapping velocities.
return np.zeros((self.num_panels, 3))
@@ -1550,7 +1337,6 @@ def calculate_current_flapping_velocities_at_front_leg_centers(self):
"""
# Check if the current step is the first step.
if self.current_step < 1:
-
# Set the flapping velocities to be zero for all points. Then, return the
# flapping velocities.
return np.zeros((self.num_panels, 3))
@@ -1579,7 +1365,6 @@ def calculate_current_flapping_velocities_at_left_leg_centers(self):
"""
# Check if the current step is the first step.
if self.current_step < 1:
-
# Set the flapping velocities to be zero for all points. Then, return the
# flapping velocities.
return np.zeros((self.num_panels, 3))
@@ -1610,17 +1395,13 @@ def finalize_near_field_forces_and_moments(self):
# Initialize matrices to hold the forces, moments, and coefficients at each of
# the time steps that has results.
total_near_field_forces_wind_axes = np.zeros(
- (self.num_airplanes, 3, num_steps_to_average)
- )
+ (self.num_airplanes, 3, num_steps_to_average))
total_near_field_force_coefficients_wind_axes = np.zeros(
- (self.num_airplanes, 3, num_steps_to_average)
- )
+ (self.num_airplanes, 3, num_steps_to_average))
total_near_field_moments_wind_axes = np.zeros(
- (self.num_airplanes, 3, num_steps_to_average)
- )
+ (self.num_airplanes, 3, num_steps_to_average))
total_near_field_moment_coefficients_wind_axes = np.zeros(
- (self.num_airplanes, 3, num_steps_to_average)
- )
+ (self.num_airplanes, 3, num_steps_to_average))
# Initialize a variable to track position in the results arrays.
results_step = 0
@@ -1635,17 +1416,13 @@ def finalize_near_field_forces_and_moments(self):
# Iterate through this step's airplanes.
for airplane_id, airplane in enumerate(these_airplanes):
total_near_field_forces_wind_axes[airplane_id, :, results_step] = (
- airplane.total_near_field_force_wind_axes
- )
- total_near_field_force_coefficients_wind_axes[
- airplane_id, :, results_step
- ] = airplane.total_near_field_force_coefficients_wind_axes
+ airplane.total_near_field_force_wind_axes)
+ total_near_field_force_coefficients_wind_axes[airplane_id, :,
+ results_step] = airplane.total_near_field_force_coefficients_wind_axes
total_near_field_moments_wind_axes[airplane_id, :, results_step] = (
- airplane.total_near_field_moment_wind_axes
- )
- total_near_field_moment_coefficients_wind_axes[
- airplane_id, :, results_step
- ] = airplane.total_near_field_moment_coefficients_wind_axes
+ airplane.total_near_field_moment_wind_axes)
+ total_near_field_moment_coefficients_wind_axes[airplane_id, :,
+ results_step] = airplane.total_near_field_moment_coefficients_wind_axes
results_step += 1
@@ -1655,82 +1432,51 @@ def finalize_near_field_forces_and_moments(self):
if is_static:
self.unsteady_problem.final_near_field_forces_wind_axes.append(
- total_near_field_forces_wind_axes[airplane_id, :, -1]
- )
+ total_near_field_forces_wind_axes[airplane_id, :, -1])
self.unsteady_problem.final_near_field_force_coefficients_wind_axes.append(
- total_near_field_force_coefficients_wind_axes[airplane_id, :, -1]
- )
+ total_near_field_force_coefficients_wind_axes[airplane_id, :, -1])
self.unsteady_problem.final_near_field_moments_wind_axes.append(
- total_near_field_moments_wind_axes[airplane_id, :, -1]
- )
+ total_near_field_moments_wind_axes[airplane_id, :, -1])
self.unsteady_problem.final_near_field_moment_coefficients_wind_axes.append(
- total_near_field_moment_coefficients_wind_axes[airplane_id, :, -1]
- )
+ total_near_field_moment_coefficients_wind_axes[airplane_id, :, -1])
else:
- mean_forces = np.mean(
- total_near_field_forces_wind_axes[airplane_id], axis=-1
- )
+ mean_forces = np.mean(total_near_field_forces_wind_axes[airplane_id],
+ axis=-1)
mean_force_coefficients = np.mean(
- total_near_field_force_coefficients_wind_axes[airplane_id], axis=-1
- )
- mean_moments = np.mean(
- total_near_field_moments_wind_axes[airplane_id], axis=-1
- )
+ total_near_field_force_coefficients_wind_axes[airplane_id], axis=-1)
+ mean_moments = np.mean(total_near_field_moments_wind_axes[airplane_id],
+ axis=-1)
mean_moment_coefficients = np.mean(
- total_near_field_moment_coefficients_wind_axes[airplane_id], axis=-1
- )
+ total_near_field_moment_coefficients_wind_axes[airplane_id],
+ axis=-1)
rms_forces = np.sqrt(
- np.mean(
- np.square(total_near_field_forces_wind_axes[airplane_id]),
- axis=-1,
- )
- )
- rms_force_coefficients = np.sqrt(
- np.mean(
- np.square(
- total_near_field_force_coefficients_wind_axes[airplane_id]
- ),
- axis=-1,
- )
- )
+ np.mean(np.square(total_near_field_forces_wind_axes[airplane_id]),
+ axis=-1, ))
+ rms_force_coefficients = np.sqrt(np.mean(np.square(
+ total_near_field_force_coefficients_wind_axes[airplane_id]),
+ axis=-1, ))
rms_moments = np.sqrt(
- np.mean(
- np.square(total_near_field_moments_wind_axes[airplane_id]),
- axis=-1,
- )
- )
- rms_moment_coefficients = np.sqrt(
- np.mean(
- np.square(
- total_near_field_moment_coefficients_wind_axes[airplane_id]
- ),
- axis=-1,
- )
- )
+ np.mean(np.square(total_near_field_moments_wind_axes[airplane_id]),
+ axis=-1, ))
+ rms_moment_coefficients = np.sqrt(np.mean(np.square(
+ total_near_field_moment_coefficients_wind_axes[airplane_id]),
+ axis=-1, ))
self.unsteady_problem.final_mean_near_field_forces_wind_axes.append(
- mean_forces
- )
+ mean_forces)
self.unsteady_problem.final_mean_near_field_force_coefficients_wind_axes.append(
- mean_force_coefficients
- )
+ mean_force_coefficients)
self.unsteady_problem.final_mean_near_field_moments_wind_axes.append(
- mean_moments
- )
+ mean_moments)
self.unsteady_problem.final_mean_near_field_moment_coefficients_wind_axes.append(
- mean_moment_coefficients
- )
+ mean_moment_coefficients)
self.unsteady_problem.final_rms_near_field_forces_wind_axes.append(
- rms_forces
- )
+ rms_forces)
self.unsteady_problem.final_rms_near_field_force_coefficients_wind_axes.append(
- rms_force_coefficients
- )
+ rms_force_coefficients)
self.unsteady_problem.final_rms_near_field_moments_wind_axes.append(
- rms_moments
- )
+ rms_moments)
self.unsteady_problem.final_rms_near_field_moment_coefficients_wind_axes.append(
- rms_moment_coefficients
- )
+ rms_moment_coefficients)
diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py
index a0b7b703..18ef002b 100644
--- a/tests/integration/__init__.py
+++ b/tests/integration/__init__.py
@@ -48,7 +48,10 @@
import tests.integration.test_steady_ring_vortex_lattice_method
import tests.integration.test_steady_trim
import tests.integration.test_unsteady_convergence
-import tests.integration.test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry
-import tests.integration.test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry
+import \
+ (tests.integration
+ .test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry)
+import \
+ tests.integration.test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry
import tests.integration.test_unsteady_ring_vortex_lattice_method_static_geometry
import tests.integration.test_unsteady_ring_vortex_lattice_method_variable_geometry
diff --git a/tests/integration/fixtures/airplane_fixtures.py b/tests/integration/fixtures/airplane_fixtures.py
index 2cb5c0d6..7d966530 100644
--- a/tests/integration/fixtures/airplane_fixtures.py
+++ b/tests/integration/fixtures/airplane_fixtures.py
@@ -35,25 +35,12 @@ def make_steady_validation_airplane():
This is the airplane fixture.
"""
# Create and return the airplane object.
- steady_validation_airplane = ps.geometry.Airplane(
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- ),
- ps.geometry.WingCrossSection(
- x_le=1.0,
- y_le=5.0,
- twist=5.0,
- chord=0.75,
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- ),
- ],
- )
- ],
- )
+ steady_validation_airplane = ps.geometry.Airplane(wings=[
+ ps.geometry.Wing(symmetric=True, wing_cross_sections=[
+ ps.geometry.WingCrossSection(
+ airfoil=ps.geometry.Airfoil(name="naca2412"), ),
+ ps.geometry.WingCrossSection(x_le=1.0, y_le=5.0, twist=5.0, chord=0.75,
+ airfoil=ps.geometry.Airfoil(name="naca2412"), ), ], )], )
return steady_validation_airplane
@@ -65,109 +52,41 @@ def make_multiple_wing_steady_validation_airplane():
This is the airplane fixture.
"""
# Create and return the airplane object.
- multiple_wing_steady_validation_airplane = ps.geometry.Airplane(
- x_ref=0.0,
- y_ref=0.0,
- z_ref=0.0,
- weight=1 * 9.81,
- wings=[
- ps.geometry.Wing(
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- chord=1.0,
- twist=0.0,
- airfoil=ps.geometry.Airfoil(
- name="naca23012",
- coordinates=None,
- repanel=True,
- n_points_per_side=400,
- ),
- control_surface_type="symmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=0.0,
- num_spanwise_panels=8,
- spanwise_spacing="uniform",
- ),
- ps.geometry.WingCrossSection(
- x_le=1.0,
- y_le=5.0,
- z_le=0.0,
- chord=0.75,
- twist=0.0,
- airfoil=ps.geometry.Airfoil(
- name="naca23012",
- coordinates=None,
- repanel=True,
- n_points_per_side=400,
- ),
- control_surface_type="symmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=0.0,
- num_spanwise_panels=8,
- spanwise_spacing="uniform",
- ),
- ],
- symmetric=True,
- num_chordwise_panels=8,
- chordwise_spacing="uniform",
- ),
- ps.geometry.Wing(
- x_le=5.0,
- y_le=0.0,
- z_le=0.0,
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- x_le=0.0,
- y_le=0.0,
- z_le=0.0,
- chord=1.00,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0010",
- coordinates=None,
- repanel=True,
- n_points_per_side=400,
- ),
- control_surface_type="symmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=0.0,
- num_spanwise_panels=8,
- spanwise_spacing="uniform",
- ),
- ps.geometry.WingCrossSection(
- x_le=1.0,
- y_le=1.0,
- z_le=0.0,
- chord=0.75,
- twist=-5.0,
- airfoil=ps.geometry.Airfoil(
- name="naca0010",
- coordinates=None,
- repanel=True,
- n_points_per_side=400,
- ),
- control_surface_type="symmetric",
- control_surface_hinge_point=0.75,
- control_surface_deflection=0.0,
- num_spanwise_panels=8,
- spanwise_spacing="uniform",
- ),
- ],
- symmetric=True,
- num_chordwise_panels=8,
- chordwise_spacing="uniform",
- ),
- ],
- s_ref=None,
- c_ref=None,
- b_ref=None,
- )
+ multiple_wing_steady_validation_airplane = ps.geometry.Airplane(x_ref=0.0,
+ y_ref=0.0, z_ref=0.0, weight=1 * 9.81, wings=[
+ ps.geometry.Wing(x_le=0.0, y_le=0.0, z_le=0.0, wing_cross_sections=[
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=0.0, z_le=0.0, chord=1.0,
+ twist=0.0,
+ airfoil=ps.geometry.Airfoil(name="naca23012", coordinates=None,
+ repanel=True, n_points_per_side=400, ),
+ control_surface_type="symmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=0.0, num_spanwise_panels=8,
+ spanwise_spacing="uniform", ),
+ ps.geometry.WingCrossSection(x_le=1.0, y_le=5.0, z_le=0.0, chord=0.75,
+ twist=0.0,
+ airfoil=ps.geometry.Airfoil(name="naca23012", coordinates=None,
+ repanel=True, n_points_per_side=400, ),
+ control_surface_type="symmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=0.0, num_spanwise_panels=8,
+ spanwise_spacing="uniform", ), ], symmetric=True,
+ num_chordwise_panels=8, chordwise_spacing="uniform", ),
+ ps.geometry.Wing(x_le=5.0, y_le=0.0, z_le=0.0, wing_cross_sections=[
+ ps.geometry.WingCrossSection(x_le=0.0, y_le=0.0, z_le=0.0, chord=1.00,
+ twist=-5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0010", coordinates=None,
+ repanel=True, n_points_per_side=400, ),
+ control_surface_type="symmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=0.0, num_spanwise_panels=8,
+ spanwise_spacing="uniform", ),
+ ps.geometry.WingCrossSection(x_le=1.0, y_le=1.0, z_le=0.0, chord=0.75,
+ twist=-5.0,
+ airfoil=ps.geometry.Airfoil(name="naca0010", coordinates=None,
+ repanel=True, n_points_per_side=400, ),
+ control_surface_type="symmetric", control_surface_hinge_point=0.75,
+ control_surface_deflection=0.0, num_spanwise_panels=8,
+ spanwise_spacing="uniform", ), ], symmetric=True,
+ num_chordwise_panels=8, chordwise_spacing="uniform", ), ], s_ref=None,
+ c_ref=None, b_ref=None, )
return multiple_wing_steady_validation_airplane
@@ -179,30 +98,14 @@ def make_asymmetric_unsteady_validation_airplane():
This is the airplane fixture.
"""
# Create and return the airplane object.
- asymmetric_unsteady_validation_airplane = ps.geometry.Airplane(
- y_ref=5.0,
- wings=[
- ps.geometry.Wing(
- num_chordwise_panels=8,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- num_spanwise_panels=16,
- spanwise_spacing="cosine",
- chord=1.0,
- ),
- ps.geometry.WingCrossSection(
- y_le=10.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- num_spanwise_panels=16,
- spanwise_spacing="cosine",
- ),
- ],
- )
- ],
- )
+ asymmetric_unsteady_validation_airplane = ps.geometry.Airplane(y_ref=5.0, wings=[
+ ps.geometry.Wing(num_chordwise_panels=8, chordwise_spacing="uniform",
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ airfoil=ps.geometry.Airfoil(name="naca2412"), num_spanwise_panels=16,
+ spanwise_spacing="cosine", chord=1.0, ),
+ ps.geometry.WingCrossSection(y_le=10.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412"),
+ num_spanwise_panels=16, spanwise_spacing="cosine", ), ], )], )
return asymmetric_unsteady_validation_airplane
@@ -214,27 +117,14 @@ def make_symmetric_unsteady_validation_airplane():
This is the airplane fixture.
"""
# Create and return the airplane object.
- symmetric_unsteady_validation_airplane = ps.geometry.Airplane(
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- chord=2.0,
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- y_le=5.0,
- chord=2.0,
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- spanwise_spacing="cosine",
- ),
- ],
- ),
- ],
- )
+ symmetric_unsteady_validation_airplane = ps.geometry.Airplane(wings=[
+ ps.geometry.Wing(symmetric=True, chordwise_spacing="uniform",
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ airfoil=ps.geometry.Airfoil(name="naca2412"), chord=2.0,
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(y_le=5.0, chord=2.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412"),
+ spanwise_spacing="cosine", ), ], ), ], )
return symmetric_unsteady_validation_airplane
@@ -246,69 +136,28 @@ def make_symmetric_multiple_wing_unsteady_validation_airplane():
This is the airplane fixture.
"""
# Create and return the airplane object.
- symmetric_multiple_wing_steady_validation_airplane = ps.geometry.Airplane(
- wings=[
- ps.geometry.Wing(
- symmetric=True,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- chord=1.5,
- spanwise_spacing="cosine",
- ),
- ps.geometry.WingCrossSection(
- x_le=0.5,
- y_le=5.0,
- z_le=0.0,
- chord=1.0,
- airfoil=ps.geometry.Airfoil(name="naca2412"),
- spanwise_spacing="cosine",
- ),
- ],
- ),
- ps.geometry.Wing(
- symmetric=True,
- z_le=1.75,
- x_le=6.25,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(name="naca0010"),
- spanwise_spacing="cosine",
- twist=-5.0,
- chord=1.00,
- ),
- ps.geometry.WingCrossSection(
- y_le=1.5,
- twist=-5.0,
- chord=0.75,
- x_le=0.25,
- airfoil=ps.geometry.Airfoil(name="naca0010"),
- spanwise_spacing="cosine",
- ),
- ],
- ),
- ps.geometry.Wing(
- symmetric=False,
- z_le=0.125,
- x_le=6.25,
- chordwise_spacing="uniform",
- wing_cross_sections=[
- ps.geometry.WingCrossSection(
- airfoil=ps.geometry.Airfoil(name="naca0010"),
- spanwise_spacing="cosine",
- chord=1.0,
- ),
- ps.geometry.WingCrossSection(
- z_le=1.5,
- chord=0.75,
- x_le=0.25,
- airfoil=ps.geometry.Airfoil(name="naca0010"),
- spanwise_spacing="cosine",
- ),
- ],
- ),
- ],
- )
+ symmetric_multiple_wing_steady_validation_airplane = ps.geometry.Airplane(wings=[
+ ps.geometry.Wing(symmetric=True, chordwise_spacing="uniform",
+ wing_cross_sections=[ps.geometry.WingCrossSection(
+ airfoil=ps.geometry.Airfoil(name="naca2412"), chord=1.5,
+ spanwise_spacing="cosine", ),
+ ps.geometry.WingCrossSection(x_le=0.5, y_le=5.0, z_le=0.0, chord=1.0,
+ airfoil=ps.geometry.Airfoil(name="naca2412"),
+ spanwise_spacing="cosine", ), ], ),
+ ps.geometry.Wing(symmetric=True, z_le=1.75, x_le=6.25,
+ chordwise_spacing="uniform", wing_cross_sections=[
+ ps.geometry.WingCrossSection(
+ airfoil=ps.geometry.Airfoil(name="naca0010"),
+ spanwise_spacing="cosine", twist=-5.0, chord=1.00, ),
+ ps.geometry.WingCrossSection(y_le=1.5, twist=-5.0, chord=0.75,
+ x_le=0.25, airfoil=ps.geometry.Airfoil(name="naca0010"),
+ spanwise_spacing="cosine", ), ], ),
+ ps.geometry.Wing(symmetric=False, z_le=0.125, x_le=6.25,
+ chordwise_spacing="uniform", wing_cross_sections=[
+ ps.geometry.WingCrossSection(
+ airfoil=ps.geometry.Airfoil(name="naca0010"),
+ spanwise_spacing="cosine", chord=1.0, ),
+ ps.geometry.WingCrossSection(z_le=1.5, chord=0.75, x_le=0.25,
+ airfoil=ps.geometry.Airfoil(name="naca0010"),
+ spanwise_spacing="cosine", ), ], ), ], )
return symmetric_multiple_wing_steady_validation_airplane
diff --git a/tests/integration/fixtures/movement_fixtures.py b/tests/integration/fixtures/movement_fixtures.py
index d69598ab..4b733f35 100644
--- a/tests/integration/fixtures/movement_fixtures.py
+++ b/tests/integration/fixtures/movement_fixtures.py
@@ -34,40 +34,27 @@ def make_static_validation_movement():
# Construct an airplane object and an operating point object.
unsteady_validation_airplane = (
- airplane_fixtures.make_asymmetric_unsteady_validation_airplane()
- )
+ airplane_fixtures.make_asymmetric_unsteady_validation_airplane())
unsteady_validation_operating_point = (
- operating_point_fixtures.make_validation_operating_point()
- )
+ operating_point_fixtures.make_validation_operating_point())
# Create a wing cross section movement object associated with this airplane's
# root wing cross section.
unsteady_validation_root_wing_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[0]
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[0]))
# Create a wing cross section movement object associated with this airplane's tip
# wing cross section.
unsteady_validation_tip_wing_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[1],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[1], ))
# Create a wing movement object associated with this airplane's wing.
unsteady_validation_wing_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[0],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[0], wing_cross_sections_movements=[
unsteady_validation_root_wing_cross_section_movement,
- unsteady_validation_tip_wing_cross_section_movement,
- ],
- )
+ unsteady_validation_tip_wing_cross_section_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_root_wing_cross_section_movement
@@ -76,8 +63,7 @@ def make_static_validation_movement():
# Create an airplane movement object associated with this airplane.
unsteady_validation_airplane_movement = ps.movement.AirplaneMovement(
base_airplane=unsteady_validation_airplane,
- wing_movements=[unsteady_validation_wing_movement],
- )
+ wing_movements=[unsteady_validation_wing_movement], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane
@@ -85,8 +71,7 @@ def make_static_validation_movement():
# Create an operating point movement object associated with this operating point.
unsteady_validation_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=unsteady_validation_operating_point
- )
+ base_operating_point=unsteady_validation_operating_point)
# Delete the now extraneous constructing fixtures.
del unsteady_validation_operating_point
@@ -95,9 +80,7 @@ def make_static_validation_movement():
unsteady_validation_movement = ps.movement.Movement(
airplane_movements=[unsteady_validation_airplane_movement],
operating_point_movement=unsteady_validation_operating_point_movement,
- num_steps=None,
- delta_time=None,
- )
+ num_steps=None, delta_time=None, )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane_movement
@@ -116,49 +99,30 @@ def make_variable_validation_movement():
# Construct an airplane object and an operating point object.
unsteady_validation_airplane = (
- airplane_fixtures.make_symmetric_unsteady_validation_airplane()
- )
+ airplane_fixtures.make_symmetric_unsteady_validation_airplane())
unsteady_validation_operating_point = (
- operating_point_fixtures.make_validation_operating_point()
- )
+ operating_point_fixtures.make_validation_operating_point())
# Create a wing cross section movement object associated with this airplane's
# root wing cross section.
unsteady_validation_root_wing_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[0],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[0], ))
# Create a wing cross section movement object associated with this airplane's tip
# wing cross section.
unsteady_validation_tip_wing_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_amplitude=30.0,
- sweeping_period=1.0,
- sweeping_spacing="sine",
- pitching_amplitude=30.0,
- pitching_period=0.5,
- pitching_spacing="sine",
- heaving_amplitude=30.0,
- heaving_period=0.5,
- heaving_spacing="sine",
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=30.0, sweeping_period=1.0, sweeping_spacing="sine",
+ pitching_amplitude=30.0, pitching_period=0.5, pitching_spacing="sine",
+ heaving_amplitude=30.0, heaving_period=0.5, heaving_spacing="sine", ))
# Create a wing movement object associated with this airplane's wing.
unsteady_validation_wing_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[0],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[0], wing_cross_sections_movements=[
unsteady_validation_root_wing_cross_section_movement,
- unsteady_validation_tip_wing_cross_section_movement,
- ],
- )
+ unsteady_validation_tip_wing_cross_section_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_root_wing_cross_section_movement
@@ -167,10 +131,7 @@ def make_variable_validation_movement():
# Create an airplane movement object associated with this airplane.
unsteady_validation_airplane_movement = ps.movement.AirplaneMovement(
base_airplane=unsteady_validation_airplane,
- wing_movements=[
- unsteady_validation_wing_movement,
- ],
- )
+ wing_movements=[unsteady_validation_wing_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane
@@ -178,8 +139,7 @@ def make_variable_validation_movement():
# Create an operating point movement object associated with this operating point.
unsteady_validation_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=unsteady_validation_operating_point,
- )
+ base_operating_point=unsteady_validation_operating_point, )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_operating_point
@@ -187,8 +147,7 @@ def make_variable_validation_movement():
# Create a movement object associated with this airplane and operating point.
unsteady_validation_movement = ps.movement.Movement(
airplane_movements=[unsteady_validation_airplane_movement],
- operating_point_movement=unsteady_validation_operating_point_movement,
- )
+ operating_point_movement=unsteady_validation_operating_point_movement, )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane_movement
@@ -208,99 +167,64 @@ def make_multiple_wing_static_validation_movement():
# Construct an airplane object and an operating point object.
unsteady_validation_airplane = (
- airplane_fixtures.make_symmetric_multiple_wing_unsteady_validation_airplane()
- )
+ airplane_fixtures.make_symmetric_multiple_wing_unsteady_validation_airplane())
unsteady_validation_operating_point = (
- operating_point_fixtures.make_validation_operating_point()
- )
+ operating_point_fixtures.make_validation_operating_point())
# Create a wing cross section movement object associated with this airplane's
# main wing's root wing cross section.
unsteady_validation_main_wing_root_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[0]
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[0]))
# Create a wing cross section movement object associated with this airplane's
# main wing's tip wing cross section.
unsteady_validation_main_wing_tip_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[1],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[1], ))
# Create a wing cross section movement object associated with this airplane's
# horizontal stabilizer's root wing cross section.
unsteady_validation_hstab_root_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 1
- ].wing_cross_sections[0]
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[1].wing_cross_sections[0]))
# Create a wing cross section movement object associated with this airplane's
# horizontal stabilizer's tip wing cross section.
unsteady_validation_hstab_tip_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 1
- ].wing_cross_sections[1],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[1].wing_cross_sections[1], ))
# Create a wing cross section movement object associated with this airplane's
# vertical stabilizer's root wing cross section.
unsteady_validation_vstab_root_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 2
- ].wing_cross_sections[0]
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[2].wing_cross_sections[0]))
# Create a wing cross section movement object associated with this airplane's
# vertical stabilizer's tip wing cross section.
unsteady_validation_vstab_tip_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 2
- ].wing_cross_sections[1],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[2].wing_cross_sections[1], ))
# Create a wing movement object associated with this airplane's main wing.
unsteady_validation_main_wing_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[0],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[0], wing_cross_sections_movements=[
unsteady_validation_main_wing_root_cross_section_movement,
- unsteady_validation_main_wing_tip_cross_section_movement,
- ],
- )
+ unsteady_validation_main_wing_tip_cross_section_movement, ], )
# Create a wing movement object associated with this airplane's horizontal
# stabilizer.
unsteady_validation_hstab_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[1],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[1], wing_cross_sections_movements=[
unsteady_validation_hstab_root_cross_section_movement,
- unsteady_validation_hstab_tip_cross_section_movement,
- ],
- )
+ unsteady_validation_hstab_tip_cross_section_movement, ], )
# Create a wing movement object associated with this airplane's vertical stabilizer.
unsteady_validation_vstab_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[2],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[2], wing_cross_sections_movements=[
unsteady_validation_vstab_root_cross_section_movement,
- unsteady_validation_vstab_tip_cross_section_movement,
- ],
- )
+ unsteady_validation_vstab_tip_cross_section_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_main_wing_root_cross_section_movement
@@ -313,12 +237,8 @@ def make_multiple_wing_static_validation_movement():
# Create an airplane movement object associated with this airplane.
unsteady_validation_airplane_movement = ps.movement.AirplaneMovement(
base_airplane=unsteady_validation_airplane,
- wing_movements=[
- unsteady_validation_main_wing_movement,
- unsteady_validation_hstab_movement,
- unsteady_validation_vstab_movement,
- ],
- )
+ wing_movements=[unsteady_validation_main_wing_movement,
+ unsteady_validation_hstab_movement, unsteady_validation_vstab_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane
@@ -328,8 +248,7 @@ def make_multiple_wing_static_validation_movement():
# Create an operating point movement object associated with this operating point.
unsteady_validation_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=unsteady_validation_operating_point
- )
+ base_operating_point=unsteady_validation_operating_point)
# Delete the now extraneous constructing fixtures.
del unsteady_validation_operating_point
@@ -338,9 +257,7 @@ def make_multiple_wing_static_validation_movement():
unsteady_validation_movement = ps.movement.Movement(
airplane_movements=[unsteady_validation_airplane_movement],
operating_point_movement=unsteady_validation_operating_point_movement,
- num_steps=8,
- delta_time=1 / 8 / 10,
- )
+ num_steps=8, delta_time=1 / 8 / 10, )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane_movement
@@ -360,108 +277,67 @@ def make_multiple_wing_variable_validation_movement():
# Construct an airplane object and an operating point object.
unsteady_validation_airplane = (
- airplane_fixtures.make_symmetric_multiple_wing_unsteady_validation_airplane()
- )
+ airplane_fixtures.make_symmetric_multiple_wing_unsteady_validation_airplane())
unsteady_validation_operating_point = (
- operating_point_fixtures.make_validation_operating_point()
- )
+ operating_point_fixtures.make_validation_operating_point())
# Create a wing cross section movement object associated with this airplane's
# main wing's root wing cross section.
unsteady_validation_main_wing_root_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[0],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[0], ))
# Create a wing cross section movement object associated with this airplane's
# main wing's tip wing cross section.
unsteady_validation_main_wing_tip_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 0
- ].wing_cross_sections[1],
- sweeping_amplitude=30.0,
- sweeping_period=1.0,
- sweeping_spacing="sine",
- heaving_amplitude=15.0,
- heaving_period=1.0,
- heaving_spacing="sine",
- pitching_amplitude=15.0,
- pitching_period=0.5,
- pitching_spacing="sine",
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[0].wing_cross_sections[1],
+ sweeping_amplitude=30.0, sweeping_period=1.0, sweeping_spacing="sine",
+ heaving_amplitude=15.0, heaving_period=1.0, heaving_spacing="sine",
+ pitching_amplitude=15.0, pitching_period=0.5, pitching_spacing="sine", ))
# Create a wing cross section movement object associated with this airplane's
# horizontal stabilizer's root wing cross section.
unsteady_validation_hstab_root_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 1
- ].wing_cross_sections[0]
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[1].wing_cross_sections[0]))
# Create a wing cross section movement object associated with this airplane's
# horizontal stabilizer's tip wing cross section.
unsteady_validation_hstab_tip_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 1
- ].wing_cross_sections[1],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[1].wing_cross_sections[1], ))
# Create a wing cross section movement object associated with this airplane's
# vertical stabilizer's root wing cross section.
unsteady_validation_vstab_root_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 2
- ].wing_cross_sections[0]
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[2].wing_cross_sections[0]))
# Create a wing cross section movement object associated with this airplane's
# vertical stabilizer's tip wing cross section.
unsteady_validation_vstab_tip_cross_section_movement = (
- ps.movement.WingCrossSectionMovement(
- base_wing_cross_section=unsteady_validation_airplane.wings[
- 2
- ].wing_cross_sections[1],
- )
- )
+ ps.movement.WingCrossSectionMovement(base_wing_cross_section=
+ unsteady_validation_airplane.wings[2].wing_cross_sections[1], ))
# Create a wing movement object associated with this airplane's main wing.
unsteady_validation_main_wing_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[0],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[0], wing_cross_sections_movements=[
unsteady_validation_main_wing_root_cross_section_movement,
- unsteady_validation_main_wing_tip_cross_section_movement,
- ],
- )
+ unsteady_validation_main_wing_tip_cross_section_movement, ], )
# Create a wing movement object associated with this airplane's horizontal
# stabilizer.
unsteady_validation_hstab_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[1],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[1], wing_cross_sections_movements=[
unsteady_validation_hstab_root_cross_section_movement,
- unsteady_validation_hstab_tip_cross_section_movement,
- ],
- )
+ unsteady_validation_hstab_tip_cross_section_movement, ], )
# Create a wing movement object associated with this airplane's vertical stabilizer.
unsteady_validation_vstab_movement = ps.movement.WingMovement(
- base_wing=unsteady_validation_airplane.wings[2],
- wing_cross_sections_movements=[
+ base_wing=unsteady_validation_airplane.wings[2], wing_cross_sections_movements=[
unsteady_validation_vstab_root_cross_section_movement,
- unsteady_validation_vstab_tip_cross_section_movement,
- ],
- )
+ unsteady_validation_vstab_tip_cross_section_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_main_wing_root_cross_section_movement
@@ -474,12 +350,8 @@ def make_multiple_wing_variable_validation_movement():
# Create an airplane movement object associated with this airplane.
unsteady_validation_airplane_movement = ps.movement.AirplaneMovement(
base_airplane=unsteady_validation_airplane,
- wing_movements=[
- unsteady_validation_main_wing_movement,
- unsteady_validation_hstab_movement,
- unsteady_validation_vstab_movement,
- ],
- )
+ wing_movements=[unsteady_validation_main_wing_movement,
+ unsteady_validation_hstab_movement, unsteady_validation_vstab_movement, ], )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane
@@ -489,8 +361,7 @@ def make_multiple_wing_variable_validation_movement():
# Create an operating point movement object associated with this operating point.
unsteady_validation_operating_point_movement = ps.movement.OperatingPointMovement(
- base_operating_point=unsteady_validation_operating_point
- )
+ base_operating_point=unsteady_validation_operating_point)
# Delete the now extraneous constructing fixtures.
del unsteady_validation_operating_point
@@ -499,9 +370,7 @@ def make_multiple_wing_variable_validation_movement():
unsteady_validation_movement = ps.movement.Movement(
airplane_movements=[unsteady_validation_airplane_movement],
operating_point_movement=unsteady_validation_operating_point_movement,
- num_steps=20,
- delta_time=1 / 8 / 10,
- )
+ num_steps=20, delta_time=1 / 8 / 10, )
# Delete the now extraneous constructing fixtures.
del unsteady_validation_airplane_movement
diff --git a/tests/integration/fixtures/problem_fixtures.py b/tests/integration/fixtures/problem_fixtures.py
index acc1c361..c8e7f4b1 100644
--- a/tests/integration/fixtures/problem_fixtures.py
+++ b/tests/integration/fixtures/problem_fixtures.py
@@ -44,14 +44,12 @@ def make_steady_validation_problem():
# Create the constructing fixtures.
steady_validation_airplane = airplane_fixtures.make_steady_validation_airplane()
steady_validation_operating_point = (
- operating_point_fixtures.make_validation_operating_point()
- )
+ operating_point_fixtures.make_validation_operating_point())
# Create the problem fixture.
steady_validation_problem = ps.problems.SteadyProblem(
airplanes=[steady_validation_airplane],
- operating_point=steady_validation_operating_point,
- )
+ operating_point=steady_validation_operating_point, )
# Delete the constructing fixtures.
del steady_validation_airplane
@@ -71,17 +69,14 @@ def make_steady_multiple_wing_validation_problem():
# Create the constructing fixtures.
steady_validation_airplane = (
- airplane_fixtures.make_multiple_wing_steady_validation_airplane()
- )
+ airplane_fixtures.make_multiple_wing_steady_validation_airplane())
steady_validation_operating_point = (
- operating_point_fixtures.make_validation_operating_point()
- )
+ operating_point_fixtures.make_validation_operating_point())
# Create the problem fixture.
steady_validation_problem = ps.problems.SteadyProblem(
airplanes=[steady_validation_airplane],
- operating_point=steady_validation_operating_point,
- )
+ operating_point=steady_validation_operating_point, )
# Delete the constructing fixtures.
del steady_validation_airplane
@@ -104,8 +99,7 @@ def make_unsteady_validation_problem_with_static_geometry():
# Create the problem fixture.
unsteady_validation_problem = ps.problems.UnsteadyProblem(
- movement=unsteady_validation_movement
- )
+ movement=unsteady_validation_movement)
# Delete the constructing fixture.
del unsteady_validation_movement
@@ -127,8 +121,7 @@ def make_unsteady_validation_problem_with_variable_geometry():
# Create the problem fixture.
unsteady_validation_problem = ps.problems.UnsteadyProblem(
- movement=unsteady_validation_movement
- )
+ movement=unsteady_validation_movement)
# Delete the constructing fixture.
del unsteady_validation_movement
@@ -147,13 +140,11 @@ def make_unsteady_validation_problem_with_multiple_wing_static_geometry():
# Create the constructing fixture.
unsteady_validation_movement = (
- movement_fixtures.make_multiple_wing_static_validation_movement()
- )
+ movement_fixtures.make_multiple_wing_static_validation_movement())
# Create the problem fixture.
unsteady_validation_problem = ps.problems.UnsteadyProblem(
- movement=unsteady_validation_movement
- )
+ movement=unsteady_validation_movement)
# Delete the constructing fixture.
del unsteady_validation_movement
@@ -172,13 +163,11 @@ def make_unsteady_validation_problem_with_multiple_wing_variable_geometry():
# Create the constructing fixture.
unsteady_validation_movement = (
- movement_fixtures.make_multiple_wing_variable_validation_movement()
- )
+ movement_fixtures.make_multiple_wing_variable_validation_movement())
# Create the problem fixture.
unsteady_validation_problem = ps.problems.UnsteadyProblem(
- movement=unsteady_validation_movement
- )
+ movement=unsteady_validation_movement)
# Delete the constructing fixture.
del unsteady_validation_movement
diff --git a/tests/integration/test_output.py b/tests/integration/test_output.py
index 7e6854fc..91effbed 100644
--- a/tests/integration/test_output.py
+++ b/tests/integration/test_output.py
@@ -1,6 +1,7 @@
"""This module is a testing case for the output module.
-Note: Most of the tests in this case do not currently test the output against an expected output. Instead,
+Note: Most of the tests in this case do not currently test the output against an
+expected output. Instead,
they test that the methods to create the output don't throw any errors.
This module contains the following classes:
@@ -48,8 +49,7 @@ def setUp(self):
# Set up the constructing fixtures.
self.unsteady_solver = (
- solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_static_geometry()
- )
+ solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_static_geometry())
def tearDown(self):
"""This method is automatically called before each testing method to tear down the fixtures.
@@ -68,9 +68,8 @@ def test_plot_results_versus_time_does_not_throw(self):
# Call the plot_results_versus_time method on the solver fixture. The show flag is set to False,
# so the figures will not be displayed.
- ps.output.plot_results_versus_time(
- unsteady_solver=self.unsteady_solver, show=False
- )
+ ps.output.plot_results_versus_time(unsteady_solver=self.unsteady_solver,
+ show=False)
def test_animate_does_not_throw(self):
"""This method tests that the animate method does not throw any errors.
@@ -79,12 +78,8 @@ def test_animate_does_not_throw(self):
"""
# Call the animate function on the unsteady solver fixture.
- ps.output.animate(
- unsteady_solver=self.unsteady_solver,
- scalar_type=None,
- show_wake_vortices=False,
- save=False,
- )
+ ps.output.animate(unsteady_solver=self.unsteady_solver, scalar_type=None,
+ show_wake_vortices=False, save=False, )
def test_draw_does_not_throw(self):
"""This method tests that the draw method does not throw any errors.
@@ -93,9 +88,5 @@ def test_draw_does_not_throw(self):
"""
# Call the draw function on the unsteady solver fixture.
- ps.output.draw(
- solver=self.unsteady_solver,
- scalar_type=None,
- show_wake_vortices=False,
- show_streamlines=False,
- )
+ ps.output.draw(solver=self.unsteady_solver, scalar_type=None,
+ show_wake_vortices=False, show_streamlines=False, )
diff --git a/tests/integration/test_steady_convergence.py b/tests/integration/test_steady_convergence.py
index 36e52448..d61a6533 100644
--- a/tests/integration/test_steady_convergence.py
+++ b/tests/integration/test_steady_convergence.py
@@ -45,8 +45,7 @@ def setUp(self):
# Create the steady problem.
self.steady_validation_problem = (
- problem_fixtures.make_steady_validation_problem()
- )
+ problem_fixtures.make_steady_validation_problem())
def tearDown(self):
"""This method tears down the test.
@@ -66,10 +65,8 @@ def test_steady_horseshoe_convergence(self):
converged_parameters = ps.convergence.analyze_steady_convergence(
ref_problem=self.steady_validation_problem,
solver_type="steady horseshoe vortex lattice method",
- panel_aspect_ratio_bounds=(4, 1),
- num_chordwise_panels_bounds=(3, 10),
- convergence_criteria=1.0,
- )
+ panel_aspect_ratio_bounds=(4, 1), num_chordwise_panels_bounds=(3, 10),
+ convergence_criteria=1.0, )
converged_panel_ar = converged_parameters[0]
converged_num_chordwise = converged_parameters[1]
@@ -90,10 +87,8 @@ def test_steady_ring_convergence(self):
converged_parameters = ps.convergence.analyze_steady_convergence(
ref_problem=self.steady_validation_problem,
solver_type="steady ring vortex lattice method",
- panel_aspect_ratio_bounds=(4, 1),
- num_chordwise_panels_bounds=(3, 10),
- convergence_criteria=1.0,
- )
+ panel_aspect_ratio_bounds=(4, 1), num_chordwise_panels_bounds=(3, 10),
+ convergence_criteria=1.0, )
converged_panel_ar = converged_parameters[0]
converged_num_chordwise = converged_parameters[1]
diff --git a/tests/integration/test_steady_horseshoe_vortex_lattice_method.py b/tests/integration/test_steady_horseshoe_vortex_lattice_method.py
index 8bda01df..8059b203 100644
--- a/tests/integration/test_steady_horseshoe_vortex_lattice_method.py
+++ b/tests/integration/test_steady_horseshoe_vortex_lattice_method.py
@@ -60,11 +60,9 @@ def setUp(self):
# Create the steady method solvers.
self.steady_horseshoe_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_steady_horseshoe_vortex_lattice_method_validation_solver()
- )
+ solver_fixtures.make_steady_horseshoe_vortex_lattice_method_validation_solver())
self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver()
- )
+ solver_fixtures.make_steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver())
def tearDown(self):
"""This method tears down the test.
@@ -87,25 +85,19 @@ def test_method(self):
c_di_expected = 0.019
c_di_calculated = (
self.steady_horseshoe_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_force_coefficients_wind_axes[0]
- )
+ 0].total_near_field_force_coefficients_wind_axes[0])
c_di_error = abs(c_di_calculated - c_di_expected) / c_di_expected
c_l_expected = 0.790
c_l_calculated = (
self.steady_horseshoe_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_force_coefficients_wind_axes[2]
- )
+ 0].total_near_field_force_coefficients_wind_axes[2])
c_l_error = abs(c_l_calculated - c_l_expected) / c_l_expected
c_m_expected = -0.690
c_m_calculated = (
self.steady_horseshoe_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_moment_coefficients_wind_axes[1]
- )
+ 0].total_near_field_moment_coefficients_wind_axes[1])
c_m_error = abs(c_m_calculated - c_m_expected) / c_m_expected
# Set the allowable percent error.
@@ -113,10 +105,7 @@ def test_method(self):
ps.output.draw(
solver=self.steady_horseshoe_vortex_lattice_method_validation_solver,
- show_wake_vortices=False,
- show_streamlines=True,
- scalar_type="side force",
- )
+ show_wake_vortices=False, show_streamlines=True, scalar_type="side force", )
# Assert that the percent errors are less than the allowable error.
self.assertTrue(abs(c_di_error) < allowable_error)
@@ -130,31 +119,26 @@ def test_method_multiple_wings(self):
"""
# Run the solver.
- self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.run()
+ (self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver
+ .run())
# Calculate the percent errors of the output.
c_di_expected = 0.007
- c_di_calculated = self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_force_coefficients_wind_axes[
- 0
- ]
+ c_di_calculated = \
+ self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.airplanes[
+ 0].total_near_field_force_coefficients_wind_axes[0]
c_di_error = abs(c_di_calculated - c_di_expected) / c_di_expected
c_l_expected = 0.524
- c_l_calculated = self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_force_coefficients_wind_axes[
- 2
- ]
+ c_l_calculated = \
+ self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.airplanes[
+ 0].total_near_field_force_coefficients_wind_axes[2]
c_l_error = abs(c_l_calculated - c_l_expected) / c_l_expected
c_m_expected = -0.350
- c_m_calculated = self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_moment_coefficients_wind_axes[
- 1
- ]
+ c_m_calculated = \
+ self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver.airplanes[
+ 0].total_near_field_moment_coefficients_wind_axes[1]
c_m_error = abs(c_m_calculated - c_m_expected) / c_m_expected
# Set the allowable percent error.
@@ -162,10 +146,8 @@ def test_method_multiple_wings(self):
ps.output.draw(
solver=self.steady_multiple_wing_horseshoe_vortex_lattice_method_validation_solver,
- scalar_type="induced drag",
- show_streamlines=True,
- show_wake_vortices=False,
- )
+ scalar_type="induced drag", show_streamlines=True,
+ show_wake_vortices=False, )
# Assert that the percent errors are less than the allowable error.
self.assertTrue(abs(c_di_error) < allowable_error)
diff --git a/tests/integration/test_steady_ring_vortex_lattice_method.py b/tests/integration/test_steady_ring_vortex_lattice_method.py
index be7c5719..24b5b8a5 100644
--- a/tests/integration/test_steady_ring_vortex_lattice_method.py
+++ b/tests/integration/test_steady_ring_vortex_lattice_method.py
@@ -50,8 +50,7 @@ def setUp(self):
# Create the steady method solver.
self.steady_ring_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_steady_ring_vortex_lattice_method_validation_solver()
- )
+ solver_fixtures.make_steady_ring_vortex_lattice_method_validation_solver())
def tearDown(self):
"""This method tears down the test.
@@ -74,36 +73,26 @@ def test_method(self):
c_di_expected = 0.019
c_di_calculated = (
self.steady_ring_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_force_coefficients_wind_axes[0]
- )
+ 0].total_near_field_force_coefficients_wind_axes[0])
c_di_error = abs(c_di_calculated - c_di_expected) / c_di_expected
c_l_expected = 0.788
c_l_calculated = (
self.steady_ring_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_force_coefficients_wind_axes[2]
- )
+ 0].total_near_field_force_coefficients_wind_axes[2])
c_l_error = abs(c_l_calculated - c_l_expected) / c_l_expected
c_m_expected = -0.687
c_m_calculated = (
self.steady_ring_vortex_lattice_method_validation_solver.airplanes[
- 0
- ].total_near_field_moment_coefficients_wind_axes[1]
- )
+ 0].total_near_field_moment_coefficients_wind_axes[1])
c_m_error = abs(c_m_calculated - c_m_expected) / c_m_expected
# Set the allowable percent error.
allowable_error = 0.10
- ps.output.draw(
- solver=self.steady_ring_vortex_lattice_method_validation_solver,
- show_wake_vortices=False,
- show_streamlines=True,
- scalar_type="lift",
- )
+ ps.output.draw(solver=self.steady_ring_vortex_lattice_method_validation_solver,
+ show_wake_vortices=False, show_streamlines=True, scalar_type="lift", )
# Assert that the percent errors are less than the allowable error.
self.assertTrue(abs(c_di_error) < allowable_error)
diff --git a/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry.py b/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry.py
index bc3a34fc..a5dc6051 100644
--- a/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry.py
+++ b/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_static_geometry.py
@@ -1,4 +1,5 @@
-"""This is a testing case for the unsteady ring vortex lattice method solver with static, multi-wing geometry.
+"""This is a testing case for the unsteady ring vortex lattice method solver with
+static, multi-wing geometry.
Note: This case does not currently test the solver's output against an expected output. Instead, it just tests that
the solver doesn't throw an error.
@@ -47,8 +48,7 @@ def setUp(self):
# Create the unsteady method solver.
self.unsteady_ring_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_multiple_wing_static_geometry()
- )
+ solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_multiple_wing_static_geometry())
def tearDown(self):
"""This method tears down the test.
@@ -66,12 +66,8 @@ def test_method_does_not_throw(self):
# Run the solver.
self.unsteady_ring_vortex_lattice_method_validation_solver.run(
- prescribed_wake=True,
- )
+ prescribed_wake=True, )
ps.output.animate(
unsteady_solver=self.unsteady_ring_vortex_lattice_method_validation_solver,
- show_wake_vortices=True,
- scalar_type="side force",
- save=False,
- )
+ show_wake_vortices=True, scalar_type="side force", save=False, )
diff --git a/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry.py b/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry.py
index adb26df9..3d89f3e0 100644
--- a/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry.py
+++ b/tests/integration/test_unsteady_ring_vortex_lattice_method_multiple_wing_variable_geometry.py
@@ -1,4 +1,5 @@
-"""This is a testing case for the unsteady ring vortex lattice method solver with variable, multi-wing geometry.
+"""This is a testing case for the unsteady ring vortex lattice method solver with
+variable, multi-wing geometry.
Note: This case does not currently test the solver's output against an expected output. Instead, it just tests that
the solver doesn't throw an error.
@@ -22,8 +23,7 @@
class TestUnsteadyRingVortexLatticeMethodMultipleWingVariableGeometry(
- unittest.TestCase
-):
+ unittest.TestCase):
"""This is a class for testing the unsteady ring vortex lattice method solver on
multi-wing, variable geometry.
@@ -50,8 +50,7 @@ def setUp(self):
# Create the unsteady method solver.
self.unsteady_ring_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_multiple_wing_variable_geometry()
- )
+ solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_multiple_wing_variable_geometry())
def tearDown(self):
"""This method tears down the test.
@@ -69,12 +68,8 @@ def test_method_does_not_throw(self):
# Run the solver.
self.unsteady_ring_vortex_lattice_method_validation_solver.run(
- prescribed_wake=True,
- )
+ prescribed_wake=True, )
ps.output.animate(
unsteady_solver=self.unsteady_ring_vortex_lattice_method_validation_solver,
- scalar_type="induced drag",
- show_wake_vortices=True,
- save=False,
- )
+ scalar_type="induced drag", show_wake_vortices=True, save=False, )
diff --git a/tests/integration/test_unsteady_ring_vortex_lattice_method_static_geometry.py b/tests/integration/test_unsteady_ring_vortex_lattice_method_static_geometry.py
index 272959cc..9267877f 100644
--- a/tests/integration/test_unsteady_ring_vortex_lattice_method_static_geometry.py
+++ b/tests/integration/test_unsteady_ring_vortex_lattice_method_static_geometry.py
@@ -6,7 +6,8 @@
CDi: 0.011
Cm: -0.197
-Note: The expected output was created using XFLR5's inviscid VLM2 analysis type, which is a ring vortex lattice
+Note: The expected output was created using XFLR5's inviscid VLM2 analysis type,
+which is a ring vortex lattice
method solver. The geometry in this case is static. Therefore, the results of this unsteady solver should converge to
be close to XFLR5's static result.
@@ -53,8 +54,7 @@ def setUp(self):
# Create the unsteady method solver.
self.unsteady_ring_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_static_geometry()
- )
+ solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_static_geometry())
def tearDown(self):
"""This method tears down the test.
@@ -72,8 +72,7 @@ def test_method(self):
# Run the solver.
self.unsteady_ring_vortex_lattice_method_validation_solver.run(
- prescribed_wake=True
- )
+ prescribed_wake=True)
this_solver = self.unsteady_ring_vortex_lattice_method_validation_solver
this_airplane = this_solver.current_airplanes[0]
@@ -96,16 +95,11 @@ def test_method(self):
ps.output.animate(
unsteady_solver=self.unsteady_ring_vortex_lattice_method_validation_solver,
- show_wake_vortices=True,
- scalar_type="lift",
- save=False,
- )
+ show_wake_vortices=True, scalar_type="lift", save=False, )
ps.output.plot_results_versus_time(
unsteady_solver=self.unsteady_ring_vortex_lattice_method_validation_solver,
- show=False,
- save=False,
- )
+ show=False, save=False, )
# Assert that the percent errors are less than the allowable error.
self.assertTrue(abs(c_di_error) < allowable_error)
diff --git a/tests/integration/test_unsteady_ring_vortex_lattice_method_variable_geometry.py b/tests/integration/test_unsteady_ring_vortex_lattice_method_variable_geometry.py
index 371962a1..09ae41b7 100644
--- a/tests/integration/test_unsteady_ring_vortex_lattice_method_variable_geometry.py
+++ b/tests/integration/test_unsteady_ring_vortex_lattice_method_variable_geometry.py
@@ -1,4 +1,5 @@
-"""This is a testing case for the unsteady ring vortex lattice method solver with variable geometry.
+"""This is a testing case for the unsteady ring vortex lattice method solver with
+variable geometry.
Note: This case does not currently test the solver's output against an expected output. Instead, it just tests that
the solver doesn't throw an error.
@@ -47,8 +48,7 @@ def setUp(self):
# Create the unsteady method solver.
self.unsteady_ring_vortex_lattice_method_validation_solver = (
- solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_variable_geometry()
- )
+ solver_fixtures.make_unsteady_ring_vortex_lattice_method_validation_solver_with_variable_geometry())
def tearDown(self):
"""This method tears down the test.
@@ -65,18 +65,12 @@ def test_method_does_not_throw(self):
"""
# Run the unsteady solver.
self.unsteady_ring_vortex_lattice_method_validation_solver.run(
- prescribed_wake=True,
- )
+ prescribed_wake=True, )
ps.output.animate(
unsteady_solver=self.unsteady_ring_vortex_lattice_method_validation_solver,
- scalar_type="lift",
- show_wake_vortices=True,
- save=False,
- )
+ scalar_type="lift", show_wake_vortices=True, save=False, )
ps.output.plot_results_versus_time(
unsteady_solver=self.unsteady_ring_vortex_lattice_method_validation_solver,
- show=False,
- save=False,
- )
+ show=False, save=False, )
diff --git a/tests/unit/fixtures/vortex_fixtures.py b/tests/unit/fixtures/vortex_fixtures.py
index 364fa625..f37970ce 100644
--- a/tests/unit/fixtures/vortex_fixtures.py
+++ b/tests/unit/fixtures/vortex_fixtures.py
@@ -90,11 +90,8 @@ def make_line_vortex_fixture():
strength_fixture = make_strength_fixture()
# Create the line vortex object.
- line_vortex_fixture = ps.aerodynamics.LineVortex(
- origin=origin_fixture,
- termination=termination_fixture,
- strength=strength_fixture,
- )
+ line_vortex_fixture = ps.aerodynamics.LineVortex(origin=origin_fixture,
+ termination=termination_fixture, strength=strength_fixture, )
# Delete the constructing fixtures.
del origin_fixture
@@ -142,12 +139,10 @@ def make_horseshoe_vortex_fixture():
# Create the horseshoe vortex object.
horseshoe_vortex_fixture = ps.aerodynamics.HorseshoeVortex(
- finite_leg_origin=origin_fixture,
- finite_leg_termination=termination_fixture,
+ finite_leg_origin=origin_fixture, finite_leg_termination=termination_fixture,
strength=strength_fixture,
infinite_leg_direction=infinite_leg_direction_fixture,
- infinite_leg_length=infinite_leg_length_fixture,
- )
+ infinite_leg_length=infinite_leg_length_fixture, )
# Delete the constructing fixtures.
del origin_fixture
@@ -222,9 +217,7 @@ def make_ring_vortex_fixture():
front_left_vertex=front_left_vertex_fixture,
front_right_vertex=front_right_vertex_fixture,
back_left_vertex=back_left_vertex_fixture,
- back_right_vertex=back_right_vertex_fixture,
- strength=strength_fixture,
- )
+ back_right_vertex=back_right_vertex_fixture, strength=strength_fixture, )
# Delete the constructing fixtures.
del front_left_vertex_fixture
diff --git a/tests/unit/test_horseshoe_vortex.py b/tests/unit/test_horseshoe_vortex.py
index 97404454..1feb747d 100644
--- a/tests/unit/test_horseshoe_vortex.py
+++ b/tests/unit/test_horseshoe_vortex.py
@@ -49,21 +49,16 @@ def setUp(self):
# Get the constructing fixtures.
self.horseshoe_vortex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_horseshoe_vortex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_horseshoe_vortex_fixture())
self.origin_fixture = tests.unit.fixtures.vortex_fixtures.make_origin_fixture()
self.termination_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_termination_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_termination_fixture())
self.strength_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_strength_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_strength_fixture())
self.infinite_leg_direction_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_infinite_leg_direction_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_infinite_leg_direction_fixture())
self.infinite_leg_length_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_infinite_leg_length_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_infinite_leg_length_fixture())
def tearDown(self):
"""This method is automatically called before each testing method to tear
@@ -87,68 +82,38 @@ def test_class(self):
"""
# Test that the objects are all the right type.
- self.assertIsInstance(
- self.horseshoe_vortex_fixture,
- ps.aerodynamics.HorseshoeVortex,
- )
- self.assertIsInstance(
- self.horseshoe_vortex_fixture.finite_leg,
- ps.aerodynamics.LineVortex,
- )
- self.assertIsInstance(
- self.horseshoe_vortex_fixture.left_leg,
- ps.aerodynamics.LineVortex,
- )
- self.assertIsInstance(
- self.horseshoe_vortex_fixture.right_leg,
- ps.aerodynamics.LineVortex,
- )
+ self.assertIsInstance(self.horseshoe_vortex_fixture,
+ ps.aerodynamics.HorseshoeVortex, )
+ self.assertIsInstance(self.horseshoe_vortex_fixture.finite_leg,
+ ps.aerodynamics.LineVortex, )
+ self.assertIsInstance(self.horseshoe_vortex_fixture.left_leg,
+ ps.aerodynamics.LineVortex, )
+ self.assertIsInstance(self.horseshoe_vortex_fixture.right_leg,
+ ps.aerodynamics.LineVortex, )
# Test that the vortex objects' coordinates were correctly set.
+ self.assertTrue(np.allclose(self.horseshoe_vortex_fixture.finite_leg_origin,
+ self.origin_fixture))
self.assertTrue(
- np.allclose(
- self.horseshoe_vortex_fixture.finite_leg_origin, self.origin_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.horseshoe_vortex_fixture.finite_leg_termination,
- self.termination_fixture,
- )
- )
+ np.allclose(self.horseshoe_vortex_fixture.finite_leg_termination,
+ self.termination_fixture, ))
# Test that the horseshoe vortex object's strength was set correctly.
self.assertEqual(self.horseshoe_vortex_fixture.strength, self.strength_fixture)
# Test that other class attributes were correctly set.
self.assertTrue(
- np.allclose(
- self.horseshoe_vortex_fixture.infinite_leg_direction,
- self.infinite_leg_direction_fixture,
- )
- )
- self.assertEqual(
- self.horseshoe_vortex_fixture.infinite_leg_length,
- self.infinite_leg_length_fixture,
- )
+ np.allclose(self.horseshoe_vortex_fixture.infinite_leg_direction,
+ self.infinite_leg_direction_fixture, ))
+ self.assertEqual(self.horseshoe_vortex_fixture.infinite_leg_length,
+ self.infinite_leg_length_fixture, )
# Test that the infinite legs' coordinates are correct.
- self.assertTrue(
- np.allclose(
- self.horseshoe_vortex_fixture.right_leg_origin,
- self.horseshoe_vortex_fixture.finite_leg_origin
- + self.horseshoe_vortex_fixture.infinite_leg_direction
- * self.horseshoe_vortex_fixture.infinite_leg_length,
- )
- )
- self.assertTrue(
- np.allclose(
- self.horseshoe_vortex_fixture.left_leg_termination,
- self.horseshoe_vortex_fixture.finite_leg_termination
- + self.horseshoe_vortex_fixture.infinite_leg_direction
- * self.horseshoe_vortex_fixture.infinite_leg_length,
- )
- )
+ self.assertTrue(np.allclose(self.horseshoe_vortex_fixture.right_leg_origin,
+ self.horseshoe_vortex_fixture.finite_leg_origin +
+ self.horseshoe_vortex_fixture.infinite_leg_direction * self.horseshoe_vortex_fixture.infinite_leg_length, ))
+ self.assertTrue(np.allclose(self.horseshoe_vortex_fixture.left_leg_termination,
+ self.horseshoe_vortex_fixture.finite_leg_termination + self.horseshoe_vortex_fixture.infinite_leg_direction * self.horseshoe_vortex_fixture.infinite_leg_length, ))
def test_update_strength(self):
"""This method tests the update_strength method.
@@ -165,15 +130,12 @@ def test_update_strength(self):
# Test that all the strength's have been updated correctly.
self.assertEqual(self.horseshoe_vortex_fixture.strength, new_strength_fixture)
- self.assertEqual(
- self.horseshoe_vortex_fixture.right_leg.strength, new_strength_fixture
- )
- self.assertEqual(
- self.horseshoe_vortex_fixture.finite_leg.strength, new_strength_fixture
- )
- self.assertEqual(
- self.horseshoe_vortex_fixture.left_leg.strength, new_strength_fixture
- )
+ self.assertEqual(self.horseshoe_vortex_fixture.right_leg.strength,
+ new_strength_fixture)
+ self.assertEqual(self.horseshoe_vortex_fixture.finite_leg.strength,
+ new_strength_fixture)
+ self.assertEqual(self.horseshoe_vortex_fixture.left_leg.strength,
+ new_strength_fixture)
# Revert the change.
self.horseshoe_vortex_fixture.update_strength(strength=old_strength_fixture)
diff --git a/tests/unit/test_line_vortex.py b/tests/unit/test_line_vortex.py
index 3e663e40..39883cb9 100644
--- a/tests/unit/test_line_vortex.py
+++ b/tests/unit/test_line_vortex.py
@@ -46,15 +46,12 @@ def setUp(self):
# Create the constructing fixtures.
self.line_vortex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_line_vortex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_line_vortex_fixture())
self.origin_fixture = tests.unit.fixtures.vortex_fixtures.make_origin_fixture()
self.termination_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_termination_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_termination_fixture())
self.strength_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_strength_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_strength_fixture())
def tearDown(self):
"""This method is automatically called before each testing method to tear
@@ -80,19 +77,15 @@ def test_class(self):
# Test that the vortex's coordinates were correctly set.
self.assertTrue(
- np.allclose(self.line_vortex_fixture.origin, self.origin_fixture)
- )
+ np.allclose(self.line_vortex_fixture.origin, self.origin_fixture))
self.assertTrue(
- np.allclose(self.line_vortex_fixture.termination, self.termination_fixture)
- )
+ np.allclose(self.line_vortex_fixture.termination, self.termination_fixture))
# Test that the vortex's strength was correctly set.
self.assertEqual(self.line_vortex_fixture.strength, self.strength_fixture)
# Test that the vortex's center and vector were correctly calculated.
self.assertTrue(
- np.allclose(self.line_vortex_fixture.center, np.array([0.5, 0.5, 0.5]))
- )
+ np.allclose(self.line_vortex_fixture.center, np.array([0.5, 0.5, 0.5])))
self.assertTrue(
- np.allclose(self.line_vortex_fixture.vector, np.array([1, 1, 1]))
- )
+ np.allclose(self.line_vortex_fixture.vector, np.array([1, 1, 1])))
diff --git a/tests/unit/test_ring_vortex.py b/tests/unit/test_ring_vortex.py
index 84a0f1ba..1296fb03 100644
--- a/tests/unit/test_ring_vortex.py
+++ b/tests/unit/test_ring_vortex.py
@@ -50,23 +50,17 @@ def setUp(self):
# Set up the constructing fixtures.
self.ring_vortex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_ring_vortex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_ring_vortex_fixture())
self.strength_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_strength_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_strength_fixture())
self.front_left_vertex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_front_left_vertex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_front_left_vertex_fixture())
self.front_right_vertex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_front_right_vertex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_front_right_vertex_fixture())
self.back_left_vertex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_back_left_vertex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_back_left_vertex_fixture())
self.back_right_vertex_fixture = (
- tests.unit.fixtures.vortex_fixtures.make_back_right_vertex_fixture()
- )
+ tests.unit.fixtures.vortex_fixtures.make_back_right_vertex_fixture())
def tearDown(self):
"""This method is automatically called before each testing method to tear
@@ -91,83 +85,43 @@ def test_class(self):
# Test that the objects are all the right type.
self.assertIsInstance(self.ring_vortex_fixture, ps.aerodynamics.RingVortex)
- self.assertIsInstance(
- self.ring_vortex_fixture.front_leg,
- ps.aerodynamics.LineVortex,
- )
- self.assertIsInstance(
- self.ring_vortex_fixture.left_leg, ps.aerodynamics.LineVortex
- )
- self.assertIsInstance(
- self.ring_vortex_fixture.back_leg, ps.aerodynamics.LineVortex
- )
- self.assertIsInstance(
- self.ring_vortex_fixture.right_leg,
- ps.aerodynamics.LineVortex,
- )
+ self.assertIsInstance(self.ring_vortex_fixture.front_leg,
+ ps.aerodynamics.LineVortex, )
+ self.assertIsInstance(self.ring_vortex_fixture.left_leg,
+ ps.aerodynamics.LineVortex)
+ self.assertIsInstance(self.ring_vortex_fixture.back_leg,
+ ps.aerodynamics.LineVortex)
+ self.assertIsInstance(self.ring_vortex_fixture.right_leg,
+ ps.aerodynamics.LineVortex, )
# Test that the vortex objects' coordinates were correctly set.
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.front_leg.origin,
- self.front_right_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.front_leg.termination,
- self.front_left_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.left_leg.origin, self.front_left_vertex_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.left_leg.termination,
- self.back_left_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.back_leg.origin, self.back_left_vertex_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.back_leg.termination,
- self.back_right_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.right_leg.origin,
- self.back_right_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.right_leg.termination,
- self.front_right_vertex_fixture,
- )
- )
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.front_leg.origin,
+ self.front_right_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.front_leg.termination,
+ self.front_left_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.left_leg.origin,
+ self.front_left_vertex_fixture))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.left_leg.termination,
+ self.back_left_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.back_leg.origin,
+ self.back_left_vertex_fixture))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.back_leg.termination,
+ self.back_right_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.right_leg.origin,
+ self.back_right_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.right_leg.termination,
+ self.front_right_vertex_fixture, ))
# Test that the vortex objects' strengths were correctly set.
self.assertEqual(self.ring_vortex_fixture.strength, self.strength_fixture)
- self.assertEqual(
- self.ring_vortex_fixture.front_leg.strength, self.strength_fixture
- )
- self.assertEqual(
- self.ring_vortex_fixture.left_leg.strength, self.strength_fixture
- )
- self.assertEqual(
- self.ring_vortex_fixture.back_leg.strength, self.strength_fixture
- )
- self.assertEqual(
- self.ring_vortex_fixture.right_leg.strength, self.strength_fixture
- )
+ self.assertEqual(self.ring_vortex_fixture.front_leg.strength,
+ self.strength_fixture)
+ self.assertEqual(self.ring_vortex_fixture.left_leg.strength,
+ self.strength_fixture)
+ self.assertEqual(self.ring_vortex_fixture.back_leg.strength,
+ self.strength_fixture)
+ self.assertEqual(self.ring_vortex_fixture.right_leg.strength,
+ self.strength_fixture)
def test_update_strength(self):
"""This method tests the update_strength method.
@@ -184,18 +138,14 @@ def test_update_strength(self):
# Test that all the strength's have been updated correctly.
self.assertEqual(self.ring_vortex_fixture.strength, new_strength_fixture)
- self.assertEqual(
- self.ring_vortex_fixture.front_leg.strength, new_strength_fixture
- )
- self.assertEqual(
- self.ring_vortex_fixture.left_leg.strength, new_strength_fixture
- )
- self.assertEqual(
- self.ring_vortex_fixture.back_leg.strength, new_strength_fixture
- )
- self.assertEqual(
- self.ring_vortex_fixture.right_leg.strength, new_strength_fixture
- )
+ self.assertEqual(self.ring_vortex_fixture.front_leg.strength,
+ new_strength_fixture)
+ self.assertEqual(self.ring_vortex_fixture.left_leg.strength,
+ new_strength_fixture)
+ self.assertEqual(self.ring_vortex_fixture.back_leg.strength,
+ new_strength_fixture)
+ self.assertEqual(self.ring_vortex_fixture.right_leg.strength,
+ new_strength_fixture)
# Revert the change.
self.ring_vortex_fixture.update_strength(strength=old_strength_fixture)
@@ -215,102 +165,52 @@ def test_update_position(self):
# Create fixtures to hold the soon-to-be new values of the ring vortex's
# position.
new_front_right_vertex_fixture = old_front_right_vertex_fixture + np.array(
- [1, 0, 0]
- )
+ [1, 0, 0])
new_front_left_vertex_fixture = old_front_left_vertex_fixture + np.array(
- [1, 0, 0]
- )
+ [1, 0, 0])
new_back_left_vertex_fixture = old_back_left_vertex_fixture + np.array(
- [1, 0, 0]
- )
+ [1, 0, 0])
new_back_right_vertex_fixture = old_back_right_vertex_fixture + np.array(
- [1, 0, 0]
- )
+ [1, 0, 0])
# Update the ring vortex fixture's position.
self.ring_vortex_fixture.update_position(
front_right_vertex=new_front_right_vertex_fixture,
front_left_vertex=new_front_left_vertex_fixture,
back_left_vertex=new_back_left_vertex_fixture,
- back_right_vertex=new_back_right_vertex_fixture,
- )
+ back_right_vertex=new_back_right_vertex_fixture, )
# Test that the position of the ring vortex was correctly updated.
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.front_right_vertex,
- new_front_right_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.front_left_vertex,
- new_front_left_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.back_left_vertex, new_back_left_vertex_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.back_right_vertex,
- new_back_right_vertex_fixture,
- )
- )
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.front_right_vertex,
+ new_front_right_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.front_left_vertex,
+ new_front_left_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.back_left_vertex,
+ new_back_left_vertex_fixture))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.back_right_vertex,
+ new_back_right_vertex_fixture, ))
# Check that the positions of the child objects have been correctly updated.
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.front_leg.origin,
- new_front_right_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.front_leg.termination,
- new_front_left_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.left_leg.origin, new_front_left_vertex_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.left_leg.termination,
- new_back_left_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.back_leg.origin, new_back_left_vertex_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.back_leg.termination,
- new_back_right_vertex_fixture,
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.right_leg.origin, new_back_right_vertex_fixture
- )
- )
- self.assertTrue(
- np.allclose(
- self.ring_vortex_fixture.right_leg.termination,
- new_front_right_vertex_fixture,
- )
- )
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.front_leg.origin,
+ new_front_right_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.front_leg.termination,
+ new_front_left_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.left_leg.origin,
+ new_front_left_vertex_fixture))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.left_leg.termination,
+ new_back_left_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.back_leg.origin,
+ new_back_left_vertex_fixture))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.back_leg.termination,
+ new_back_right_vertex_fixture, ))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.right_leg.origin,
+ new_back_right_vertex_fixture))
+ self.assertTrue(np.allclose(self.ring_vortex_fixture.right_leg.termination,
+ new_front_right_vertex_fixture, ))
# Revert the changes.
self.ring_vortex_fixture.update_position(
front_right_vertex=old_front_right_vertex_fixture,
front_left_vertex=old_front_left_vertex_fixture,
back_left_vertex=old_back_left_vertex_fixture,
- back_right_vertex=old_back_right_vertex_fixture,
- )
+ back_right_vertex=old_back_right_vertex_fixture, )