Simulation of High Aspect Ratio planes in Python [SHARPy]

https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fraw.githubusercontent.com%2FImperialCollegeLondon%2Fsharpy%2Fmaster%2F.version.json https://codecov.io/gh/ImperialCollegeLondon/sharpy/branch/master/graph/badge.svg https://img.shields.io/badge/License-BSD%203--Clause-blue.svg https://readthedocs.org/projects/ic-sharpy/badge/?version=master https://joss.theoj.org/papers/f7ccd562160f1a54f64a81e90f5d9af9/status.svg https://zenodo.org/badge/DOI/10.5281/zenodo.3531965.svg

Welcome to SHARPy (Simulation of High Aspect Ratio aeroplanes in Python)!

SHARPy is an aeroelastic analysis package currently under development at the Department of Aeronautics, Imperial College London. It can be used for the structural, aerodynamic, aeroelastic and flight dynamics analysis of flexible aircraft, flying wings and wind turbines. Amongst other capabilities, it offers the following solutions to the user:

  • Static aerodynamic, structural and aeroelastic solutions

  • Finding trim conditions for aeroelastic configurations

  • Nonlinear, dynamic time domain simulations under a large number of conditions such as:

    • Prescribed trajectories.
    • Free flight.
    • Dynamic follower forces.
    • Control inputs in thrust, control surface deflection…
    • Arbitrary time-domain gusts, including non span-constant ones.
    • Full 3D turbulent fields.
  • Multibody dynamics with hinges, articulations and prescribed nodal motions.

    • Applicable to wind turbines.
    • Hinged aircraft.
    • Catapult assisted takeoffs.
  • Linear analysis

    • Linearisation around a nonlinear equilibrium.
    • Frequency response analysis.
    • Asymptotic stability analysis.
  • Model order reduction

    • Krylov-subspace reduction methods.
    • Balancing reduction methods.

The modular design of SHARPy allows to simulate complex aeroelastic cases involving very flexible aircraft. The structural solver supports very complex beam arrangements, while retaining geometrical nonlinearity. The UVLM solver features different wake modelling fidelities while supporting large lifting surface deformations in a native way. Detailed information on each of the solvers is presented in their respective documentation packages.

Contents

SHARPy Installation Guide

Last revision 3 February 2020

The following step by step tutorial will guide you through the installation process of SHARPy.

Requirements

Operating System Requirements

SHARPy is being developed and tested on the following operating systems:

  • CentOS 7 and CentOS 8
  • Ubuntu 18.04 LTS
  • MacOS Mojave and Catalina

It is also available to the vast majority of operating systems that are supported by Docker, including Windows!

Required Distributions

  • Anaconda Python 3.7
  • GCC 6.0 or higher (recommended). C++ and Fortran.

Recommended Software

You may find the applications below useful, we recommend you use them but cannot provide any direct support.

  • HDFView to read and view .h5 files. HDF5 is the SHARPy input file format.
  • Paraview to visualise SHARPy’s output.

GitHub Repository

SHARPy can be installed from the source code available on GitHub or you can get it packed in a Docker container. If what you want is to give it a go and run some static or simple dynamic cases (and are familiar with Docker), we recommend the Docker route. If you want to check the code, modify it and compile the libraries with custom flags, build it from source (recommended).

Building SHARPy from source (release or development builds)

SHARPy can be built from source so that you can get the latest release or (stable) development build.

SHARPy depends on two external libraries, xbeam and UVLM. These are included as submodules to SHARPy and therefore once you initialise SHARPy you will also automatically clone the relevant versions of each library.

Set up the folder structure
  1. Clone sharpy in your desired location, if you agree with the license in license.txt

    git clone --recursive http://github.com/ImperialCollegeLondon/sharpy
    

    The --recursive flag will also initialise and update the submodules SHARPy depends on, xbeam and UVLM.

  2. We will now set up the SHARPy environment that will install other required distributions.

Setting up the Python Environment

SHARPy uses the Anaconda package manager to provide the necessary Python packages. These are specified in an Anaconda environment that shall be activated prior to compiling the xbeam and UVLM libraries or running any SHARPy cases.

  1. If you do not have it, install the Anaconda Python 3 distribution

  2. Make sure your Python version is at least 3.7:

    python --version
    
  3. Create the conda environment that SHARPy will use. Change environment_linux.yml to read environment_macos.yml file if you are installing SHARPy on Mac OS X

    cd sharpy/utils
    conda env create -f environment_linux.yml
    cd ../..
    

    We also provide a light-weight environment with the minimum required dependencies. If you’d like to use it, create the conda environment using environment_minimal.yml.

  4. Activate the sharpy_env conda environment

    conda activate sharpy_env
    

    you need to do this before you compile the xbeam and uvlm libraries, as some dependencies are included in the conda environment.

    If you would like to use the minimal environment you can run conda activate sharpy_minimal.

Quick install

The quick install is geared towards getting the release build of SHARPy running as quickly and simply as possible. If you would like to install a develop build or modify the compilation settings of the libraries skip to the next section.

  1. Move into the cloned repository

    cd sharpy
    
  2. Ensure that the SHARPy environment is active in the session. Your terminal prompt line should begin with

    (sharpy_env) [usr@host] $
    

    If it is not the case, activate the environment. Otherwise xbeam and UVLM will not compile

    conda activate sharpy_env
    
  3. Create a directory build that will be used during CMake’s building process and cd into it:

    mkdir build
    cd build
    
  4. Prepare UVLM and xbeam for compilation using gfortran and g++ in their release builds running. If you’d like to change compilers see the Custom Installation.

    cmake ..
    
  5. Compile the libraries

    make install -j 4
    

    where the number after the -j flag will specify how many cores to use during installation.

  6. Finally, load the SHARPy variables

    source bin/sharpy_vars.sh
    

You are ready to run SHARPy. Continue reading the Running SHARPy section.

Custom installation

These steps will show you how to compile the xbeam and UVLM libraries such that you can modify the compilation settings to your taste.

  1. Ensure that the SHARPy environment is loaded in your session

    conda activate sharpy_env
    
  2. If you want to use SHARPy’s latest release, skip this step. If you would like to use the latest development work, you will need to checkout the develop branch. For more info on how we structure our development and what branches are used for what kind of features have a look at the Contributing page.

    git checkout -b develop --track origin/develop
    

    This command will check out the develop branch and set it to track the remote origin.

  3. Run CMake with custom flags:

    1. Choose your compilers for Fortran FC and C++ CXX, for instance

      FC=gfortran CXX=g++ cmake ..
      

      If you’d like to use the Intel compilers you can set them using:

      FC=ifort CXX=icpc cmake ..
      
    2. To build the libraries in debug mode:

      cmake -DCMAKE_BUILD_TYPE=Debug ..
      
  4. Compile the libraries and parallelise as you prefer

    make install -j 4
    
  5. This concludes the installation! Continue reading the Running SHARPy section.

Using SHARPy from a Docker container

Docker containers are similar to lightweight virtual machines. The SHARPy container distributed through Docker Hub is a CentOS 8 machine with the libraries compiled with gfortran and g++ and an Anaconda Python distribution.

Make sure your machine has Docker working. The instructions are here: link.

You might want to run a test in your terminal:

docker pull hello-world
docker run hello-world

If this works, you’re good to go!

First, obtain the SHARPy docker container:

docker pull fonsocarre/sharpy:stable

Now you can run it:

docker run --name sharpy -it fonsocarre/sharpy:stable

You should see a welcome dialog such as:

>>>> docker run -it fonsocarre/sharpy:stable
SHARPy added to PATH from the directory: /sharpy_dir/bin
=======================================================================
Welcome to the Docker image of SHARPy
SHARPy is located in /sharpy_dir/ and the
environment is already set up!
Copyright Imperial College London. Released under BSD 3-Clause license.
=======================================================================
SHARPy> 

You are now good to go.

It is important to note that a docker container runs as an independent operating system with no access to your hard drive. If you want to copy your own files, run the container and from another terminal run:

docker cp my_file.txt sharpy:/my_file.txt     # copy from host to container
docker cp sharpy:/my_file.txt my_file.txt     # copy from container to host

The sharpy: part is the --name argument you wrote in the docker run command.

You can run the test suite once inside the container as:

cd sharpy_dir
python -m unittest

We make available two different releases: stable and experimental. The former is the latest SHARPy release. The latter is our latest development work which will include new features but with higher chances of encountering some bugs along the way. To obtain the experimental build, follow the instructions above replacing the stable tag for experimental.

Enjoy!

Running SHARPy

In order to run SHARPy, you need to load the conda environment and load the SHARPy variables (so your computer knows where SHARPy is). Therefore, before you run any SHARPy case:

  1. Activate the SHARPy conda environment

    conda activate sharpy_env
    
  2. Load the SHARPy variables

    source sharpy/bin/sharpy_vars.sh
    

You are now ready to run SHARPy cases from the terminal.

Automated tests

SHARPy uses unittests to verify the integrity of the code.

These tests can be run from the ./sharpy directory.

python -m unittest

The tests will run and you should see a success message. If you don’t… check the following options:

  • Check you are running the latest version. Running the following from the root directory should update to the latest release version:
    • git pull
    • git submodule update --init --recursive
  • If the tests don’t run, make sure you have followed correctly the instructions and that you managed to compile xbeam and UVLM.
  • If some tests fail, i.e. you get a message after the tests run saying that certain tests did not pass, please open an issue with the following information:
    • Operating system
    • Whether you did a Custom/quick install
    • UVLM and xbeam compiler of choice
    • A log of the tests that failed
The SHARPy Case Structure and input files

Setting up a SHARPy case

SHARPy cases are usually structured in the following way:

  1. A generate_case.py file: contains the setup of the problem like geometry, flight conditions etc. This script creates the output files that will then be used by SHARPy, namely:

    • The structural .fem.h5 file.
    • The aerodynamic .aero.h5 file.
    • Simulation information and settings .sharpy file.
    • The dynamic forces file .dyn.h5 (when required).
    • The linear input files .lininput.h5 (when required).
    • The ROM settings file .rom.h5 (when required).

    See the chapter on the case files for a detailed description on the contents of each one.Data is exchanged in binary format by means of .h5 files that make the transmission efficient between the different languages of the required libraries. To view these .h5 files, a viewer like HDF5 is recommended.

  2. The h5 files contain data of the FEM, aerodynamics, dynamic conditions. They are later read by SHARPy.

  3. The .sharpy file contains the settings for SHARPy and is the file that is parsed to SHARPy.

To run a SHARPy case

SHARPy cases are therefore usually ran in the following way:

  1. Create a generate_case.py file following the provided templates.

  2. Run it to produce the .h5 files and the .sharpy files.

    (sharpy_env) python generate_case.py
    
  3. Run SHARPy (ensure the environment is activated).

    (sharpy_env) sharpy case.sharpy
    
Output

By default, the output is located in the output folder.

The contents of the folder will typically be a beam and aero folders, which contain the output data that can then be loaded in Paraview. These are the .vtu format files that can be used with Paraview.

Running (and modifiying) a test case
  1. This command generates the required files for running a static, clamped beam case that is used as part of code verification:

    cd ../sharpy
    python ./tests/xbeam/geradin/generate_geradin.py
    

Now you should see a success message, and if you check the ./tests/xbeam/geradin/ folder, you should see two new files:

  • geradin_cardona.sharpy
  • geradin_cardona.fem.h5

Try to open the sharpy file with a plain text editor and have a quick look. The sharpy file is the main settings file. We’ll get deeper into this later.

If you try to open the fem.h5 file, you’ll get an error or something meaningless. This is because the structural data is stored in HDF5 format, which is compressed binary.

  1. Run it (part 1)

    The sharpy call is:

    # Make sure that the sharpy_env conda environment is active
    sharpy <path to solver file>
    
  2. Results (part 1)

    Since this is a test case, there is no output directly to screen.

    We will therefore change this setting first. In the generate_geradin.py file, look for the SHARPy setting write_screen and set it to on. This will output the progress of the execution to the terminal.

    We would also like to create a Paraview file to view the beam deformation. Append the post-processor BeamPlot to the end of the SHARPy setting flow, which is a list. This will run the post-processor and plot the beam in Paraview format with the settings specified in the generate_geradin.py file under config['BeamPlot].

  3. Run (part 2)

    Now that we have made these modifications, run again the generation script:

    python ./tests/xbeam/geradin/generate_geradin.py
    

    Check the solver file geradin.sharpy and look for the settings we just changed. Make sure they read what we wanted.

    You are now ready to run the case again:

    # Make sure that the sharpy_env conda environment is active
    sharpy <path to solver file>
    
  4. Post-processing

    After a successful execution, you should a long display of information in the terminal as the case is being executed.

    The deformed beam will have been written in a .vtu file and will be located in the output/ folder (or where you specified in the settings) which you can open using Paraview.

    In the output directory you will also note a folder named WriteVariablesTime which outputs certain variables as a function of time to a .dat file. In this case, the beam tip position deflection and rotation is written. Check the values of those files and look for the following result:

        Pos_def:
    	      4.403530 0.000000 -2.159692
        Psi_def:
    	      0.000000 0.672006 0.000000
    

    FYI, the correct solution for this test case by Geradin and Cardona is Delta R_3 = -2.159 m and Psi_2 = 0.6720 rad.

Congratulations, you’ve run your first case. You can now check the Examples section for further cases.

Capabilities

This is just the tip of the iceberg, possibilities are nearly endless and once you understand how SHARPy’s modular interface works, you will be capable of running very complex simulations.

Very flexible aircraft nonlinear aeroelasticity

The modular design of SHARPy allows to simulate complex aeroelastic cases involving very flexible aircraft. The structural solver supports very complex beam arrangements, while retaining geometrical nonlinearity. The UVLM solver features different wake modelling fidelities while supporting large lifting surface deformations in a native way.

Among the problems studied, a few interesting ones, in no particular order are:

  • Catapult take off of a very flexible aircraft analysis [Paper]. In this type of simulations, a PID controller was used in order to enforce displacements and velocities in a number of structural nodes (the clamping points). Then, several take off strategies were studied in order to analyse the influence of the structural stiffness in this kind of procedures. This case is a very good example of the type of problems where nonlinear aeroelasticity is essential.

_images/hale_cruise.pngCatapult Takeoff of Flexible Aircraft

  • Flight in full 3D atmospheric boundary layer (to be published). A very flexible aircraft is flown immersed in a turbulent boundary layer obtained from HPC LES simulations. The results are compared against simpler turbulence models such as von Karman and Kaimal. Intermittency and coherence features in the LES field are absent or less remarkable in the synthetic turbulence fields.

_images/hale_turb.jpegHALE Aircraft in a Turbulent Field

  • Lateral gust reponse of a realistic very flexible aircraft. For this problem (to be published), a realistic very flexible aircraft (University of Michigan X-HALE) model has been created in SHARPy and validated against their own aeroelastic solver for static and dynamic cases. A set of vertical and lateral gust responses have been simulated.

_images/xhale.pngX-HALE

Wind turbine aeroelasticity

SHARPy is suitable to simulate wind turbine aeroelasticity.

On the structural side, it accounts for material anisotropy which is needed to characterize composite blades and for geometrically non-linear deformations observed in current blades due to the increasing length and flexibility. Both rigid and flexible simulations can be performed and the structural modes can be computed accounting for rotational effects (Campbell diagrams). The rotor-tower interaction is modelled through a multibody approach based on the theory of Lagrange multipliers. Finally, he tower base can be fixed or subjected to prescribed linear and angular velocities.

On the aerodynamic side, the use of potential flow theory allows the characterization of flow unsteadiness at a reasonable computational cost. Specifically, steady and dynamic simulations can be performed. The steady simulations are carried out in a non-inertial frame of reference linked to the rotor under uniform steady wind with the assumption of prescribed helicoidal wake. On the other hand, dynamic simulations can be enriched with a wide variety of incoming winds such as shear and yaw. Moreover, the wake shape can be freely computed under no assumptions accounting for self-induction and wake expansion or can be prescribed to an helicoidal shape for computational efficiency.

_images/turbine.pngWind Turbine

Model Order Reduction

Numerical models of physical phenomena require fine discretisations to show convergence and agreement with their real counterparts, and, in the case of SHARPy’s aeroelastic systems, hundreds of thousands of states are not an uncommon encounter. However, modern hardware or the use of these models for other applications such as controller synthesis may limit their size, and we must turn to model order reduction techniques to achieve lower dimensional representations that can then be used.

SHARPy offers several model order reduction methods to reduce the initially large system to a lower dimension, attending to the user’s requirements of numerical efficiency or global error bound.

Krylov Methods for Model Order Reduction - Moment Matching

Model reduction by moment matching can be seen as approximating a transfer function through a power series expansion about a user defined point in the complex plane. The reduction by projection retains the moments between the full and reduced systems as long as the projection matrices span certain Krylov subspaces dependant on the expansion point and the system’s matrices. This can be taken advantage of, in particular for aeroelastic applications where the interest resides in the low frequency behaviour of the system, the ROM can be expanded about these low frequency points discarding accuracy higher up the frequency spectrum.

Example 1 - Aerodynamics - Frequency response of a high AR flat plate subject to a sinusoidal gust

The objective is to compare SHARPy’s solution of a very high aspect ratio flat plate subject to a sinusoidal gust to the closed form solution obtained by Sears (1944 - Ref). SHARPy’s inherent 3D nature makes comparing results to the 2D solution require very high aspect ratio wings with fine discretisations, resulting in very large state space models. In this case, we would like to utilise a Krylov ROM to approximate the low frequency behaviour and perform a frequency response analysis on the reduced system, since it would represent too much computational cost if it were performed on the full system.

The full order model was reduced utilising Krylov methods, in particular the Arnoldi iteration, with an expansion about zero frequency to produce the following result.

_images/sears.pngSears Gust Bode Plot

As it can be seen from the image above, the ROM approximates well the low frequency, quasi-steady state and loses accuracy as the frequency is increased, just as intended. Still, perfect matching is never achieved even at the expansion frequency given the 3D nature of the wing compared to the 2D analytical solution.

Example 2 - Aeroelastics - Flutter analysis of a Goland wing with modal projection

The Goland wing flutter example is presented next. The aerodynamic surface is finely discretised for the UVLM solution, resulting in not only a large state space but also in large input/output dimensionality. Therefore, to reduce the number of inputs and outputs, the UVLM is projected onto the structural mode shapes, the first four in this particular case. The resulting multi input multi output system (mode shapes -> UVLM -> modal forces) was subsequently reduced using Krylov methods aimed at MIMO systems which use variations of the block Arnoldi iteration. Again, the expansion frequency selected was the zero frequency. As a sample, the transfer function from two inputs to two outputs is shown to illustrate the performance of the reduced model against the full order UVLM.

_images/goland_rom.pngGoland Reduced Order Model Transfer Functions

The reduced aerodynamic model projected onto the modal shapes was then coupled to the linearised beam model, and the stability analysed against a change in velocity. Note that the UVLM model and its ROM are actually scaled to be independent on the freestream velocity, hence only one UVLM and ROM need to be computed. The structural model needs to be updated at each test velocity but its a lot less costly in computational terms. The resulting stability of the aeroelastic system is plotted on the Argand diagram below with changing freestream velocity.

_images/goland_flutter.pngGoland Flutter

Publications

SHARPy has been used in many technical papers that have been both published in Journals and presented at conferences. Here we present a list of past papers which have used SHARPy for research purposes:

2020

  • Del Carre, A., Deskos, G., & Palacios, R. (2020). Realistic turbulence effects in low altitude dynamics of very flexible aircraft. In AIAA SciTech Forum (pp. 1–18). https://doi.org/10.2514/6.2020-1187
  • Artola, M., Goizueta, N., Wynn, A., & Palacios, R. (2020). Modal-Based Nonlinear Estimation and Control for Highly Flexible Aeroelastic Systems. In AIAA SciTech Forum (pp. 1–23). https://doi.org/10.2514/6.2020-1192
  • Muñoz-Simón, A., Wynn, A., & Palacios, R. (2020). Unsteady and three-dimensional aerodynamic effects on wind turbine rotor loads. In AIAA SciTech Forum. https://doi.org/10.2514/6.2020-0991

2019

  • Carre, A., Muñoz-Simón, A., Goizueta, N., & Palacios, R. (2019). SHARPy : A dynamic aeroelastic simulation toolbox for very flexible aircraft and wind turbines. Journal of Open Source Software, 4(44), 1885. https://doi.org/10.21105/joss.01885
  • Del Carre, A., Teixeira, P. C., Palacios, R., & Cesnik, C. E. S. (2019). Nonlinear Response of a Very Flexible Aircraft Under Lateral Gust. In International Forum on Aeroelasticity and Structural Dynamics.
  • Del Carre, A., & Palacios, R. (2019). Efficient Time-Domain Simulations in Nonlinear Aeroelasticity. In AIAA Scitech Forum (pp. 1–20). https://doi.org/10.2514/6.2019-2038
  • Maraniello, S., & Palacios, R. (2019). State-Space Realizations and Internal Balancing in Potential-Flow Aerodynamics with Arbitrary Kinematics. AIAA Journal, 57(6), 1–14. https://doi.org/10.2514/1.J058153

Examples

A set of SHARPy examples created with Jupyter Notebooks is provided for users to interact and modify cases running on SHARPy.

Flutter Analysis of a Goland Wing using the SHARPy Linear Solver

This is an example using SHARPy to find the flutter speed of a Goland wing by:

  • Calculating aerodynamic forces and deflections using a nonlinear solver
  • Linearising about this reference condition
  • Creating a reduced order model of the linearised aerodynamics
  • Evaluate the stability of the linearised aeroelastic system at different velocities
References

Maraniello, S., & Palacios, R. (2019). State-Space Realizations and Internal Balancing in Potential-Flow Aerodynamics with Arbitrary Kinematics. AIAA Journal, 57(6), 1–14. https://doi.org/10.2514/1.J058153

Required Packages
[1]:
import numpy as np
import matplotlib.pyplot as plt
import os
import sys
import cases.templates.flying_wings as wings  # See this package for the Goland wing structural and aerodynamic definition
import sharpy.sharpy_main  # used to run SHARPy from Jupyter
Problem Set-up
Velocity

The UVLM is assembled in normalised time at a velocity of \(1 m/s\). The only matrices that need updating then with free stream velocity are the structural matrices, which is significantly cheaper to do than to update the UVLM.

[2]:
u_inf = 1.
alpha_deg = 0.
rho = 1.02
num_modes = 4
Discretisation

Note: To achieve convergence of the flutter results with the ones found in the literature, a significant discretisation may be required. If you are running this notebook for the first time, set M = 4 initially to verify that your system can perform!

[3]:
M = 16
N = 32
M_star_fact = 10
ROM

A moment-matching (Krylov subspace) model order reduction technique is employed. This ROM method offers the ability to interpolate the transfer functions at a desired point in the complex plane. See the ROM documentation pages for more info.

Note: this ROM method matches the transfer function but does not guarantee stability. Therefore the resulting system may be unstable. These unstable modes may appear far in the right hand plane but will not affect the flutter speed calculations.

[4]:
c_ref = 1.8288 # Goland wing reference chord. Used for frequency normalisation
rom_settings = dict()
rom_settings['algorithm'] = 'mimo_rational_arnoldi'  # reduction algorithm
rom_settings['r'] = 6  # Krylov subspace order
frequency_continuous_k = np.array([0.])  # Interpolation point in the complex plane with reduced frequency units
frequency_continuous_w = 2 * u_inf * frequency_continuous_k / c_ref
rom_settings['frequency'] = frequency_continuous_w
Case Admin
[5]:
case_name = 'goland_cs'
case_nlin_info = 'M%dN%dMs%d_nmodes%d' % (M, N, M_star_fact, num_modes)
case_rom_info = 'rom_MIMORA_r%d_sig%04d_%04dj' % (rom_settings['r'], frequency_continuous_k[-1].real * 100,
                                                  frequency_continuous_k[-1].imag * 100)

case_name += case_nlin_info + case_rom_info

route_test_dir = os.path.abspath('')

print('The case to run will be: %s' % case_name)
print('Case files will be saved in ./cases/%s' %case_name)
print('Output files will be saved in ./output/%s/' %case_name)
The case to run will be: goland_csM16N32Ms10_nmodes4rom_MIMORA_r6_sig0000_0000j
Case files will be saved in ./cases/goland_csM16N32Ms10_nmodes4rom_MIMORA_r6_sig0000_0000j
Output files will be saved in ./output/goland_csM16N32Ms10_nmodes4rom_MIMORA_r6_sig0000_0000j/
Simulation Set-Up
Goland Wing

ws is an instance of a Goland wing with a control surface. Reference the template file cases.templates.flying_wings.GolandControlSurface for more info on the geometrical, structural and aerodynamic definition of the Goland wing here used.

[6]:
ws = wings.GolandControlSurface(M=M,
                                N=N,
                                Mstar_fact=M_star_fact,
                                u_inf=u_inf,
                                alpha=alpha_deg,
                                cs_deflection=[0, 0],
                                rho=rho,
                                sweep=0,
                                physical_time=2,
                                n_surfaces=2,
                                route=route_test_dir + '/cases',
                                case_name=case_name)

ws.clean_test_files()
ws.update_derived_params()
ws.set_default_config_dict()

ws.generate_aero_file()
ws.generate_fem_file()
Surface0
Surface1
Simulation Settings

The settings for each of the solvers are now set. For a detailed description on them please reference their respective documentation pages

SHARPy Settings

The most important setting is the flow list. It tells SHARPy which solvers to run and in which order.

[7]:
ws.config['SHARPy'] = {
    'flow':
        ['BeamLoader', 'AerogridLoader',
         'StaticCoupled',
         'AerogridPlot',
         'BeamPlot',
         'Modal',
         'LinearAssembler',
         'FrequencyResponse',
         'AsymptoticStability',
         ],
    'case': ws.case_name, 'route': ws.route,
    'write_screen': 'on', 'write_log': 'on',
    'log_folder': route_test_dir + '/output/' + ws.case_name + '/',
    'log_file': ws.case_name + '.log'}
Beam Loader Settings
[8]:
ws.config['BeamLoader'] = {
    'unsteady': 'off',
    'orientation': ws.quat}
Aerogrid Loader Settings
[9]:
ws.config['AerogridLoader'] = {
    'unsteady': 'off',
    'aligned_grid': 'on',
    'mstar': ws.Mstar_fact * ws.M,
    'freestream_dir': ws.u_inf_direction
}
Static Coupled Solver
[10]:
ws.config['StaticCoupled'] = {
    'print_info': 'on',
    'max_iter': 200,
    'n_load_steps': 1,
    'tolerance': 1e-10,
    'relaxation_factor': 0.,
    'aero_solver': 'StaticUvlm',
    'aero_solver_settings': {
        'rho': ws.rho,
        'print_info': 'off',
        'horseshoe': 'off',
        'num_cores': 4,
        'n_rollup': 0,
        'rollup_dt': ws.dt,
        'rollup_aic_refresh': 1,
        'rollup_tolerance': 1e-4,
        'velocity_field_generator': 'SteadyVelocityField',
        'velocity_field_input': {
            'u_inf': ws.u_inf,
            'u_inf_direction': ws.u_inf_direction}},
    'structural_solver': 'NonLinearStatic',
    'structural_solver_settings': {'print_info': 'off',
                                   'max_iterations': 150,
                                   'num_load_steps': 4,
                                   'delta_curved': 1e-1,
                                   'min_delta': 1e-10,
                                   'gravity_on': 'on',
                                   'gravity': 9.81}}
AerogridPlot Settings
[11]:
ws.config['AerogridPlot'] = {'folder': route_test_dir + '/output/',
                             'include_rbm': 'off',
                             'include_applied_forces': 'on',
                             'minus_m_star': 0}
BeamPlot Settings
[12]:
ws.config['BeamPlot'] = {'folder': route_test_dir + '/output/',
                         'include_rbm': 'off',
                         'include_applied_forces': 'on'}
Linear System Assembly Settings
[14]:
ws.config['LinearAssembler'] = {'linear_system': 'LinearAeroelastic',
                                'linear_system_settings': {
                                    'beam_settings': {'modal_projection': 'on',
                                                      'inout_coords': 'modes',
                                                      'discrete_time': 'on',
                                                      'newmark_damp': 0.5e-4,
                                                      'discr_method': 'newmark',
                                                      'dt': ws.dt,
                                                      'proj_modes': 'undamped',
                                                      'use_euler': 'off',
                                                      'num_modes': num_modes,
                                                      'print_info': 'on',
                                                      'gravity': 'on',
                                                      'remove_sym_modes': 'on',
                                                      'remove_dofs': []},
                                    'aero_settings': {'dt': ws.dt,
                                                      'ScalingDict': {'length': 0.5 * ws.c_ref,
                                                                      'speed': u_inf,
                                                                      'density': rho},
                                                      'integr_order': 2,
                                                      'density': ws.rho,
                                                      'remove_predictor': 'on',
                                                      'use_sparse': 'on',
                                                      'rigid_body_motion': 'off',
                                                      'use_euler': 'off',
                                                      'remove_inputs': ['u_gust'],
                                                      'rom_method': ['Krylov'],
                                                      'rom_method_settings': {'Krylov': rom_settings}},
                                    'rigid_body_motion': False}}
Asymptotic Stability Analysis Settings
[15]:
ws.config['AsymptoticStability'] = {'print_info': True,
                                    'folder': route_test_dir + '/output/',
                                    'velocity_analysis': [100, 180, 81],
                                   'modes_to_plot': []}
[16]:
ws.config.write()
Run SHARPy
[17]:
sharpy.sharpy_main.main(['', ws.route + ws.case_name + '.sharpy'])
--------------------------------------------------------------------------------
            ######  ##     ##    ###    ########  ########  ##    ##
           ##    ## ##     ##   ## ##   ##     ## ##     ##  ##  ##
           ##       ##     ##  ##   ##  ##     ## ##     ##   ####
            ######  ######### ##     ## ########  ########     ##
                 ## ##     ## ######### ##   ##   ##           ##
           ##    ## ##     ## ##     ## ##    ##  ##           ##
            ######  ##     ## ##     ## ##     ## ##           ##
--------------------------------------------------------------------------------
Aeroelastics Lab, Aeronautics Department.
    Copyright (c), Imperial College London.
    All rights reserved.
    License available at https://github.com/imperialcollegelondon/sharpy
Running SHARPy from /home/ng213/code/sharpy/docs/source/content/example_notebooks
SHARPy being run is in /home/ng213/code/sharpy
The branch being run is dev_examples
The version and commit hash are: v0.1-1539-gd3ef7dd-d3ef7dd
The available solvers on this session are:
PreSharpy 
_BaseStructural 
AerogridLoader 
BeamLoader 
DynamicCoupled 
DynamicUVLM 
LinDynamicSim 
LinearAssembler 
Modal 
NoAero 
NonLinearDynamic 
NonLinearDynamicCoupledStep 
NonLinearDynamicMultibody 
NonLinearDynamicPrescribedStep 
NonLinearStatic 
NonLinearStaticMultibody 
PrescribedUvlm 
RigidDynamicPrescribedStep 
SHWUvlm 
StaticCoupled 
StaticCoupledRBM 
StaticTrim 
StaticUvlm 
StepLinearUVLM 
StepUvlm 
Trim 
Cleanup 
PickleData 
SaveData 
CreateSnapshot 
PlotFlowField 
StabilityDerivatives 
AeroForcesCalculator 
WriteVariablesTime 
AerogridPlot 
LiftDistribution 
StallCheck 
FrequencyResponse 
AsymptoticStability 
BeamPlot 
BeamLoads 
Generating an instance of BeamLoader
Generating an instance of AerogridLoader
Variable control_surface_deflection has no assigned value in the settings file.
    will default to the value: []
Variable control_surface_deflection_generator_settings has no assigned value in the settings file.
    will default to the value: []
The aerodynamic grid contains 2 surfaces
  Surface 0, M=16, N=16
     Wake 0, M=160, N=16
  Surface 1, M=16, N=16
     Wake 1, M=160, N=16
  In total: 512 bound panels
  In total: 5120 wake panels
  Total number of panels = 5632
Generating an instance of StaticCoupled
Generating an instance of NonLinearStatic
Variable newmark_damp has no assigned value in the settings file.
    will default to the value: c_double(0.0001)
Variable relaxation_factor has no assigned value in the settings file.
    will default to the value: c_double(0.3)
Variable dt has no assigned value in the settings file.
    will default to the value: c_double(0.01)
Variable num_steps has no assigned value in the settings file.
    will default to the value: c_int(500)
Variable initial_position has no assigned value in the settings file.
    will default to the value: [0. 0. 0.]
Generating an instance of StaticUvlm
Variable iterative_solver has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable iterative_tol has no assigned value in the settings file.
    will default to the value: c_double(0.0001)
Variable iterative_precond has no assigned value in the settings file.
    will default to the value: c_bool(False)



|=====|=====|============|==========|==========|==========|==========|==========|==========|
|iter |step | log10(res) |    Fx    |    Fy    |    Fz    |    Mx    |    My    |    Mz    |
|=====|=====|============|==========|==========|==========|==========|==========|==========|
|  0  |  0  |  0.00000   | -0.0000  |  0.0000  |-4271.0417|  0.0000  | 781.0842 | -0.0000  |
|  1  |  0  | -11.88931  |  0.0000  | -0.0000  |-4271.0039|  0.0000  | 781.0906 | -0.0000  |
Generating an instance of AerogridPlot
Variable include_forward_motion has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable include_unsteady_applied_forces has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable name_prefix has no assigned value in the settings file.
    will default to the value: 
Variable u_inf has no assigned value in the settings file.
    will default to the value: c_double(0.0)
Variable dt has no assigned value in the settings file.
    will default to the value: c_double(0.0)
Variable include_velocities has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable num_cores has no assigned value in the settings file.
    will default to the value: c_int(1)
...Finished
Generating an instance of BeamPlot
Variable include_FoR has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable include_applied_moments has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable name_prefix has no assigned value in the settings file.
    will default to the value: 
Variable output_rbm has no assigned value in the settings file.
    will default to the value: c_bool(True)
...Finished
Generating an instance of Modal
Variable print_info has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable delta_curved has no assigned value in the settings file.
    will default to the value: c_double(0.01)
Variable use_custom_timestep has no assigned value in the settings file.
    will default to the value: c_int(-1)
Structural eigenvalues



|==============|==============|==============|==============|==============|==============|==============|
|     mode     |  eval_real   |  eval_imag   | freq_n (Hz)  | freq_d (Hz)  |   damping    |  period (s)  |
|==============|==============|==============|==============|==============|==============|==============|
|      0       |   0.000000   |  48.067396   |   7.650164   |   7.650164   |  -0.000000   |   0.130716   |
|      1       |   0.000000   |  48.067398   |   7.650164   |   7.650164   |  -0.000000   |   0.130716   |
|      2       |   0.000000   |  95.685736   |  15.228858   |  15.228858   |  -0.000000   |   0.065665   |
|      3       |   0.000000   |  95.685754   |  15.228861   |  15.228861   |  -0.000000   |   0.065665   |
|      4       |   0.000000   |  243.144471  |  38.697644   |  38.697644   |  -0.000000   |   0.025841   |
|      5       |   0.000000   |  243.144477  |  38.697645   |  38.697645   |  -0.000000   |   0.025841   |
|      6       |   0.000000   |  343.801136  |  54.717650   |  54.717650   |  -0.000000   |   0.018276   |
|      7       |   0.000000   |  343.801137  |  54.717650   |  54.717650   |  -0.000000   |   0.018276   |
|      8       |   0.000000   |  443.324608  |  70.557303   |  70.557303   |  -0.000000   |   0.014173   |
|      9       |   0.000000   |  443.324619  |  70.557304   |  70.557304   |  -0.000000   |   0.014173   |
|      10      |   0.000000   |  461.992869  |  73.528449   |  73.528449   |  -0.000000   |   0.013600   |
|      11      |   0.000000   |  461.992869  |  73.528449   |  73.528449   |  -0.000000   |   0.013600   |
|      12      |   0.000000   |  601.126871  |  95.672313   |  95.672313   |  -0.000000   |   0.010452   |
|      13      |   0.000000   |  601.126873  |  95.672313   |  95.672313   |  -0.000000   |   0.010452   |
|      14      |   0.000000   |  782.997645  |  124.617946  |  124.617946  |  -0.000000   |   0.008025   |
|      15      |   0.000000   |  782.997649  |  124.617946  |  124.617946  |  -0.000000   |   0.008025   |
|      16      |   0.000000   |  917.191257  |  145.975522  |  145.975522  |  -0.000000   |   0.006850   |
|      17      |   0.000000   |  917.191259  |  145.975523  |  145.975523  |  -0.000000   |   0.006850   |
|      18      |   0.000000   |  975.005694  |  155.176976  |  155.176976  |  -0.000000   |   0.006444   |
|      19      |   0.000000   |  975.005699  |  155.176977  |  155.176977  |  -0.000000   |   0.006444   |
Generating an instance of LinearAssembler
Variable linearisation_tstep has no assigned value in the settings file.
    will default to the value: c_int(-1)
Generating an instance of LinearAeroelastic
Variable uvlm_filename has no assigned value in the settings file.
    will default to the value: 
Variable track_body has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable use_euler has no assigned value in the settings file.
    will default to the value: c_bool(False)
Generating an instance of LinearUVLM
Variable gust_assembler has no assigned value in the settings file.
    will default to the value: 
Initialising Static linear UVLM solver class...
/home/ng213/code/sharpy/sharpy/solvers/linearassembler.py:79: UserWarning: LinearAssembler solver under development
  warnings.warn('LinearAssembler solver under development')
                        ...done in 1.41 sec
Generating an instance of Krylov
Variable print_info has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable tangent_input_file has no assigned value in the settings file.
    will default to the value: 
Variable restart_arnoldi has no assigned value in the settings file.
    will default to the value: c_bool(False)
Initialising Krylov Model Order Reduction
State-space realisation of UVLM equations started...
/home/ng213/code/sharpy/sharpy/linear/src/assembly.py:1256: SparseEfficiencyWarning: Changing the sparsity structure of a csc_matrix is expensive. lil_matrix is more efficient.
  C[iivec, N * (M - 1) + iivec] = 1.0
/home/ng213/code/sharpy/sharpy/linear/src/assembly.py:1259: SparseEfficiencyWarning: Changing the sparsity structure of a csc_matrix is expensive. lil_matrix is more efficient.
  C_star[mm * N + iivec, (mm - 1) * N + iivec] = 1.0
state-space model produced in form:
        h_{n+1} = A h_{n} + B u_{n}
        with:
        x_n = h_n + Bp u_n
                        ...done in 19.06 sec
Scaling UVLM system with reference time 0.914400s
Non-dimensional time step set (0.125000)
System scaled in 31.559722s
Generating an instance of LinearBeam
Warning, projecting system with damping onto undamped modes

Linearising gravity terms...
     M = 7.26 kg
     X_CG A -> 0.00 -0.00 -0.00
Node  1      -> B -0.000 -0.116 0.000
                     -> A 0.116 0.381 -0.000
                     -> G 0.116 0.381 -0.000
     Node mass:
             Matrix: 14.5125
Node  2      -> B -0.000 -0.116 0.000
                     -> A 0.116 0.762 -0.000
                     -> G 0.116 0.762 -0.000
     Node mass:
             Matrix: 7.2563
Node  3      -> B -0.000 -0.116 0.000
                     -> A 0.116 1.143 -0.000
                     -> G 0.116 1.143 -0.000
     Node mass:
             Matrix: 14.5125
Node  4      -> B -0.000 -0.116 0.000
                     -> A 0.116 1.524 -0.001
                     -> G 0.116 1.524 -0.001
     Node mass:
             Matrix: 7.2563
Node  5      -> B -0.000 -0.116 0.000
                     -> A 0.116 1.905 -0.001
                     -> G 0.116 1.905 -0.001
     Node mass:
             Matrix: 14.5125
Node  6      -> B -0.000 -0.116 0.000
                     -> A 0.116 2.286 -0.001
                     -> G 0.116 2.286 -0.001
     Node mass:
             Matrix: 7.2563
Node  7      -> B -0.000 -0.116 0.000
                     -> A 0.116 2.667 -0.002
                     -> G 0.116 2.667 -0.002
     Node mass:
             Matrix: 14.5125
Node  8      -> B -0.000 -0.116 0.000
                     -> A 0.116 3.048 -0.002
                     -> G 0.116 3.048 -0.002
     Node mass:
             Matrix: 7.2563
Node  9      -> B -0.000 -0.116 0.000
                     -> A 0.116 3.429 -0.003
                     -> G 0.116 3.429 -0.003
     Node mass:
             Matrix: 14.5125
Node 10      -> B -0.000 -0.116 0.000
                     -> A 0.116 3.810 -0.003
                     -> G 0.116 3.810 -0.003
     Node mass:
             Matrix: 7.2563
Node 11      -> B -0.000 -0.116 0.000
                     -> A 0.116 4.191 -0.004
                     -> G 0.116 4.191 -0.004
     Node mass:
             Matrix: 14.5125
Node 12      -> B -0.000 -0.116 0.000
                     -> A 0.116 4.572 -0.004
                     -> G 0.116 4.572 -0.004
     Node mass:
             Matrix: 7.2563
Node 13      -> B -0.000 -0.116 0.000
                     -> A 0.116 4.953 -0.005
                     -> G 0.116 4.953 -0.005
     Node mass:
             Matrix: 14.5125
Node 14      -> B -0.000 -0.116 0.000
                     -> A 0.116 5.334 -0.005
                     -> G 0.116 5.334 -0.005
     Node mass:
             Matrix: 7.2563
Node 15      -> B -0.000 -0.116 0.000
                     -> A 0.116 5.715 -0.006
                     -> G 0.116 5.715 -0.006
     Node mass:
             Matrix: 14.5125
Node 16      -> B -0.000 -0.116 0.000
                     -> A 0.116 6.096 -0.006
                     -> G 0.116 6.096 -0.006
     Node mass:
             Matrix: 3.6281
Node 17      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -6.096 -0.006
                     -> G 0.116 -6.096 -0.006
     Node mass:
             Matrix: 3.6281
Node 18      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -5.715 -0.006
                     -> G 0.116 -5.715 -0.006
     Node mass:
             Matrix: 14.5125
Node 19      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -5.334 -0.005
                     -> G 0.116 -5.334 -0.005
     Node mass:
             Matrix: 7.2563
Node 20      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -4.953 -0.005
                     -> G 0.116 -4.953 -0.005
     Node mass:
             Matrix: 14.5125
Node 21      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -4.572 -0.004
                     -> G 0.116 -4.572 -0.004
     Node mass:
             Matrix: 7.2563
Node 22      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -4.191 -0.004
                     -> G 0.116 -4.191 -0.004
     Node mass:
             Matrix: 14.5125
Node 23      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -3.810 -0.003
                     -> G 0.116 -3.810 -0.003
     Node mass:
             Matrix: 7.2563
Node 24      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -3.429 -0.003
                     -> G 0.116 -3.429 -0.003
     Node mass:
             Matrix: 14.5125
Node 25      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -3.048 -0.002
                     -> G 0.116 -3.048 -0.002
     Node mass:
             Matrix: 7.2563
Node 26      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -2.667 -0.002
                     -> G 0.116 -2.667 -0.002
     Node mass:
             Matrix: 14.5125
Node 27      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -2.286 -0.002
                     -> G 0.116 -2.286 -0.002
     Node mass:
             Matrix: 7.2563
Node 28      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -1.905 -0.001
                     -> G 0.116 -1.905 -0.001
     Node mass:
             Matrix: 14.5125
Node 29      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -1.524 -0.001
                     -> G 0.116 -1.524 -0.001
     Node mass:
             Matrix: 7.2563
Node 30      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -1.143 -0.000
                     -> G 0.116 -1.143 -0.000
     Node mass:
             Matrix: 14.5125
Node 31      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -0.762 -0.000
                     -> G 0.116 -0.762 -0.000
     Node mass:
             Matrix: 7.2563
Node 32      -> B -0.000 -0.116 -0.000
                     -> A 0.116 -0.381 -0.000
                     -> G 0.116 -0.381 -0.000
     Node mass:
             Matrix: 14.5125
        Updated the beam C, modal C and K matrices with the terms from the
gravity linearisation

Scaling beam according to reduced time...
     Setting the beam time step to (0.1250)
Updating C and K matrices and natural frequencies with new normalised time...
Model Order Reduction in progress...
Moment Matching Krylov Model Reduction
        Construction Algorithm:
             mimo_rational_arnoldi
        Interpolation points:
        Krylov order:
             r = 6
Unstable ROM - 2 Eigenvalues with |r| > 1
        mu = -3.202177 + 0.000000j
        mu = 1.062204 + 0.000000j
System reduced from order 6656 to
     n = 36 states
...Completed Model Order Reduction in 2.51 s
Aeroelastic system assembled:
     Aerodynamic states: 36
     Structural states: 4
     Total states: 40
     Inputs: 8
     Outputs: 6
Generating an instance of FrequencyResponse
Variable load_fom has no assigned value in the settings file.
    will default to the value: 
Variable num_freqs has no assigned value in the settings file.
    will default to the value: c_int(50)
Computing frequency response...
Full order system:
/home/ng213/anaconda3/envs/sharpy_env/lib/python3.7/site-packages/scipy/sparse/compressed.py:708: SparseEfficiencyWarning: Changing the sparsity structure of a csc_matrix is expensive. lil_matrix is more efficient.
  self[i, j] = values
     Computed the frequency response of the full order system in 26.673870 s
Reduced order system:
     Computed the frequency response of the reduced order system in 0.002653 s
Computing error in frequency response
m = 0, p = 0
     Error Magnitude -real-: log10(error) = -4.85 (-0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.80 (-0.00 pct) at 1.07 rad/s
m = 0, p = 1
     Error Magnitude -real-: log10(error) = -4.93 (-0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -5.17 (0.00 pct) at 1.09 rad/s
m = 1, p = 0
     Error Magnitude -real-: log10(error) = -3.98 (0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -3.94 (0.00 pct) at 1.07 rad/s
m = 1, p = 1
     Error Magnitude -real-: log10(error) = -4.06 (0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.30 (-0.00 pct) at 1.09 rad/s
m = 2, p = 0
     Error Magnitude -real-: log10(error) = -4.28 (-0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.23 (-0.00 pct) at 1.07 rad/s
m = 2, p = 1
     Error Magnitude -real-: log10(error) = -4.35 (-0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.61 (0.00 pct) at 1.09 rad/s
m = 3, p = 0
     Error Magnitude -real-: log10(error) = -4.16 (0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.12 (0.01 pct) at 1.07 rad/s
m = 3, p = 1
     Error Magnitude -real-: log10(error) = -4.24 (-0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.48 (-0.00 pct) at 1.09 rad/s
m = 4, p = 0
     Error Magnitude -real-: log10(error) = -3.67 (0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -3.59 (0.00 pct) at 1.07 rad/s
m = 4, p = 1
     Error Magnitude -real-: log10(error) = -3.71 (0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.00 (-0.00 pct) at 0.98 rad/s
m = 5, p = 0
     Error Magnitude -real-: log10(error) = -3.83 (0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -3.75 (0.00 pct) at 1.07 rad/s
m = 5, p = 1
     Error Magnitude -real-: log10(error) = -3.87 (-0.00 pct) at 1.09 rad/s
     Error Magnitude -imag-: log10(error) = -4.16 (-0.00 pct) at 0.98 rad/s
Creating Quick plots of the frequency response
     Plots saved to ./output//goland_csM16N32Ms10_nmodes4rom_MIMORA_r6_sig0000_0000j/frequencyresponse/
Generating an instance of AsymptoticStability
Variable reference_velocity has no assigned value in the settings file.
    will default to the value: c_double(1.0)
Variable frequency_cutoff has no assigned value in the settings file.
    will default to the value: c_double(0.0)
Variable export_eigenvalues has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable display_root_locus has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable num_evals has no assigned value in the settings file.
    will default to the value: c_int(200)
Variable postprocessors has no assigned value in the settings file.
    will default to the value: []
Variable postprocessors_settings has no assigned value in the settings file.
    will default to the value: {}
Dynamical System Eigenvalues



|==============|==============|==============|==============|==============|==============|==============|
|     mode     |  eval_real   |  eval_imag   | freq_n (Hz)  | freq_d (Hz)  |   damping    |  period (s)  |
|==============|==============|==============|==============|==============|==============|==============|
|      0       |  10.182550   |  -27.485500  |   4.664997   |   4.374453   |  -0.347396   |   0.228600   |
|      1       |   0.527963   |  -0.000000   |   0.084028   |   0.000000   |   1.000000   |     inf      |
|      2       |  -0.021585   |  -24.315459  |   3.869927   |   3.869926   |   0.000888   |   0.258403   |
|      3       |  -0.021585   |  24.315459   |   3.869927   |   3.869926   |   0.000888   |   0.258403   |
|      4       |  -0.105973   |  -21.319801  |   3.393194   |   3.393152   |   0.004971   |   0.294711   |
|      5       |  -0.105973   |  21.319801   |   3.393194   |   3.393152   |   0.004971   |   0.294711   |
|      6       |  -0.253786   |   0.000000   |   0.040391   |   0.000000   |   1.000000   |     inf      |
|      7       |  -0.372465   |  -0.355725   |   0.081972   |   0.056615   |   0.723172   |  17.663059   |
|      8       |  -0.372465   |   0.355725   |   0.081972   |   0.056615   |   0.723172   |  17.663059   |
|      9       |  -0.405420   |   0.870139   |   0.152781   |   0.138487   |   0.422334   |   7.220896   |
|      10      |  -0.405420   |  -0.870139   |   0.152781   |   0.138487   |   0.422334   |   7.220896   |
|      11      |  -0.414445   |   0.000000   |   0.065961   |   0.000000   |   1.000000   |     inf      |
|      12      |  -0.433769   |  -0.705316   |   0.131784   |   0.112255   |   0.523860   |   8.908329   |
|      13      |  -0.433769   |   0.705316   |   0.131784   |   0.112255   |   0.523860   |   8.908329   |
|      14      |  -0.584818   |   0.000000   |   0.093077   |   0.000000   |   1.000000   |     inf      |
|      15      |  -0.652779   |  -0.945278   |   0.182832   |   0.150446   |   0.568242   |   6.646916   |
|      16      |  -0.652779   |   0.945278   |   0.182832   |   0.150446   |   0.568242   |   6.646916   |
|      17      |  -0.662253   |  -0.344794   |   0.118830   |   0.054876   |   0.886985   |  18.223008   |
|      18      |  -0.662253   |   0.344794   |   0.118830   |   0.054876   |   0.886985   |  18.223008   |
|      19      |  -0.689479   |  -0.611472   |   0.146671   |   0.097319   |   0.748162   |  10.275501   |
|      20      |  -0.689479   |   0.611472   |   0.146671   |   0.097319   |   0.748162   |  10.275501   |
|      21      |  -0.733120   |  -0.423757   |   0.134769   |   0.067443   |   0.865775   |  14.827328   |
|      22      |  -0.733120   |   0.423757   |   0.134769   |   0.067443   |   0.865775   |  14.827328   |
|      23      |  -0.755676   |   0.287185   |   0.128662   |   0.045707   |   0.934772   |  21.878536   |
|      24      |  -0.755676   |  -0.287185   |   0.128662   |   0.045707   |   0.934772   |  21.878536   |
|      25      |  -0.765019   |   0.043949   |   0.121957   |   0.006995   |   0.998354   |  142.964071  |
|      26      |  -0.765019   |  -0.043949   |   0.121957   |   0.006995   |   0.998354   |  142.964071  |
|      27      |  -0.768680   |   0.696822   |   0.165125   |   0.110903   |   0.740889   |   9.016920   |
|      28      |  -0.768680   |  -0.696822   |   0.165125   |   0.110903   |   0.740889   |   9.016920   |
|      29      |  -0.847888   |  -0.177523   |   0.137872   |   0.028254   |   0.978777   |  35.393580   |
|      30      |  -0.847888   |   0.177523   |   0.137872   |   0.028254   |   0.978777   |  35.393580   |
|      31      |  -2.191875   |  -0.000000   |   0.348848   |   0.000000   |   1.000000   |     inf      |
|      32      |  -3.035678   |   1.135842   |   0.515855   |   0.180775   |   0.936586   |   5.531743   |
|      33      |  -3.035678   |  -1.135842   |   0.515855   |   0.180775   |   0.936586   |   5.531743   |
|      34      |  -4.223460   |   0.000000   |   0.672185   |   0.000000   |   1.000000   |     inf      |
|      35      |  -9.070692   |  -0.000000   |   1.443645   |   0.000000   |   1.000000   |     inf      |
|      36      |  -26.578730  |  27.485500   |   6.085219   |   4.374453   |   0.695149   |   0.228600   |
|      37      |  -28.711479  |  -0.000000   |   4.569574   |   0.000000   |   1.000000   |     inf      |
|      38      |  -35.859976  |  27.485500   |   7.190899   |   4.374453   |   0.793683   |   0.228600   |
|      39      |  -36.744614  |   0.000000   |   5.848087   |   0.000000   |   1.000000   |     inf      |
Velocity Asymptotic Stability Analysis
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 100.00 m/2   max. CT eig. real: 1018.304110
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       52.80   49.09
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 101.00 m/2   max. CT eig. real: 1028.487151
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       53.32   49.15
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 102.00 m/2   max. CT eig. real: 1038.670193
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       53.85   49.21
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 103.00 m/2   max. CT eig. real: 1048.853234
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       54.38   49.27
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 104.00 m/2   max. CT eig. real: 1059.036275
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       54.91   49.34
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 105.00 m/2   max. CT eig. real: 1069.219316
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       55.44   49.40
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 106.00 m/2   max. CT eig. real: 1079.402357
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       55.96   49.47
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 107.00 m/2   max. CT eig. real: 1089.585399
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       56.49   49.54
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 108.00 m/2   max. CT eig. real: 1099.768440
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       57.02   49.60
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 109.00 m/2   max. CT eig. real: 1109.951481
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       57.55   49.68
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 110.00 m/2   max. CT eig. real: 1120.134522
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       58.08   49.75
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 111.00 m/2   max. CT eig. real: 1130.317564
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       58.60   49.82
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 112.00 m/2   max. CT eig. real: 1140.500605
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       59.13   49.90
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 113.00 m/2   max. CT eig. real: 1150.683646
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       59.66   49.97
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 114.00 m/2   max. CT eig. real: 1160.866687
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       60.19   50.05
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 115.00 m/2   max. CT eig. real: 1171.049728
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       60.72   50.13
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 116.00 m/2   max. CT eig. real: 1181.232770
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       61.24   50.22
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 117.00 m/2   max. CT eig. real: 1191.415811
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       61.77   50.30
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 118.00 m/2   max. CT eig. real: 1201.598852
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       62.30   50.39
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 119.00 m/2   max. CT eig. real: 1211.781893
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       62.83   83.07
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 120.00 m/2   max. CT eig. real: 1221.964934
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       63.36   82.86
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 121.00 m/2   max. CT eig. real: 1232.147976
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       63.88   82.64
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 122.00 m/2   max. CT eig. real: 1242.331017
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       64.41   82.42
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 123.00 m/2   max. CT eig. real: 1252.514058
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       64.94   82.19
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 124.00 m/2   max. CT eig. real: 1262.697099
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       65.47   81.96
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 125.00 m/2   max. CT eig. real: 1272.880140
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       66.00   81.73
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 126.00 m/2   max. CT eig. real: 1283.063182
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       66.52   81.50
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 127.00 m/2   max. CT eig. real: 1293.246223
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       67.05   81.26
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 128.00 m/2   max. CT eig. real: 1303.429264
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       67.58   81.01
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 129.00 m/2   max. CT eig. real: 1313.612305
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       68.11   80.77
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 130.00 m/2   max. CT eig. real: 1323.795346
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       68.64   80.51
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 131.00 m/2   max. CT eig. real: 1333.978388
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       69.16   80.26
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 132.00 m/2   max. CT eig. real: 1344.161429
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       69.69   80.00
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 133.00 m/2   max. CT eig. real: 1354.344470
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       70.22   79.74
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 134.00 m/2   max. CT eig. real: 1364.527511
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       70.75   79.47
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 135.00 m/2   max. CT eig. real: 1374.710552
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       71.28   79.20
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 136.00 m/2   max. CT eig. real: 1384.893594
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       71.80   78.92
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 137.00 m/2   max. CT eig. real: 1395.076635
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       72.33   78.64
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 138.00 m/2   max. CT eig. real: 1405.259676
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       72.86   78.36
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 139.00 m/2   max. CT eig. real: 1415.442717
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       73.39   78.07
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 140.00 m/2   max. CT eig. real: 1425.625758
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       73.91   77.77
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 141.00 m/2   max. CT eig. real: 1435.808799
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       74.44   77.48
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 142.00 m/2   max. CT eig. real: 1445.991841
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       74.97   77.18
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 143.00 m/2   max. CT eig. real: 1456.174882
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       75.50   76.87
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 144.00 m/2   max. CT eig. real: 1466.357923
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       76.03   76.57
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 145.00 m/2   max. CT eig. real: 1476.540964
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       76.55   76.25
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 146.00 m/2   max. CT eig. real: 1486.724005
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       77.08   75.94
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 147.00 m/2   max. CT eig. real: 1496.907047
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       77.61   75.62
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 148.00 m/2   max. CT eig. real: 1507.090088
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       78.14   75.31
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 149.00 m/2   max. CT eig. real: 1517.273129
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       78.67   74.99
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 150.00 m/2   max. CT eig. real: 1527.456170
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       79.19   74.67
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 151.00 m/2   max. CT eig. real: 1537.639211
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       79.72   74.35
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 152.00 m/2   max. CT eig. real: 1547.822253
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       80.25   74.03
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 153.00 m/2   max. CT eig. real: 1558.005294
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       80.78   73.71
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 154.00 m/2   max. CT eig. real: 1568.188335
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       81.31   73.40
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 155.00 m/2   max. CT eig. real: 1578.371376
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       81.83   73.09
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 156.00 m/2   max. CT eig. real: 1588.554417
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       82.36   72.78
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 157.00 m/2   max. CT eig. real: 1598.737458
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       82.89   72.49
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 158.00 m/2   max. CT eig. real: 1608.920500
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       83.42   72.19
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 159.00 m/2   max. CT eig. real: 1619.103541
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       83.95   71.91
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 160.00 m/2   max. CT eig. real: 1629.286582
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       84.47   71.64
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 161.00 m/2   max. CT eig. real: 1639.469623
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       85.00   71.37
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 162.00 m/2   max. CT eig. real: 1649.652664
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       85.53   71.12
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 163.00 m/2   max. CT eig. real: 1659.835706
        N unstab.: 002
        Unstable aeroelastic natural frequency CT(rad/s):       86.06   70.87
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 164.00 m/2   max. CT eig. real: 1670.018747
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       86.59   70.64   70.64   56.53
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 165.00 m/2   max. CT eig. real: 1680.201788
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       87.11   70.41   70.41   56.63
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 166.00 m/2   max. CT eig. real: 1690.384829
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       87.64   70.20   70.20   56.73
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 167.00 m/2   max. CT eig. real: 1700.567870
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       88.17   69.99   69.99   56.82
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 168.00 m/2   max. CT eig. real: 1710.750911
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       88.70   69.79   69.79   56.90
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 169.00 m/2   max. CT eig. real: 1720.933953
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       89.23   69.61   69.61   56.97
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 170.00 m/2   max. CT eig. real: 1731.116994
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       89.75   69.43   69.43   57.04
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 171.00 m/2   max. CT eig. real: 1741.300035
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       90.28   69.26   69.26   57.10
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 172.00 m/2   max. CT eig. real: 1751.483076
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       90.81   69.10   69.10   57.16
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 173.00 m/2   max. CT eig. real: 1761.666117
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       91.34   68.94   68.94   57.21
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 174.00 m/2   max. CT eig. real: 1771.849159
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       91.87   68.79   68.79   57.25
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 175.00 m/2   max. CT eig. real: 1782.032200
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       92.39   68.65   68.65   57.29
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 176.00 m/2   max. CT eig. real: 1792.215241
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       92.92   68.51   68.51   57.33
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 177.00 m/2   max. CT eig. real: 1802.398282
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       93.45   68.38   68.38   57.36
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 178.00 m/2   max. CT eig. real: 1812.581323
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       93.98   68.25   68.25   57.39
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 179.00 m/2   max. CT eig. real: 1822.764364
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       94.51   68.13   68.13   57.41
Updating C and K matrices and natural frequencies with new normalised time...
LTI     u: 180.00 m/2   max. CT eig. real: 1832.947406
        N unstab.: 004
        Unstable aeroelastic natural frequency CT(rad/s):       95.03   68.01   68.01   57.43
Saving velocity analysis results...
     Successful
FINISHED - Elapsed time = 87.4548716 seconds
FINISHED - CPU process time = 158.0786466 seconds
/home/ng213/code/sharpy/sharpy/postproc/asymptoticstability.py:171: UserWarning: Plotting modes is under development
  warn.warn('Plotting modes is under development')
[17]:
<sharpy.presharpy.presharpy.PreSharpy at 0x7f94ae37cf28>
Analysis
Nonlinear equilibrium

The nonlinear equilibrium condition can be visualised and analysed by opening, with Paraview, the files in the /output/<case_name>/aero and /output/<case_name>/beam folders to see the deflection and aerodynamic forces acting

Stability

The stability of the Goland wing is now analysed under changing free stream velocity. The aeroelastic system is projected onto 2 structural modes (1st bending and 1st torsion). The two modes are seen quite separated at 100 m/s. As speed is increased, the damping of the torsion mode decreases until it crosses the imaginary axis onto the right hand plane and flutter begins. This flutter mode is a bending-torsion mode, as seen from the natural frequency plot where the frequencies of each coalesce into this mode.

[18]:
file_name = './output/%s/stability/velocity_analysis_min1000_max1800_nvel0081.dat' % case_name

velocity_analysis = np.loadtxt(file_name)
u_inf = velocity_analysis[:, 0]
eigs_r = velocity_analysis[:, 1]
eigs_i = velocity_analysis[:, 2]
[19]:
fig = plt.figure()
plt.scatter(eigs_r, eigs_i, c=u_inf, cmap='Blues')
cbar = plt.colorbar()
cbar.set_label('Free Stream Velocity, $u_\infty$ [m/s]')

plt.grid()
plt.xlim(-10, 10)
plt.ylim(-150, 150)
plt.xlabel('Real Part, $\lambda$ [rad/s]')
plt.ylabel('Imag Part, $\lambda$ [rad/s]');
_images/content_example_notebooks_linear_goland_flutter_43_0.png
[20]:
fig = plt.figure()
natural_frequency = np.sqrt(eigs_r ** 2 + eigs_i ** 2)
damping_ratio = eigs_r / natural_frequency
cond = (eigs_r>-25) * (eigs_r<10) * (natural_frequency<100) # filter unwanted eigenvalues for this plot (mostly aero modes)

plt.scatter(u_inf[cond], damping_ratio[cond], color='k', marker='s', s=9)

plt.grid()
plt.ylim(-0.25, 0.25)
plt.xlabel('Free Stream Velocity, $u_\infty$ [m/s]')
plt.ylabel('Damping Ratio, $\zeta$ [-]');
_images/content_example_notebooks_linear_goland_flutter_44_0.png
[21]:
fig = plt.figure()
cond = (eigs_r>-25) * (eigs_r<10) # filter unwanted eigenvalues for this plot (mostly aero modes)
plt.scatter(u_inf[cond], natural_frequency[cond], color='k', marker='s', s=9)

plt.grid()
plt.ylim(40, 100)
plt.xlabel('Free Stream Velocity, $u_\infty$ [m/s]')
plt.ylabel('Natural Frequency, $\omega_n$ [rad/s]');
_images/content_example_notebooks_linear_goland_flutter_45_0.png
[1]:
%load_ext autoreload
%autoreload 2
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import Image

T-Tail HALE Model tutorial

The HALE T-Tail model intends to be a representative example of a typical HALE configuration, with high flexibility and aspect-ratio.

A geometry outline and a summary of the beam properties are given next

[2]:
url = 'https://raw.githubusercontent.com/ImperialCollegeLondon/sharpy/dev_doc/docs/source/content/example_notebooks/images/t-tail_geometry.png'
Image(url=url, width=800)
[2]:
[3]:
url = 'https://raw.githubusercontent.com/ImperialCollegeLondon/sharpy/dev_doc/docs/source/content/example_notebooks/images/t-tail_properties.png'
Image(url=url, width=500)
[3]:

This case is included in tests/coupled/simple_HALE/. The generate_hale.py file in that folder is the one that, if executed, generates all the required SHARPy files. This document is a step by step guide to how to process that case.

The T-Tail HALE model is subject to a 20% 1-cos spanwise constant gust.

First, let’s start with importing SHARPy in our Python environment.

[4]:
import sharpy
import sharpy.sharpy_main as sharpy_main

And now the generate_HALE.py file needs to be executed.

[5]:
route_to_case = '../../../../cases/coupled/simple_HALE/'
%run '../../../../cases/coupled/simple_HALE/generate_hale.py'

There should be 3 new files, apart from the original generate_hale.py:

[6]:
!ls ../../../../cases/coupled/simple_HALE/
generate_hale.py  simple_HALE.aero.h5  simple_HALE.fem.h5  simple_HALE.sharpy

SHARPy can be run now. In the terminal, doing cd to the simple_HALE folder, the command would look like:

sharpy simple_HALE.sharpy

From a python console with import sharpy already run, the command is:

[7]:
case_data = sharpy_main.main(['', route_to_case + 'simple_HALE.sharpy'])
/home/ad214/run/code_doc/sharpy/sharpy/aero/utils/uvlmlib.py:230: RuntimeWarning: invalid value encountered in true_divide
  flightconditions.uinf_direction = np.ctypeslib.as_ctypes(ts_info.u_ext[0][:, 0, 0]/flightconditions.uinf)
/home/ad214/run/code_doc/sharpy/sharpy/aero/utils/uvlmlib.py:347: RuntimeWarning: invalid value encountered in true_divide
  flightconditions.uinf_direction = np.ctypeslib.as_ctypes(ts_info.u_ext[0][:, 0, 0]/flightconditions.uinf)

The resulting data structure that is returned from the call to main contains all the time-dependant variables for both the structural and aerodynamic solvers.

timestep_info can be found in case_data.structure and case_data.aero. It is an array with custom-made structure to contain the data of each solver.

In the .sharpy file, we can see which solvers are run:

flow = ['BeamLoader',
        'AerogridLoader',
        'StaticTrim',
        'BeamLoads',
        'AerogridPlot',
        'BeamPlot',
        'DynamicCoupled',
        ]

In order:

  • BeamLoader: reads the fem.h5 file and generates the structure for the beam solver.
  • AerogridLoader: reads the aero.h5 file and generates the aerodynamic grid for the aerodynamic solver.
  • StaticTrim: this solver performs a longitudinal trim (Thrust, Angle of attack and Elevator deflection) using the StaticCoupled solver.
  • BeamLoads: calculates the internal beam loads for the static solution
  • AerogridPlot: outputs the aerodynamic grid for the static solution.
  • BeamPlot: outputs the structural discretisation for the static solution.
  • DynamicCoupled: is the main driver of the dynamic simulation: executes the structural and aerodynamic solvers and couples both. Every converged time step is followed by a BeamLoads, AerogridPlot and BeamPlot execution.
Structural data organisation

The timestep_info structure contains several relevant variables:

  • for_pos: position of the body-attached frame of reference in inertial FoR.
  • for_vel: velocity (in body FoR) of the body FoR wrt inertial FoR.
  • pos: nodal position in A FoR.
  • psi: nodal rotations (from the material B FoR to A FoR) in a Cartesian Rotation Vector parametrisation.
  • applied_steady_forces: nodal forces from the aero solver and the applied forces.
  • postproc_cell: is a dictionary that contains the variables generated by a postprocessor, such as the internal beam loads.

The structural timestep_info also contains some useful variables:

  • cag and cga return \(C^{AG}\) and \(C^{GA}\), the rotation matrices from the body-attached (A) FoR to the inertial (G).
  • glob_pos rotates the pos variable to give you the inertial nodal position. If include_rbm = True is passed, for_pos is added to it.
Aerodynamic data organisation

The aerodynamic datastructure can be found in case_data.aero.timestep_info. It contains useful variables, such as:

  • dimensions and dimensions_star: gives the dimensions of every surface and wake surface. Organised as: dimensions[i_surf, 0] = chordwise panels, dimensions[i_surf, 1] = spanwise panels.
  • zeta and zeta_star: they are the \(G\) FoR coordinates of the surface vertices.
  • gamma and gamma_star: vortex ring circulations.
Structural dynamics

We can now plot the rigid body dynamics:

RBM trajectory

[16]:
fig, ax = plt.subplots(1, 1, figsize=(7, 4))

# extract information
n_tsteps = len(case_data.structure.timestep_info)
xz = np.zeros((n_tsteps, 2))
for it in range(n_tsteps):
    xz[it, 0] = -case_data.structure.timestep_info[it].for_pos[0] # the - is so that increasing time -> increasing x
    xz[it, 1] = case_data.structure.timestep_info[it].for_pos[2]
ax.plot(xz[:, 0], xz[:, 1])
fig.suptitle('Longitudinal trajectory of the T-Tail model in a 20% 1-cos gust encounter')
ax.set_xlabel('X [m]')
ax.set_ylabel('Z [m]');
plt.show()
_images/content_example_notebooks_nonlinear_t-tail_HALE_22_0.svg

RBM velocities

[17]:
fig, ax = plt.subplots(3, 1, figsize=(7, 6), sharex=True)
ylabels = ['Vx [m/s]', 'Vy [m/s]', 'Vz [m/s]']

# extract information
n_tsteps = len(case_data.structure.timestep_info)
dt = case_data.settings['DynamicCoupled']['dt'].value
time_vec = np.linspace(0, n_tsteps*dt, n_tsteps)
for_vel = np.zeros((n_tsteps, 3))
for it in range(n_tsteps):
    for_vel[it, 0:3] = case_data.structure.timestep_info[it].for_vel[0:3]

for idim in range(3):
    ax[idim].plot(time_vec, for_vel[:, idim])
    ax[idim].set_ylabel(ylabels[idim])

ax[2].set_xlabel('time [s]')
plt.subplots_adjust(hspace=0)
fig.suptitle('Linear RBM velocities. T-Tail model in a 20% 1-cos gust encounter');
# ax.set_xlabel('X [m]')
# ax.set_ylabel('Z [m]');
plt.show()
_images/content_example_notebooks_nonlinear_t-tail_HALE_24_0.svg
[18]:
fig, ax = plt.subplots(3, 1, figsize=(7, 6), sharex=True)
ylabels = ['Roll rate [deg/s]', 'Pitch rate [deg/s]', 'Yaw rate [deg/s]']

# extract information
n_tsteps = len(case_data.structure.timestep_info)
dt = case_data.settings['DynamicCoupled']['dt'].value
time_vec = np.linspace(0, n_tsteps*dt, n_tsteps)
for_vel = np.zeros((n_tsteps, 3))
for it in range(n_tsteps):
    for_vel[it, 0:3] = case_data.structure.timestep_info[it].for_vel[3:6]*180/np.pi

for idim in range(3):
    ax[idim].plot(time_vec, for_vel[:, idim])
    ax[idim].set_ylabel(ylabels[idim])

ax[2].set_xlabel('time [s]')
plt.subplots_adjust(hspace=0)
fig.suptitle('Angular RBM velocities. T-Tail model in a 20% 1-cos gust encounter');
# ax.set_xlabel('X [m]')
# ax.set_ylabel('Z [m]');
plt.show()
_images/content_example_notebooks_nonlinear_t-tail_HALE_25_0.svg

Wing tip deformation

It is stored in timestep_info as pos. We need to find the correct node.

[19]:
fig, ax = plt.subplots(1, 1, figsize=(6, 6))
ax.scatter(case_data.structure.ini_info.pos[:, 0], case_data.structure.ini_info.pos[:, 1])
ax.axis('equal')
tip_node = np.argmax(case_data.structure.ini_info.pos[:, 1])
print('Wing tip node is the maximum Y one: ', tip_node)
ax.scatter(case_data.structure.ini_info.pos[tip_node, 0], case_data.structure.ini_info.pos[tip_node, 1], color='red')
plt.show()
Wing tip node is the maximum Y one:  16
_images/content_example_notebooks_nonlinear_t-tail_HALE_27_1.svg

We can plot now the pos[tip_node,:] variable:

[20]:
fig, ax = plt.subplots(1, 1, figsize=(7, 3))

# extract information
n_tsteps = len(case_data.structure.timestep_info)
xz = np.zeros((n_tsteps, 2))
for it in range(n_tsteps):
    xz[it, 0] = case_data.structure.timestep_info[it].pos[tip_node, 0]
    xz[it, 1] = case_data.structure.timestep_info[it].pos[tip_node, 2]
ax.plot(time_vec, xz[:, 1])
# fig.suptitle('Longitudinal trajectory of the T-Tail model in a 20% 1-cos gust encounter')
ax.set_xlabel('time [s]')
ax.set_ylabel('Vertical disp. [m]');
plt.show()
_images/content_example_notebooks_nonlinear_t-tail_HALE_29_0.svg
[21]:
fig, ax = plt.subplots(1, 1, figsize=(7, 3))

# extract information
n_tsteps = len(case_data.structure.timestep_info)
xz = np.zeros((n_tsteps, 2))
for it in range(n_tsteps):
    xz[it, 0] = case_data.structure.timestep_info[it].pos[tip_node, 0]
    xz[it, 1] = case_data.structure.timestep_info[it].pos[tip_node, 2]
ax.plot(time_vec, xz[:, 0])
# fig.suptitle('Longitudinal trajectory of the T-Tail model in a 20% 1-cos gust encounter')
ax.set_xlabel('time [s]')
ax.set_ylabel('Horizontal disp. [m]\nPositive is aft');
plt.show()
_images/content_example_notebooks_nonlinear_t-tail_HALE_30_0.svg

Wing root loads

The wing root loads can be extracted from the postproc_cell structure in timestep_info.

[22]:
fig, ax = plt.subplots(3, 1, figsize=(7, 6), sharex=True)
ylabels = ['Torsion [Nm2]', 'OOP [Nm2]', 'IP [Nm2]']

# extract information
n_tsteps = len(case_data.structure.timestep_info)
dt = case_data.settings['DynamicCoupled']['dt'].value
time_vec = np.linspace(0, n_tsteps*dt, n_tsteps)
loads = np.zeros((n_tsteps, 3))
for it in range(n_tsteps):
    loads[it, 0:3] = case_data.structure.timestep_info[it].postproc_cell['loads'][0, 3:6]

for idim in range(3):
    ax[idim].plot(time_vec, loads[:, idim])
    ax[idim].set_ylabel(ylabels[idim])

ax[2].set_xlabel('time [s]')
plt.subplots_adjust(hspace=0)
fig.suptitle('Wing root loads. T-Tail model in a 20% 1-cos gust encounter');
# ax.set_xlabel('X [m]')
# ax.set_ylabel('Z [m]');
plt.show()
_images/content_example_notebooks_nonlinear_t-tail_HALE_32_0.svg
Aerodynamic analysis

The aerodynamic analysis can be obviously conducted using python. However, the easiest way is to run the case by yourself and open the files in output/simple_HALE/beam and output/simple_HALE/aero with Paraview.

[23]:
url = 'https://raw.githubusercontent.com/ImperialCollegeLondon/sharpy/dev_doc/docs/source/content/example_notebooks/images/t-tail_solution.png'
Image(url=url, width=600)
[23]:

Asymptotic Stability of a Flying Wing in Cruise Trimmed Conditions

A Horten flying wing is analysed. The nonlinear trim condition is found and the system is linearised. The eigenvalues of the linearised system are then used to evaluate the stability at the cruise trimmed flight conditions.

[1]:
# required packages
import sharpy.utils.algebra as algebra
import sharpy.sharpy_main
from cases.hangar.richards_wing import Baseline
import numpy as np
import configobj
import matplotlib.pyplot as plt
Flight Conditions

Initial flight conditions. The values for angle of attack alpha, control surface deflection cs_deflection and thrust are only initial values. The values required for trim will be calculated by the StaticTrim routine

[2]:
u_inf = 28
alpha_deg = 4.5135
cs_deflection = 0.1814
thrust = 5.5129
Discretisation
[3]:
M = 4  # chordwise panels
N = 11  # spanwise panels
Msf = 5  # wake length in chord numbers
Create Horten Wing
[4]:
ws = Baseline(M=M,
              N=N,
              Mstarfactor=Msf,
              u_inf=u_inf,
              rho=1.02,
              alpha_deg=alpha_deg,
              roll_deg=0,
              cs_deflection_deg=cs_deflection,
              thrust=thrust,
              physical_time=20,
              case_name='horten',
              case_name_format=4,
              case_remarks='M%gN%gMsf%g' % (M, N, Msf))

ws.set_properties()
ws.initialise()
ws.clean_test_files()

ws.update_mass_stiffness(sigma=1., sigma_mass=2.5)
ws.update_fem_prop()
ws.generate_fem_file()
ws.update_aero_properties()
ws.generate_aero_file()
0
Section Mass: 11.88
Linear Mass: 11.88
Section Ixx: 1.8777
Section Iyy: 1.0137
Section Izz: 2.5496
Linear Ixx: 1.88
1
Section Mass: 10.99
Linear Mass: 10.99
Section Ixx: 1.4694
Section Iyy: 0.9345
Section Izz: 2.1501
Linear Ixx: 1.74
2
Section Mass: 10.10
Linear Mass: 10.10
Section Ixx: 1.1257
Section Iyy: 0.8561
Section Izz: 1.7993
Linear Ixx: 1.60
3
Section Mass: 9.21
Linear Mass: 9.21
Section Ixx: 0.8410
Section Iyy: 0.7783
Section Izz: 1.4933
Linear Ixx: 1.46
4
Section Mass: 8.32
Linear Mass: 8.32
Section Ixx: 0.6096
Section Iyy: 0.7011
Section Izz: 1.2280
Linear Ixx: 1.31
5
Section Mass: 7.43
Linear Mass: 7.43
Section Ixx: 0.4260
Section Iyy: 0.6246
Section Izz: 0.9996
Linear Ixx: 1.17
6
Section Mass: 6.54
Linear Mass: 6.54
Section Ixx: 0.2845
Section Iyy: 0.5485
Section Izz: 0.8040
Linear Ixx: 1.03
7
Section Mass: 5.64
Linear Mass: 5.64
Section Ixx: 0.1796
Section Iyy: 0.4728
Section Izz: 0.6374
Linear Ixx: 0.89
8
Section Mass: 4.75
Linear Mass: 4.75
Section Ixx: 0.1055
Section Iyy: 0.3975
Section Izz: 0.4959
Linear Ixx: 0.75
9
Section Mass: 3.86
Linear Mass: 3.86
Section Ixx: 0.0567
Section Iyy: 0.3226
Section Izz: 0.3753
Linear Ixx: 0.61
10
Section Mass: 2.97
Linear Mass: 2.97
Section Ixx: 0.0275
Section Iyy: 0.2479
Section Izz: 0.2719
Linear Ixx: 0.47
Simulation Information

The flow setting tells SHARPy which solvers to run and in which order. You may be stranged by the presence of the DynamicCoupled solver but it is necessary to give an initial speed to the structure. This will allow proper linearisation of the structural and rigid body equations.

[5]:
flow = ['BeamLoader',
        'AerogridLoader',
        'StaticTrim',
        'BeamPlot',
        'AerogridPlot',
        'AeroForcesCalculator',
        'DynamicCoupled',
        'Modal',
        'LinearAssembler',
        'AsymptoticStability',
        'StabilityDerivatives',
        ]
SHARPy Settings
[6]:
settings = dict()
settings['SHARPy'] = {'case': ws.case_name,
                      'route': ws.case_route,
                      'flow': flow,
                      'write_screen': 'on',
                      'write_log': 'on',
                      'log_folder': './output/' + ws.case_name + '/',
                      'log_file': ws.case_name + '.log'}


Loaders
[7]:
settings['BeamLoader'] = {'unsteady': 'off',
                          'orientation': algebra.euler2quat(np.array([ws.roll,
                                                                      ws.alpha,
                                                                      ws.beta]))}
settings['AerogridLoader'] = {'unsteady': 'off',
                              'aligned_grid': 'on',
                              'mstar': int(ws.M * ws.Mstarfactor),
                              'freestream_dir': ['1', '0', '0'],
                              'control_surface_deflection': ['']}
StaticCoupled Solver
[8]:
settings['StaticCoupled'] = {'print_info': 'on',
                             'structural_solver': 'NonLinearStatic',
                             'structural_solver_settings': {'print_info': 'off',
                                                            'max_iterations': 200,
                                                            'num_load_steps': 1,
                                                            'delta_curved': 1e-5,
                                                            'min_delta': ws.tolerance,
                                                            'gravity_on': 'on',
                                                            'gravity': 9.81},
                             'aero_solver': 'StaticUvlm',
                             'aero_solver_settings': {'print_info': 'on',
                                                      'horseshoe': ws.horseshoe,
                                                      'num_cores': 4,
                                                      'n_rollup': int(0),
                                                      'rollup_dt': ws.dt,
                                                      'rollup_aic_refresh': 1,
                                                      'rollup_tolerance': 1e-4,
                                                      'velocity_field_generator': 'SteadyVelocityField',
                                                      'velocity_field_input': {'u_inf': ws.u_inf,
                                                                               'u_inf_direction': [1., 0, 0]},
                                                      'rho': ws.rho},
                             'max_iter': 200,
                             'n_load_steps': 1,
                             'tolerance': ws.tolerance,
                             'relaxation_factor': 0.2}
Trim solver
[9]:
settings['StaticTrim'] = {'solver': 'StaticCoupled',
                          'solver_settings': settings['StaticCoupled'],
                          'thrust_nodes': ws.thrust_nodes,
                          'initial_alpha': ws.alpha,
                          'initial_deflection': ws.cs_deflection,
                          'initial_thrust': ws.thrust,
                          'max_iter': 200,
                          'fz_tolerance': 1e-2,
                          'fx_tolerance': 1e-2,
                          'm_tolerance': 1e-2}
Nonlinear Equilibrium Post-process
[10]:
settings['AerogridPlot'] = {'folder': './output/',
                            'include_rbm': 'off',
                            'include_applied_forces': 'on',
                            'minus_m_star': 0,
                            'u_inf': ws.u_inf
                            }
settings['AeroForcesCalculator'] = {'folder': './output/',
                                    'write_text_file': 'off',
                                    'text_file_name': ws.case_name + '_aeroforces.csv',
                                    'screen_output': 'on',
                                    'unsteady': 'off',
                                    'coefficients': True,
                                    'q_ref': 0.5 * ws.rho * ws.u_inf ** 2,
                                    'S_ref': 12.809,
                                    }

settings['BeamPlot'] = {'folder': './output/',
                        'include_rbm': 'on',
                        'include_applied_forces': 'on',
                        'include_FoR': 'on'}
DynamicCoupled Solver

As mentioned before, a single time step of DynamicCoupled is required to give the structure the velocity required for the linearisation of the rigid body equations to be correct. Hence n_time_steps = 1

[11]:
struct_solver_settings = {'print_info': 'off',
                          'initial_velocity_direction': [-1., 0., 0.],
                          'max_iterations': 950,
                          'delta_curved': 1e-6,
                          'min_delta': ws.tolerance,
                          'newmark_damp': 5e-3,
                          'gravity_on': True,
                          'gravity': 9.81,
                          'num_steps': ws.n_tstep,
                          'dt': ws.dt,
                          'initial_velocity': ws.u_inf * 1}

step_uvlm_settings = {'print_info': 'on',
                      'horseshoe': ws.horseshoe,
                      'num_cores': 4,
                      'n_rollup': 1,
                      'convection_scheme': ws.wake_type,
                      'rollup_dt': ws.dt,
                      'rollup_aic_refresh': 1,
                      'rollup_tolerance': 1e-4,
                      'velocity_field_generator': 'SteadyVelocityField',
                      'velocity_field_input': {'u_inf': ws.u_inf * 0,
                                               'u_inf_direction': [1., 0., 0.]},
                      'rho': ws.rho,
                      'n_time_steps': ws.n_tstep,
                      'dt': ws.dt,
                      'gamma_dot_filtering': 3}

settings['DynamicCoupled'] = {'print_info': 'on',
                              'structural_solver': 'NonLinearDynamicCoupledStep',
                              'structural_solver_settings': struct_solver_settings,
                              'aero_solver': 'StepUvlm',
                              'aero_solver_settings': step_uvlm_settings,
                              'fsi_substeps': 200,
                              'fsi_tolerance': ws.fsi_tolerance,
                              'relaxation_factor': ws.relaxation_factor,
                              'minimum_steps': 1,
                              'relaxation_steps': 150,
                              'final_relaxation_factor': 0.5,
                              'n_time_steps': 1,
                              'dt': ws.dt,
                              'include_unsteady_force_contribution': 'off',
                                                          }
Linear Assembler Settings

Note that for the assembly of the linear system, we replace the parametrisation of the orientation with Euler angles instead of quaternions.

[13]:
settings['LinearAssembler'] = {'linear_system': 'LinearAeroelastic',
                               'linear_system_settings': {
                                   'beam_settings': {'modal_projection': 'off',
                                                     'inout_coords': 'modes',
                                                     'discrete_time': True,
                                                     'newmark_damp': 0.5e-2,
                                                     'discr_method': 'newmark',
                                                     'dt': ws.dt,
                                                     'proj_modes': 'undamped',
                                                     'num_modes': 9,
                                                     'print_info': 'on',
                                                     'gravity': 'on',
                                                     'remove_dofs': []},
                                   'aero_settings': {'dt': ws.dt,
                                                     'integr_order': 2,
                                                     'density': ws.rho,
                                                     'remove_predictor': 'off',
                                                     'use_sparse': 'off',
                                                     'rigid_body_motion': 'on',
                                                     'remove_inputs': ['u_gust']},
                                   'rigid_body_motion': True,
                                   'track_body': 'on',
                                   'use_euler': 'on',
                                   'linearisation_tstep': -1
                                }}
Asymptotic Stability Post-processor
[14]:
settings['AsymptoticStability'] = {
                                    'print_info': 'on',
                                    'frequency_cutoff': 0,
                                    'export_eigenvalues': 'on',
                                    'num_evals': 1000,
                                    'folder': './output/'}
Stability Derivatives Post-processor
[15]:
settings['StabilityDerivatives'] = {'u_inf': ws.u_inf,
                                    'S_ref': 12.809,
                                    'b_ref': ws.span,
                                    'c_ref': 0.719}
Write solver file
[16]:
config = configobj.ConfigObj()
np.set_printoptions(precision=16)
file_name = ws.case_route + '/' + ws.case_name + '.sharpy'
config.filename = file_name
for k, v in settings.items():
    config[k] = v
config.write()
Run Simulation
[17]:
data = sharpy.sharpy_main.main(['', ws.case_route + '/' + ws.case_name + '.sharpy'])
--------------------------------------------------------------------------------
            ######  ##     ##    ###    ########  ########  ##    ##
           ##    ## ##     ##   ## ##   ##     ## ##     ##  ##  ##
           ##       ##     ##  ##   ##  ##     ## ##     ##   ####
            ######  ######### ##     ## ########  ########     ##
                 ## ##     ## ######### ##   ##   ##           ##
           ##    ## ##     ## ##     ## ##    ##  ##           ##
            ######  ##     ## ##     ## ##     ## ##           ##
--------------------------------------------------------------------------------
Aeroelastics Lab, Aeronautics Department.
    Copyright (c), Imperial College London.
    All rights reserved.
    License available at https://github.com/imperialcollegelondon/sharpy
Running SHARPy from /home/ng213/code/sharpy/docs/source/content/example_notebooks
SHARPy being run is in /home/ng213/code/sharpy
The branch being run is dev_examples
The version and commit hash are: v0.1-1590-g7385fe4-7385fe4
The available solvers on this session are:
PreSharpy 
_BaseStructural 
AerogridLoader 
BeamLoader 
DynamicCoupled 
DynamicUVLM 
LinDynamicSim 
LinearAssembler 
Modal 
NoAero 
NonLinearDynamic 
NonLinearDynamicCoupledStep 
NonLinearDynamicMultibody 
NonLinearDynamicPrescribedStep 
NonLinearStatic 
NonLinearStaticMultibody 
PrescribedUvlm 
RigidDynamicPrescribedStep 
SHWUvlm 
StaticCoupled 
StaticCoupledRBM 
StaticTrim 
StaticUvlm 
StepLinearUVLM 
StepUvlm 
Trim 
Cleanup 
PickleData 
SaveData 
CreateSnapshot 
PlotFlowField 
StabilityDerivatives 
AeroForcesCalculator 
WriteVariablesTime 
AerogridPlot 
LiftDistribution 
StallCheck 
FrequencyResponse 
AsymptoticStability 
BeamPlot 
BeamLoads 
Generating an instance of BeamLoader
Generating an instance of AerogridLoader
Variable control_surface_deflection_generator_settings has no assigned value in the settings file.
    will default to the value: []
The aerodynamic grid contains 4 surfaces
  Surface 0, M=4, N=2
     Wake 0, M=20, N=2
  Surface 1, M=4, N=22
     Wake 1, M=20, N=22
  Surface 2, M=4, N=2
     Wake 2, M=20, N=2
  Surface 3, M=4, N=22
     Wake 3, M=20, N=22
  In total: 192 bound panels
  In total: 960 wake panels
  Total number of panels = 1152
Generating an instance of StaticTrim
Variable print_info has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable tail_cs_index has no assigned value in the settings file.
    will default to the value: c_int(0)
Variable initial_angle_eps has no assigned value in the settings file.
    will default to the value: c_double(0.05)
Variable initial_thrust_eps has no assigned value in the settings file.
    will default to the value: c_double(2.0)
Variable relaxation_factor has no assigned value in the settings file.
    will default to the value: c_double(0.2)
Generating an instance of StaticCoupled
Generating an instance of NonLinearStatic
Variable newmark_damp has no assigned value in the settings file.
    will default to the value: c_double(0.0001)
Variable relaxation_factor has no assigned value in the settings file.
    will default to the value: c_double(0.3)
Variable dt has no assigned value in the settings file.
    will default to the value: c_double(0.01)
Variable num_steps has no assigned value in the settings file.
    will default to the value: c_int(500)
Variable initial_position has no assigned value in the settings file.
    will default to the value: [0. 0. 0.]
Generating an instance of StaticUvlm
Variable iterative_solver has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable iterative_tol has no assigned value in the settings file.
    will default to the value: c_double(0.0001)
Variable iterative_precond has no assigned value in the settings file.
    will default to the value: c_bool(False)



|=====|=====|============|==========|==========|==========|==========|==========|==========|
|iter |step | log10(res) |    Fx    |    Fy    |    Fz    |    Mx    |    My    |    Mz    |
|=====|=====|============|==========|==========|==========|==========|==========|==========|



|==========|==========|==========|==========|==========|==========|==========|==========|==========|==========|
|   iter   |  alpha   |   elev   |  thrust  |    Fx    |    Fy    |    Fz    |    Mx    |    My    |    Mz    |
|==========|==========|==========|==========|==========|==========|==========|==========|==========|==========|
|  0  |  0  |  0.00000   | -0.1051  | -0.0000  |  0.0604  | -0.0000  |  1.0816  | -0.0000  |
|  1  |  0  |  -7.62661  | -0.1119  |  0.0000  |  0.1274  | -0.0000  |  0.0026  |  0.0000  |
|  2  |  0  |  -8.34118  | -0.0941  | -0.0000  |  0.0393  |  0.0000  | -0.0793  |  0.0000  |
|  3  |  0  |  -9.29266  | -0.0870  |  0.0000  |  0.0007  | -0.0000  | -0.0089  |  0.0000  |
|  4  |  0  | -10.67443  | -0.0876  |  0.0000  |  0.0028  |  0.0000  | -0.0119  |  0.0000  |
|  5  |  0  | -10.87008  | -0.0878  |  0.0000  |  0.0039  | -0.0000  | -0.0138  |  0.0000  |
|  6  |  0  | -11.64423  | -0.0877  | -0.0000  |  0.0037  |  0.0000  | -0.0135  | -0.0000  |
|  7  |  0  | -12.87835  | -0.0877  |  0.0000  |  0.0037  | -0.0000  | -0.0135  |  0.0000  |
|    0     |  4.5135  |  0.1814  |  5.5129  | -0.0877  |  0.0000  |  0.0037  | -0.0000  | -0.0135  |  0.0000  |
|  0  |  0  |  0.00000   |-116.9870 | -0.0000  | 994.8061 | -0.0000  |-882.4096 |  0.0000  |
|  1  |  0  |  -5.81338  | -81.0252 | -0.0000  | 944.6090 | -0.0000  |-802.5942 | -0.0000  |
|  2  |  0  |  -6.69380  | -74.1802 | -0.0000  | 937.6597 | -0.0000  |-792.1302 |  0.0000  |
|  3  |  0  |  -7.20553  | -75.0015 |  0.0000  | 939.7800 | -0.0000  |-795.7138 | -0.0000  |
|  4  |  0  |  -8.63165  | -74.9725 |  0.0000  | 939.7033 | -0.0000  |-795.5808 |  0.0000  |
|  5  |  0  |  -8.79020  | -74.9511 |  0.0000  | 939.6488 |  0.0000  |-795.4881 |  0.0000  |
|  6  |  0  |  -9.56992  | -74.9546 | -0.0000  | 939.6578 |  0.0000  |-795.5035 | -0.0000  |
|  7  |  0  | -10.77969  | -74.9549 |  0.0000  | 939.6584 | -0.0000  |-795.5044 |  0.0000  |
|  8  |  0  | -10.98913  | -74.9547 | -0.0000  | 939.6580 |  0.0000  |-795.5039 | -0.0000  |
|  9  |  0  | -12.12706  | -74.9547 | -0.0000  | 939.6581 |  0.0000  |-795.5039 | -0.0000  |
|    0     |  7.3783  | -2.6834  |  5.5129  | -74.9547 | -0.0000  | 939.6581 |  0.0000  |-795.5039 | -0.0000  |
|  0  |  0  |  0.00000   | -32.9132 | -0.0000  | 371.4719 | -0.0000  |-902.7965 | -0.0000  |
|  1  |  0  |  -5.48782  | -11.8207 |  0.0000  | 298.8468 | -0.0000  |-777.2958 |  0.0000  |
|  2  |  0  |  -6.40702  | -8.5206  |  0.0000  | 289.8069 | -0.0000  |-761.4879 | -0.0000  |
|  3  |  0  |  -6.85006  | -9.2671  | -0.0000  | 293.2383 |  0.0000  |-767.3401 | -0.0000  |
|  4  |  0  |  -8.25284  | -9.2365  |  0.0000  | 293.1025 | -0.0000  |-767.1091 |  0.0000  |
|  5  |  0  |  -8.43408  | -9.2166  |  0.0000  | 293.0132 |  0.0000  |-766.9570 |  0.0000  |
|  6  |  0  |  -9.20313  | -9.2199  | -0.0000  | 293.0284 | -0.0000  |-766.9829 | -0.0000  |
|  7  |  0  | -10.44114  | -9.2201  |  0.0000  | 293.0293 | -0.0000  |-766.9844 |  0.0000  |
|  8  |  0  | -10.62337  | -9.2200  | -0.0000  | 293.0287 |  0.0000  |-766.9834 | -0.0000  |
|  9  |  0  | -11.73764  | -9.2200  | -0.0000  | 293.0287 |  0.0000  |-766.9835 | -0.0000  |
| 10  |  0  | -12.29756  | -9.2200  |  0.0000  | 293.0287 | -0.0000  |-766.9835 |  0.0000  |
|    0     |  4.5135  |  3.0462  |  5.5129  | -9.2200  |  0.0000  | 293.0287 | -0.0000  |-766.9835 |  0.0000  |
|  0  |  0  |  0.00000   | -4.1051  | -0.0000  |  0.0604  | -0.0000  |  1.0812  | -0.0000  |
|  1  |  0  |  -7.62660  | -4.1120  | -0.0000  |  0.1274  | -0.0000  |  0.0023  | -0.0000  |
|  2  |  0  |  -8.34116  | -4.0942  | -0.0000  |  0.0393  |  0.0000  | -0.0796  | -0.0000  |
|  3  |  0  |  -9.29268  | -4.0871  |  0.0000  |  0.0007  | -0.0000  | -0.0093  |  0.0000  |
|  4  |  0  | -10.67446  | -4.0876  |  0.0000  |  0.0028  |  0.0000  | -0.0123  |  0.0000  |
|  5  |  0  | -10.86979  | -4.0878  |  0.0000  |  0.0039  | -0.0000  | -0.0142  |  0.0000  |
|  6  |  0  | -11.64229  | -4.0878  |  0.0000  |  0.0037  | -0.0000  | -0.0138  |  0.0000  |
|  7  |  0  | -12.86703  | -4.0878  |  0.0000  |  0.0037  | -0.0000  | -0.0138  |  0.0000  |
|    0     |  4.5135  |  0.1814  |  7.5129  | -4.0878  |  0.0000  |  0.0037  | -0.0000  | -0.0138  |  0.0000  |
|  0  |  0  |  0.00000   | -0.0165  |  0.0000  |  0.0499  |  0.0000  |  1.1009  |  0.0000  |
|  1  |  0  |  -7.62629  | -0.0236  |  0.0000  |  0.1184  |  0.0000  |  0.0195  |  0.0000  |
|  2  |  0  |  -8.34096  | -0.0058  | -0.0000  |  0.0305  | -0.0000  | -0.0628  | -0.0000  |
|  3  |  0  |  -9.29199  |  0.0012  |  0.0000  | -0.0082  |  0.0000  |  0.0077  |  0.0000  |
|  4  |  0  | -10.67407  |  0.0007  |  0.0000  | -0.0061  | -0.0000  |  0.0047  |  0.0000  |
|  5  |  0  | -10.86912  |  0.0005  | -0.0000  | -0.0050  |  0.0000  |  0.0028  | -0.0000  |
|  6  |  0  | -11.64225  |  0.0005  |  0.0000  | -0.0052  | -0.0000  |  0.0031  |  0.0000  |
|  7  |  0  | -12.83721  |  0.0005  | -0.0000  | -0.0052  |  0.0000  |  0.0032  | -0.0000  |
|    1     |  4.5135  |  0.1814  |  5.4690  |  0.0005  | -0.0000  | -0.0052  |  0.0000  |  0.0032  | -0.0000  |
Generating an instance of BeamPlot
Variable include_applied_moments has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable name_prefix has no assigned value in the settings file.
    will default to the value: 
Variable output_rbm has no assigned value in the settings file.
    will default to the value: c_bool(True)
...Finished
Generating an instance of AerogridPlot
Variable include_forward_motion has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable include_unsteady_applied_forces has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable name_prefix has no assigned value in the settings file.
    will default to the value: 
Variable dt has no assigned value in the settings file.
    will default to the value: c_double(0.0)
Variable include_velocities has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable num_cores has no assigned value in the settings file.
    will default to the value: c_int(1)
...Finished
Generating an instance of AeroForcesCalculator
--------------------------------------------------------------------------------
tstep |   fx_g     |   fy_g     |   fz_g     |   Cfx_g    |   Cfy_g    |   Cfz_g   
    0 |  1.090e+01 | -1.250e-07 |  1.835e+03 |  2.129e-03 | -2.441e-11 |  3.583e-01
...Finished
Generating an instance of DynamicCoupled
Variable structural_substeps has no assigned value in the settings file.
    will default to the value: c_int(0)
Variable dynamic_relaxation has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable postprocessors has no assigned value in the settings file.
    will default to the value: []
Variable postprocessors_settings has no assigned value in the settings file.
    will default to the value: {}
Variable controller_id has no assigned value in the settings file.
    will default to the value: {}
Variable controller_settings has no assigned value in the settings file.
    will default to the value: {}
Variable cleanup_previous_solution has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable steps_without_unsteady_force has no assigned value in the settings file.
    will default to the value: c_int(0)
Variable pseudosteps_ramp_unsteady_force has no assigned value in the settings file.
    will default to the value: c_int(0)
Generating an instance of NonLinearDynamicCoupledStep
Variable num_load_steps has no assigned value in the settings file.
    will default to the value: c_int(1)
Variable relaxation_factor has no assigned value in the settings file.
    will default to the value: c_double(0.3)
Variable balancing has no assigned value in the settings file.
    will default to the value: c_bool(False)
Generating an instance of StepUvlm
Variable iterative_solver has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable iterative_tol has no assigned value in the settings file.
    will default to the value: c_double(0.0001)
Variable iterative_precond has no assigned value in the settings file.
    will default to the value: c_bool(False)



|=======|========|======|==============|==============|==============|==============|==============|
|  ts   |   t    | iter | struc ratio  |  iter time   | residual vel |  FoR_vel(x)  |  FoR_vel(z)  |
|=======|========|======|==============|==============|==============|==============|==============|
/home/ng213/code/sharpy/sharpy/aero/utils/uvlmlib.py:230: RuntimeWarning: invalid value encountered in true_divide
  flightconditions.uinf_direction = np.ctypeslib.as_ctypes(ts_info.u_ext[0][:, 0, 0]/flightconditions.uinf)
|   1   | 0.0089 |  3   |   0.652648   |   0.921936   |  -10.549271  |-2.791317e+01 |-2.203427e+00 |
...Finished
Generating an instance of Modal
Variable folder has no assigned value in the settings file.
    will default to the value: ./output
Variable keep_linear_matrices has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable write_dat has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable delta_curved has no assigned value in the settings file.
    will default to the value: c_double(0.01)
Variable max_rotation_deg has no assigned value in the settings file.
    will default to the value: c_double(15.0)
Variable max_displacement has no assigned value in the settings file.
    will default to the value: c_double(0.15)
Variable use_custom_timestep has no assigned value in the settings file.
    will default to the value: c_int(-1)
Structural eigenvalues



|==============|==============|==============|==============|==============|==============|==============|
|     mode     |  eval_real   |  eval_imag   | freq_n (Hz)  | freq_d (Hz)  |   damping    |  period (s)  |
|==============|==============|==============|==============|==============|==============|==============|
/home/ng213/code/sharpy/sharpy/solvers/modal.py:284: UserWarning: Projecting a system with damping on undamped modal shapes
  'Projecting a system with damping on undamped modal shapes')
|      0       |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      1       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      2       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      3       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      4       |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      5       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      6       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      7       |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      8       |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      9       |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      10      |   0.000000   |  28.293939   |   4.503120   |   4.503120   |  -0.000000   |   0.222068   |
|      11      |   0.000000   |  29.271318   |   4.658675   |   4.658675   |  -0.000000   |   0.214653   |
|      12      |   0.000000   |  54.780234   |   8.718545   |   8.718545   |  -0.000000   |   0.114698   |
|      13      |   0.000000   |  58.999779   |   9.390106   |   9.390106   |  -0.000000   |   0.106495   |
|      14      |   0.000000   |  70.520741   |  11.223724   |  11.223724   |  -0.000000   |   0.089097   |
|      15      |   0.000000   |  76.917111   |  12.241738   |  12.241738   |  -0.000000   |   0.081688   |
|      16      |   0.000000   |  87.324076   |  13.898058   |  13.898058   |  -0.000000   |   0.071952   |
|      17      |   0.000000   |  108.035577  |  17.194396   |  17.194396   |  -0.000000   |   0.058158   |
|      18      |   0.000000   |  119.692139  |  19.049596   |  19.049596   |  -0.000000   |   0.052495   |
|      19      |   0.000000   |  133.495187  |  21.246419   |  21.246419   |  -0.000000   |   0.047067   |
|      20      |   0.000000   |  134.444788  |  21.397553   |  21.397553   |  -0.000000   |   0.046734   |
|      21      |   0.000000   |  151.060442  |  24.042016   |  24.042016   |  -0.000000   |   0.041594   |
|      22      |   0.000000   |  159.369020  |  25.364367   |  25.364367   |  -0.000000   |   0.039425   |
|      23      |   0.000000   |  171.256102  |  27.256255   |  27.256255   |  -0.000000   |   0.036689   |
|      24      |   0.000000   |  173.895881  |  27.676389   |  27.676389   |  -0.000000   |   0.036132   |
|      25      |   0.000000   |  199.016557  |  31.674469   |  31.674469   |  -0.000000   |   0.031571   |
|      26      |   0.000000   |  205.412581  |  32.692428   |  32.692428   |  -0.000000   |   0.030588   |
|      27      |   0.000000   |  205.419531  |  32.693534   |  32.693534   |  -0.000000   |   0.030587   |
|      28      |   0.000000   |  223.563796  |  35.581283   |  35.581283   |  -0.000000   |   0.028105   |
|      29      |   0.000000   |  227.924750  |  36.275351   |  36.275351   |  -0.000000   |   0.027567   |
Generating an instance of LinearAssembler
Variable linearisation_tstep has no assigned value in the settings file.
    will default to the value: c_int(-1)
Generating an instance of LinearAeroelastic
Variable uvlm_filename has no assigned value in the settings file.
    will default to the value: 
Generating an instance of LinearUVLM
Variable ScalingDict has no assigned value in the settings file.
    will default to the value: {}
Variable gust_assembler has no assigned value in the settings file.
    will default to the value: 
Variable rom_method has no assigned value in the settings file.
    will default to the value: []
Variable rom_method_settings has no assigned value in the settings file.
    will default to the value: {}
Variable length has no assigned value in the settings file.
    will default to the value: 1.0
Variable speed has no assigned value in the settings file.
    will default to the value: 1.0
Variable density has no assigned value in the settings file.
    will default to the value: 1.0
Initialising Static linear UVLM solver class...
                        ...done in 0.27 sec
State-space realisation of UVLM equations started...
state-space model produced in form:
        x_{n+1} = A x_{n} + Bp u_{n+1}
                        ...done in 2.44 sec
Generating an instance of LinearBeam
Variable remove_sym_modes has no assigned value in the settings file.
    will default to the value: False
Warning, projecting system with damping onto undamped modes

Linearising gravity terms...
     M = 187.12 kg
     X_CG A -> 1.19 -0.00 0.01
Node  1      -> B 0.000 -0.089 -0.000
                     -> A 0.089 0.206 0.000
                     -> G 0.089 0.206 -0.007
     Node mass:
             Matrix: 2.6141
Node  2      -> B -0.010 -0.019 -0.000
                     -> A 0.019 0.403 0.000
                     -> G 0.019 0.403 -0.001
     Node mass:
             Matrix: 7.3672
Node  3      -> B -0.019 -0.087 -0.000
                     -> A 0.234 0.800 0.000
                     -> G 0.234 0.800 -0.018
     Node mass:
             Matrix: 5.8780
Node  4      -> B -0.019 -0.084 -0.000
                     -> A 0.390 1.238 0.001
                     -> G 0.389 1.238 -0.030
     Node mass:
             Matrix: 2.8288
Node  5      -> B -0.018 -0.081 -0.000
                     -> A 0.546 1.676 0.001
                     -> G 0.544 1.676 -0.041
     Node mass:
             Matrix: 5.4372
Node  6      -> B -0.017 -0.078 -0.000
                     -> A 0.702 2.113 0.002
                     -> G 0.700 2.113 -0.053
     Node mass:
             Matrix: 2.6084
Node  7      -> B -0.016 -0.074 -0.000
                     -> A 0.857 2.551 0.003
                     -> G 0.855 2.551 -0.064
     Node mass:
             Matrix: 4.9963
Node  8      -> B -0.016 -0.071 -0.000
                     -> A 1.013 2.988 0.004
                     -> G 1.010 2.988 -0.076
     Node mass:
             Matrix: 2.3879
Node  9      -> B -0.015 -0.068 -0.000
                     -> A 1.169 3.426 0.005
                     -> G 1.166 3.426 -0.087
     Node mass:
             Matrix: 4.5555
Node 10      -> B -0.014 -0.065 -0.000
                     -> A 1.325 3.863 0.006
                     -> G 1.321 3.863 -0.098
     Node mass:
             Matrix: 2.1675
Node 11      -> B -0.013 -0.061 -0.000
                     -> A 1.480 4.301 0.007
                     -> G 1.476 4.301 -0.109
     Node mass:
             Matrix: 4.1146
Node 12      -> B -0.013 -0.058 -0.000
                     -> A 1.636 4.739 0.009
                     -> G 1.632 4.739 -0.120
     Node mass:
             Matrix: 1.9471
Node 13      -> B -0.012 -0.055 -0.000
                     -> A 1.792 5.176 0.010
                     -> G 1.787 5.176 -0.131
     Node mass:
             Matrix: 3.6738
Node 14      -> B -0.011 -0.052 -0.000
                     -> A 1.948 5.614 0.011
                     -> G 1.943 5.614 -0.142
     Node mass:
             Matrix: 1.7267
Node 15      -> B -0.011 -0.048 -0.000
                     -> A 2.104 6.052 0.012
                     -> G 2.098 6.052 -0.153
     Node mass:
             Matrix: 3.2329
Node 16      -> B -0.010 -0.045 -0.000
                     -> A 2.260 6.489 0.014
                     -> G 2.254 6.489 -0.164
     Node mass:
             Matrix: 1.5062
Node 17      -> B -0.009 -0.042 -0.000
                     -> A 2.415 6.927 0.015
                     -> G 2.409 6.927 -0.175
     Node mass:
             Matrix: 2.7921
Node 18      -> B -0.008 -0.039 -0.000
                     -> A 2.571 7.364 0.016
                     -> G 2.564 7.364 -0.186
     Node mass:
             Matrix: 1.2858
Node 19      -> B -0.008 -0.035 -0.000
                     -> A 2.727 7.802 0.017
                     -> G 2.720 7.802 -0.197
     Node mass:
             Matrix: 2.3512
Node 20      -> B -0.007 -0.032 -0.000
                     -> A 2.883 8.239 0.019
                     -> G 2.875 8.239 -0.208
     Node mass:
             Matrix: 1.0654
Node 21      -> B -0.006 -0.028 -0.000
                     -> A 3.038 8.677 0.020
                     -> G 3.030 8.677 -0.219
     Node mass:
             Matrix: 1.9104
Node 22      -> B -0.006 -0.026 -0.000
                     -> A 3.194 9.114 0.021
                     -> G 3.186 9.114 -0.230
     Node mass:
             Matrix: 0.8450
Node 23      -> B -0.005 -0.022 -0.000
                     -> A 3.350 9.552 0.023
                     -> G 3.341 9.552 -0.241
     Node mass:
             Matrix: 1.4695
Node 24      -> B -0.005 -0.022 -0.000
                     -> A 3.508 9.988 0.024
                     -> G 3.499 9.988 -0.252
     Node mass:
             Matrix: 0.3674
Node 25      -> B 0.000 0.089 -0.000
                     -> A 0.089 -0.206 0.000
                     -> G 0.089 -0.206 -0.007
     Node mass:
             Matrix: 2.6141
Node 26      -> B -0.010 0.019 -0.000
                     -> A 0.019 -0.403 0.000
                     -> G 0.019 -0.403 -0.001
     Node mass:
             Matrix: 7.3672
Node 27      -> B -0.019 0.087 -0.000
                     -> A 0.234 -0.800 0.000
                     -> G 0.234 -0.800 -0.018
     Node mass:
             Matrix: 5.8780
Node 28      -> B -0.019 0.084 -0.000
                     -> A 0.390 -1.238 0.001
                     -> G 0.389 -1.238 -0.030
     Node mass:
             Matrix: 2.8288
Node 29      -> B -0.018 0.081 -0.000
                     -> A 0.546 -1.676 0.001
                     -> G 0.544 -1.676 -0.041
     Node mass:
             Matrix: 5.4372
Node 30      -> B -0.017 0.078 -0.000
                     -> A 0.702 -2.113 0.002
                     -> G 0.700 -2.113 -0.053
     Node mass:
             Matrix: 2.6084
Node 31      -> B -0.016 0.074 -0.000
                     -> A 0.857 -2.551 0.003
                     -> G 0.855 -2.551 -0.064
     Node mass:
             Matrix: 4.9963
Node 32      -> B -0.016 0.071 -0.000
                     -> A 1.013 -2.988 0.004
                     -> G 1.010 -2.988 -0.076
     Node mass:
             Matrix: 2.3879
Node 33      -> B -0.015 0.068 -0.000
                     -> A 1.169 -3.426 0.005
                     -> G 1.166 -3.426 -0.087
     Node mass:
             Matrix: 4.5555
Node 34      -> B -0.014 0.065 -0.000
                     -> A 1.325 -3.863 0.006
                     -> G 1.321 -3.863 -0.098
     Node mass:
             Matrix: 2.1675
Node 35      -> B -0.013 0.061 -0.000
                     -> A 1.480 -4.301 0.007
                     -> G 1.476 -4.301 -0.109
     Node mass:
             Matrix: 4.1146
Node 36      -> B -0.013 0.058 -0.000
                     -> A 1.636 -4.739 0.009
                     -> G 1.632 -4.739 -0.120
     Node mass:
             Matrix: 1.9471
Node 37      -> B -0.012 0.055 -0.000
                     -> A 1.792 -5.176 0.010
                     -> G 1.787 -5.176 -0.131
     Node mass:
             Matrix: 3.6738
Node 38      -> B -0.011 0.052 -0.000
                     -> A 1.948 -5.614 0.011
                     -> G 1.943 -5.614 -0.142
     Node mass:
             Matrix: 1.7267
Node 39      -> B -0.011 0.048 -0.000
                     -> A 2.104 -6.052 0.012
                     -> G 2.098 -6.052 -0.153
     Node mass:
             Matrix: 3.2329
Node 40      -> B -0.010 0.045 -0.000
                     -> A 2.260 -6.489 0.014
                     -> G 2.254 -6.489 -0.164
     Node mass:
             Matrix: 1.5062
Node 41      -> B -0.009 0.042 -0.000
                     -> A 2.415 -6.927 0.015
                     -> G 2.409 -6.927 -0.175
     Node mass:
             Matrix: 2.7921
Node 42      -> B -0.008 0.039 -0.000
                     -> A 2.571 -7.364 0.016
                     -> G 2.564 -7.364 -0.186
     Node mass:
             Matrix: 1.2858
Node 43      -> B -0.008 0.035 -0.000
                     -> A 2.727 -7.802 0.017
                     -> G 2.720 -7.802 -0.197
     Node mass:
             Matrix: 2.3512
Node 44      -> B -0.007 0.032 -0.000
                     -> A 2.883 -8.239 0.019
                     -> G 2.875 -8.239 -0.208
     Node mass:
             Matrix: 1.0654
Node 45      -> B -0.006 0.028 -0.000
                     -> A 3.038 -8.677 0.020
                     -> G 3.030 -8.677 -0.219
     Node mass:
             Matrix: 1.9104
Node 46      -> B -0.006 0.026 -0.000
                     -> A 3.194 -9.114 0.021
                     -> G 3.186 -9.114 -0.230
     Node mass:
             Matrix: 0.8450
Node 47      -> B -0.005 0.022 -0.000
                     -> A 3.350 -9.552 0.023
                     -> G 3.341 -9.552 -0.241
     Node mass:
             Matrix: 1.4695
Node 48      -> B -0.005 0.022 -0.000
                     -> A 3.508 -9.988 0.024
                     -> G 3.499 -9.988 -0.252
     Node mass:
             Matrix: 0.3674
        Updated the beam C, modal C and K matrices with the terms from the
gravity linearisation

Aeroelastic system assembled:
     Aerodynamic states: 1536
     Structural states: 594
     Total states: 2130
     Inputs: 893
     Outputs: 891
Generating an instance of AsymptoticStability
Variable reference_velocity has no assigned value in the settings file.
    will default to the value: c_double(1.0)
Variable display_root_locus has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable velocity_analysis has no assigned value in the settings file.
    will default to the value: []
Variable modes_to_plot has no assigned value in the settings file.
    will default to the value: []
Variable postprocessors has no assigned value in the settings file.
    will default to the value: []
Variable postprocessors_settings has no assigned value in the settings file.
    will default to the value: {}
Dynamical System Eigenvalues



|==============|==============|==============|==============|==============|==============|==============|
|     mode     |  eval_real   |  eval_imag   | freq_n (Hz)  | freq_d (Hz)  |   damping    |  period (s)  |
|==============|==============|==============|==============|==============|==============|==============|
|      0       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      1       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      2       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      3       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      4       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      5       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      6       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      7       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      8       |   0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      9       |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |   1.000000   |     inf      |
|      10      |  -0.000884   |   0.321695   |   0.051200   |   0.051199   |   0.002749   |  19.531499   |
|      11      |  -0.000884   |  -0.321695   |   0.051200   |   0.051199   |   0.002749   |  19.531499   |
|      12      |  -0.008471   |  -0.391290   |   0.062290   |   0.062276   |   0.021644   |  16.057627   |
|      13      |  -0.008471   |   0.391290   |   0.062290   |   0.062276   |   0.021644   |  16.057627   |
|      14      |  -0.022506   |   0.000000   |   0.003582   |   0.000000   |   1.000000   |     inf      |
|      15      |  -0.064807   |  -53.732340  |   8.551774   |   8.551767   |   0.001206   |   0.116935   |
|      16      |  -0.064807   |  53.732340   |   8.551774   |   8.551767   |   0.001206   |   0.116935   |
|      17      |  -0.101946   |  68.319126   |  10.873339   |  10.873327   |   0.001492   |   0.091968   |
|      18      |  -0.101946   |  -68.319126  |  10.873339   |  10.873327   |   0.001492   |   0.091968   |
|      19      |  -0.147587   |  83.265087   |  13.252071   |  13.252050   |   0.001772   |   0.075460   |
|      20      |  -0.147587   |  -83.265087  |  13.252071   |  13.252050   |   0.001772   |   0.075460   |
|      21      |  -0.248703   |  109.925761  |  17.495273   |  17.495228   |   0.002262   |   0.057158   |
|      22      |  -0.248703   | -109.925761  |  17.495273   |  17.495228   |   0.002262   |   0.057158   |
|      23      |  -0.293471   | -120.387486  |  19.160320   |  19.160263   |   0.002438   |   0.052191   |
|      24      |  -0.293471   |  120.387486  |  19.160320   |  19.160263   |   0.002438   |   0.052191   |
|      25      |  -0.350319   | -132.903267  |  21.152285   |  21.152212   |   0.002636   |   0.047276   |
|      26      |  -0.350319   |  132.903267  |  21.152285   |  21.152212   |   0.002636   |   0.047276   |
|      27      |  -0.376400   | -138.516845  |  22.045722   |  22.045641   |   0.002717   |   0.045360   |
|      28      |  -0.376400   |  138.516845  |  22.045722   |  22.045641   |   0.002717   |   0.045360   |
|      29      |  -0.494445   | -162.714219  |  25.896892   |  25.896772   |   0.003039   |   0.038615   |
|      30      |  -0.494445   |  162.714219  |  25.896892   |  25.896772   |   0.003039   |   0.038615   |
|      31      |  -0.511650   |  166.238203  |  26.457757   |  26.457632   |   0.003078   |   0.037796   |
|      32      |  -0.511650   | -166.238203  |  26.457757   |  26.457632   |   0.003078   |   0.037796   |
|      33      |  -0.559180   |  175.709808  |  27.965226   |  27.965084   |   0.003182   |   0.035759   |
|      34      |  -0.559180   | -175.709808  |  27.965226   |  27.965084   |   0.003182   |   0.035759   |
|      35      |  -0.569755   | -177.873185  |  28.309542   |  28.309397   |   0.003203   |   0.035324   |
|      36      |  -0.569755   |  177.873185  |  28.309542   |  28.309397   |   0.003203   |   0.035324   |
|      37      |  -0.669914   | -197.999013  |  31.512702   |  31.512522   |   0.003383   |   0.031733   |
|      38      |  -0.669914   |  197.999013  |  31.512702   |  31.512522   |   0.003383   |   0.031733   |
|      39      |  -0.678424   | -199.782668  |  31.796582   |  31.796399   |   0.003396   |   0.031450   |
|      40      |  -0.678424   |  199.782668  |  31.796582   |  31.796399   |   0.003396   |   0.031450   |
|      41      |  -0.715684   | -207.440558  |  33.015387   |  33.015190   |   0.003450   |   0.030289   |
|      42      |  -0.715684   |  207.440558  |  33.015387   |  33.015190   |   0.003450   |   0.030289   |
|      43      |  -0.721193   | -208.622990  |  33.203578   |  33.203380   |   0.003457   |   0.030117   |
|      44      |  -0.721193   |  208.622990  |  33.203578   |  33.203380   |   0.003457   |   0.030117   |
|      45      |  -0.796838   | -224.809925  |  35.779836   |  35.779611   |   0.003544   |   0.027949   |
|      46      |  -0.796838   |  224.809925  |  35.779836   |  35.779611   |   0.003544   |   0.027949   |
|      47      |  -0.801462   | -225.851206  |  35.945562   |  35.945336   |   0.003549   |   0.027820   |
|      48      |  -0.801462   |  225.851206  |  35.945562   |  35.945336   |   0.003549   |   0.027820   |
|      49      |  -0.823221   | -257.880049  |  41.043094   |  41.042885   |   0.003192   |   0.024365   |
|      50      |  -0.823221   |  257.880049  |  41.043094   |  41.042885   |   0.003192   |   0.024365   |
|      51      |  -0.829849   |  232.223375  |  36.959734   |  36.959498   |   0.003573   |   0.027057   |
|      52      |  -0.829849   | -232.223375  |  36.959734   |  36.959498   |   0.003573   |   0.027057   |
|      53      |  -0.833132   |  232.986709  |  37.081224   |  37.080986   |   0.003576   |   0.026968   |
|      54      |  -0.833132   | -232.986709  |  37.081224   |  37.080986   |   0.003576   |   0.026968   |
|      55      |  -0.837695   |  252.830753  |  40.239485   |  40.239264   |   0.003313   |   0.024851   |
|      56      |  -0.837695   | -252.830753  |  40.239485   |  40.239264   |   0.003313   |   0.024851   |
|      57      |  -0.843057   |  274.636583  |  43.709976   |  43.709770   |   0.003070   |   0.022878   |
|      58      |  -0.843057   | -274.636583  |  43.709976   |  43.709770   |   0.003070   |   0.022878   |
|      59      |  -0.855992   |  264.468482  |  42.091687   |  42.091466   |   0.003237   |   0.023758   |
|      60      |  -0.855992   | -264.468482  |  42.091687   |  42.091466   |   0.003237   |   0.023758   |
|      61      |  -0.864725   |  271.184097  |  43.160509   |  43.160289   |   0.003189   |   0.023169   |
|      62      |  -0.864725   | -271.184097  |  43.160509   |  43.160289   |   0.003189   |   0.023169   |
|      63      |  -0.871326   | -283.421753  |  45.108186   |  45.107973   |   0.003074   |   0.022169   |
|      64      |  -0.871326   |  283.421753  |  45.108186   |  45.107973   |   0.003074   |   0.022169   |
|      65      |  -0.878446   | -267.336880  |  42.548216   |  42.547986   |   0.003286   |   0.023503   |
|      66      |  -0.878446   |  267.336880  |  42.548216   |  42.547986   |   0.003286   |   0.023503   |
|      67      |  -0.882869   | -280.833492  |  44.696259   |  44.696038   |   0.003144   |   0.022373   |
|      68      |  -0.882869   |  280.833492  |  44.696259   |  44.696038   |   0.003144   |   0.022373   |
|      69      |  -0.884024   |  245.027541  |  38.997598   |  38.997344   |   0.003608   |   0.025643   |
|      70      |  -0.884024   | -245.027541  |  38.997598   |  38.997344   |   0.003608   |   0.025643   |
|      71      |  -0.886589   | -245.661872  |  39.098556   |  39.098301   |   0.003609   |   0.025577   |
|      72      |  -0.886589   |  245.661872  |  39.098556   |  39.098301   |   0.003609   |   0.025577   |
|      73      |  -0.891211   |  288.915187  |  45.982499   |  45.982280   |   0.003085   |   0.021748   |
|      74      |  -0.891211   | -288.915187  |  45.982499   |  45.982280   |   0.003085   |   0.021748   |
|      75      |  -0.908699   |  251.206722  |  39.981053   |  39.980792   |   0.003617   |   0.025012   |
|      76      |  -0.908699   | -251.206722  |  39.981053   |  39.980792   |   0.003617   |   0.025012   |
|      77      |  -0.910251   |  251.606123  |  40.044620   |  40.044358   |   0.003618   |   0.024972   |
|      78      |  -0.910251   | -251.606123  |  40.044620   |  40.044358   |   0.003618   |   0.024972   |
|      79      |  -0.914189   | -241.156654  |  38.381549   |  38.381274   |   0.003791   |   0.026054   |
|      80      |  -0.914189   |  241.156654  |  38.381549   |  38.381274   |   0.003791   |   0.026054   |
|      81      |  -0.915396   |  290.517028  |  46.237451   |  46.237221   |   0.003151   |   0.021628   |
|      82      |  -0.915396   | -290.517028  |  46.237451   |  46.237221   |   0.003151   |   0.021628   |
|      83      |  -0.933975   |  278.955366  |  44.397374   |  44.397125   |   0.003348   |   0.022524   |
|      84      |  -0.933975   | -278.955366  |  44.397374   |  44.397125   |   0.003348   |   0.022524   |
|      85      |  -0.943144   |  260.320871  |  41.431625   |  41.431353   |   0.003623   |   0.024136   |
|      86      |  -0.943144   | -260.320871  |  41.431625   |  41.431353   |   0.003623   |   0.024136   |
|      87      |  -0.944542   |  260.700477  |  41.492042   |  41.491770   |   0.003623   |   0.024101   |
|      88      |  -0.944542   | -260.700477  |  41.492042   |  41.491770   |   0.003623   |   0.024101   |
|      89      |  -0.953005   |  294.814043  |  46.921357   |  46.921112   |   0.003233   |   0.021312   |
|      90      |  -0.953005   | -294.814043  |  46.921357   |  46.921112   |   0.003233   |   0.021312   |
|      91      |  -0.960628   |  295.652741  |  47.054843   |  47.054595   |   0.003249   |   0.021252   |
|      92      |  -0.960628   | -295.652741  |  47.054843   |  47.054595   |   0.003249   |   0.021252   |
|      93      |  -0.960976   |  265.315973  |  42.226626   |  42.226349   |   0.003622   |   0.023682   |
|      94      |  -0.960976   | -265.315973  |  42.226626   |  42.226349   |   0.003622   |   0.023682   |
|      95      |  -0.961740   | -300.017780  |  47.749558   |  47.749313   |   0.003206   |   0.020943   |
|      96      |  -0.961740   |  300.017780  |  47.749558   |  47.749313   |   0.003206   |   0.020943   |
|      97      |  -0.961940   | -265.596058  |  42.271203   |  42.270926   |   0.003622   |   0.023657   |
|      98      |  -0.961940   |  265.596058  |  42.271203   |  42.270926   |   0.003622   |   0.023657   |
|      99      |  -0.965384   |  266.582845  |  42.428256   |  42.427978   |   0.003621   |   0.023569   |
|     100      |  -0.965384   | -266.582845  |  42.428256   |  42.427978   |   0.003621   |   0.023569   |
|     101      |  -0.968899   | -235.916658  |  37.547619   |  37.547302   |   0.004107   |   0.026633   |
|     102      |  -0.968899   |  235.916658  |  37.547619   |  37.547302   |   0.004107   |   0.026633   |
|     103      |  -0.969126   |  301.069959  |  47.917020   |  47.916772   |   0.003219   |   0.020870   |
|     104      |  -0.969126   | -301.069959  |  47.917020   |  47.916772   |   0.003219   |   0.020870   |
|     105      |  -0.977774   | -281.665806  |  44.828775   |  44.828505   |   0.003471   |   0.022307   |
|     106      |  -0.977774   |  281.665806  |  44.828775   |  44.828505   |   0.003471   |   0.022307   |
|     107      |  -0.984431   | -272.268138  |  43.333103   |  43.332820   |   0.003616   |   0.023077   |
|     108      |  -0.984431   |  272.268138  |  43.333103   |  43.332820   |   0.003616   |   0.023077   |
|     109      |  -0.985003   |  251.399896  |  40.011843   |  40.011536   |   0.003918   |   0.024993   |
|     110      |  -0.985003   | -251.399896  |  40.011843   |  40.011536   |   0.003918   |   0.024993   |
|     111      |  -0.985198   | -272.494340  |  43.369105   |  43.368821   |   0.003615   |   0.023058   |
|     112      |  -0.985198   |  272.494340  |  43.369105   |  43.368821   |   0.003615   |   0.023058   |
|     113      |  -0.998111   |  276.558228  |  44.015896   |  44.015609   |   0.003609   |   0.022719   |
|     114      |  -0.998111   | -276.558228  |  44.015896   |  44.015609   |   0.003609   |   0.022719   |
|     115      |  -0.998802   |  276.771420  |  44.049826   |  44.049540   |   0.003609   |   0.022702   |
|     116      |  -0.998802   | -276.771420  |  44.049826   |  44.049540   |   0.003609   |   0.022702   |
|     117      |  -1.002609   | -296.732610  |  47.226731   |  47.226462   |   0.003379   |   0.021175   |
|     118      |  -1.002609   |  296.732610  |  47.226731   |  47.226462   |   0.003379   |   0.021175   |
|     119      |  -1.006593   | -246.344800  |  39.207320   |  39.206993   |   0.004086   |   0.025506   |
|     120      |  -1.006593   |  246.344800  |  39.207320   |  39.206993   |   0.004086   |   0.025506   |
|     121      |  -1.012564   | -297.793229  |  47.395538   |  47.395264   |   0.003400   |   0.021099   |
|     122      |  -1.012564   |  297.793229  |  47.395538   |  47.395264   |   0.003400   |   0.021099   |
|     123      |  -1.014283   |  306.354455  |  48.758093   |  48.757826   |   0.003311   |   0.020510   |
|     124      |  -1.014283   | -306.354455  |  48.758093   |  48.757826   |   0.003311   |   0.020510   |
|     125      |  -1.014361   |  281.941928  |  44.872742   |  44.872451   |   0.003598   |   0.022285   |
|     126      |  -1.014361   | -281.941928  |  44.872742   |  44.872451   |   0.003598   |   0.022285   |
|     127      |  -1.014860   |  282.102785  |  44.898343   |  44.898053   |   0.003597   |   0.022273   |
|     128      |  -1.014860   | -282.102785  |  44.898343   |  44.898053   |   0.003597   |   0.022273   |
|     129      |  -1.017175   | -306.227153  |  48.737834   |  48.737565   |   0.003322   |   0.020518   |
|     130      |  -1.017175   |  306.227153  |  48.737834   |  48.737565   |   0.003322   |   0.020518   |
|     131      |  -1.017450   |  57.533524   |   9.158176   |   9.156745   |   0.017682   |   0.109209   |
|     132      |  -1.017450   |  -57.533524  |   9.158176   |   9.156745   |   0.017682   |   0.109209   |
|     133      |  -1.021012   |  310.599833  |  49.433766   |  49.433499   |   0.003287   |   0.020229   |
|     134      |  -1.021012   | -310.599833  |  49.433766   |  49.433499   |   0.003287   |   0.020229   |
|     135      |  -1.021452   |  310.492397  |  49.416667   |  49.416400   |   0.003290   |   0.020236   |
|     136      |  -1.021452   | -310.492397  |  49.416667   |  49.416400   |   0.003290   |   0.020236   |
|     137      |  -1.022875   | -284.908060  |  45.344818   |  45.344526   |   0.003590   |   0.022053   |
|     138      |  -1.022875   |  284.908060  |  45.344818   |  45.344526   |   0.003590   |   0.022053   |
|     139      |  -1.023294   |  285.048653  |  45.367195   |  45.366902   |   0.003590   |   0.022043   |
|     140      |  -1.023294   | -285.048653  |  45.367195   |  45.366902   |   0.003590   |   0.022043   |
|     141      |  -1.036388   | -289.874565  |  46.135265   |  46.134970   |   0.003575   |   0.021676   |
|     142      |  -1.036388   |  289.874565  |  46.135265   |  46.134970   |   0.003575   |   0.021676   |
|     143      |  -1.036747   | -290.000394  |  46.155291   |  46.154996   |   0.003575   |   0.021666   |
|     144      |  -1.036747   |  290.000394  |  46.155291   |  46.154996   |   0.003575   |   0.021666   |
|     145      |  -1.040407   |  291.418922  |  46.381058   |  46.380762   |   0.003570   |   0.021561   |
|     146      |  -1.040407   | -291.418922  |  46.381058   |  46.380762   |   0.003570   |   0.021561   |
|     147      |  -1.040753   |  291.545493  |  46.401202   |  46.400906   |   0.003570   |   0.021551   |
|     148      |  -1.040753   | -291.545493  |  46.401202   |  46.400906   |   0.003570   |   0.021551   |
|     149      |  -1.041948   |  304.815949  |  48.513248   |  48.512965   |   0.003418   |   0.020613   |
|     150      |  -1.041948   | -304.815949  |  48.513248   |  48.512965   |   0.003418   |   0.020613   |
|     151      |  -1.042964   | -314.673618  |  50.082137   |  50.081862   |   0.003314   |   0.019967   |
|     152      |  -1.042964   |  314.673618  |  50.082137   |  50.081862   |   0.003314   |   0.019967   |
|     153      |  -1.043286   | -307.905151  |  49.004908   |  49.004627   |   0.003388   |   0.020406   |
|     154      |  -1.043286   |  307.905151  |  49.004908   |  49.004627   |   0.003388   |   0.020406   |
|     155      |  -1.044327   |  308.342971  |  49.074590   |  49.074308   |   0.003387   |   0.020377   |
|     156      |  -1.044327   | -308.342971  |  49.074590   |  49.074308   |   0.003387   |   0.020377   |
|     157      |  -1.046009   | -304.875396  |  48.522712   |  48.522426   |   0.003431   |   0.020609   |
|     158      |  -1.046009   |  304.875396  |  48.522712   |  48.522426   |   0.003431   |   0.020609   |
|     159      |  -1.047589   |  314.548401  |  50.062210   |  50.061933   |   0.003330   |   0.019975   |
|     160      |  -1.047589   | -314.548401  |  50.062210   |  50.061933   |   0.003330   |   0.019975   |
|     161      |  -1.049126   | -306.882777  |  48.842196   |  48.841911   |   0.003419   |   0.020474   |
|     162      |  -1.049126   |  306.882777  |  48.842196   |  48.841911   |   0.003419   |   0.020474   |
|     163      |  -1.050232   |  295.362748  |  47.008739   |  47.008441   |   0.003556   |   0.021273   |
|     164      |  -1.050232   | -295.362748  |  47.008739   |  47.008441   |   0.003556   |   0.021273   |
|     165      |  -1.050553   | -295.497323  |  47.030157   |  47.029860   |   0.003555   |   0.021263   |
|     166      |  -1.050553   |  295.497323  |  47.030157   |  47.029860   |   0.003555   |   0.021263   |
|     167      |  -1.051548   | -295.907799  |  47.095486   |  47.095189   |   0.003554   |   0.021234   |
|     168      |  -1.051548   |  295.907799  |  47.095486   |  47.095189   |   0.003554   |   0.021234   |
|     169      |  -1.051948   |  296.064745  |  47.120465   |  47.120168   |   0.003553   |   0.021222   |
|     170      |  -1.051948   | -296.064745  |  47.120465   |  47.120168   |   0.003553   |   0.021222   |
|     171      |  -1.054264   | -306.923573  |  48.848692   |  48.848404   |   0.003435   |   0.020471   |
|     172      |  -1.054264   |  306.923573  |  48.848692   |  48.848404   |   0.003435   |   0.020471   |
|     173      |  -1.054520   | -318.465849  |  50.685692   |  50.685414   |   0.003311   |   0.019730   |
|     174      |  -1.054520   |  318.465849  |  50.685692   |  50.685414   |   0.003311   |   0.019730   |
|     175      |  -1.055288   | -318.515081  |  50.693528   |  50.693250   |   0.003313   |   0.019726   |
|     176      |  -1.055288   |  318.515081  |  50.693528   |  50.693250   |   0.003313   |   0.019726   |
|     177      |  -1.057440   |  314.897307  |  50.117746   |  50.117463   |   0.003358   |   0.019953   |
|     178      |  -1.057440   | -314.897307  |  50.117746   |  50.117463   |   0.003358   |   0.019953   |
|     179      |  -1.058199   | -309.920136  |  49.325609   |  49.325322   |   0.003414   |   0.020274   |
|     180      |  -1.058199   |  309.920136  |  49.325609   |  49.325322   |   0.003414   |   0.020274   |
|     181      |  -1.059262   |  299.214097  |  47.621701   |  47.621403   |   0.003540   |   0.020999   |
|     182      |  -1.059262   | -299.214097  |  47.621701   |  47.621403   |   0.003540   |   0.020999   |
|     183      |  -1.059504   | -299.314232  |  47.637638   |  47.637340   |   0.003540   |   0.020992   |
|     184      |  -1.059504   |  299.314232  |  47.637638   |  47.637340   |   0.003540   |   0.020992   |
|     185      |  -1.060555   | -299.787498  |  47.712961   |  47.712662   |   0.003538   |   0.020959   |
|     186      |  -1.060555   |  299.787498  |  47.712961   |  47.712662   |   0.003538   |   0.020959   |
|     187      |  -1.060658   | -309.965877  |  49.332890   |  49.332602   |   0.003422   |   0.020271   |
|     188      |  -1.060658   |  309.965877  |  49.332890   |  49.332602   |   0.003422   |   0.020271   |
|     189      |  -1.060760   |  299.897460  |  47.730462   |  47.730163   |   0.003537   |   0.020951   |
|     190      |  -1.060760   | -299.897460  |  47.730462   |  47.730163   |   0.003537   |   0.020951   |
|     191      |  -1.064660   |  315.237918  |  50.171959   |  50.171673   |   0.003377   |   0.019932   |
|     192      |  -1.064660   | -315.237918  |  50.171959   |  50.171673   |   0.003377   |   0.019932   |
|     193      |  -1.065948   | -313.067380  |  49.826510   |  49.826221   |   0.003405   |   0.020070   |
|     194      |  -1.065948   |  313.067380  |  49.826510   |  49.826221   |   0.003405   |   0.020070   |
|     195      |  -1.066182   |  312.991749  |  49.814473   |  49.814184   |   0.003406   |   0.020075   |
|     196      |  -1.066182   | -312.991749  |  49.814473   |  49.814184   |   0.003406   |   0.020075   |
|     197      |  -1.070206   |  304.267646  |  48.425999   |  48.425700   |   0.003517   |   0.020650   |
|     198      |  -1.070206   | -304.267646  |  48.425999   |  48.425700   |   0.003517   |   0.020650   |
|     199      |  -1.070296   |  304.308945  |  48.432572   |  48.432273   |   0.003517   |   0.020647   |
|     200      |  -1.070296   | -304.308945  |  48.432572   |  48.432273   |   0.003517   |   0.020647   |
|     201      |  -1.071416   | -304.858400  |  48.520021   |  48.519721   |   0.003514   |   0.020610   |
|     202      |  -1.071416   |  304.858400  |  48.520021   |  48.519721   |   0.003514   |   0.020610   |
|     203      |  -1.071537   | -304.918001  |  48.529507   |  48.529207   |   0.003514   |   0.020606   |
|     204      |  -1.071537   |  304.918001  |  48.529507   |  48.529207   |   0.003514   |   0.020606   |
|     205      |  -1.071722   | -321.513275  |  51.170711   |  51.170427   |   0.003333   |   0.019543   |
|     206      |  -1.071722   |  321.513275  |  51.170711   |  51.170427   |   0.003333   |   0.019543   |
|     207      |  -1.072773   | -321.531559  |  51.173622   |  51.173337   |   0.003336   |   0.019541   |
|     208      |  -1.072773   |  321.531559  |  51.173622   |  51.173337   |   0.003336   |   0.019541   |
|     209      |  -1.073011   |  316.543066  |  50.379683   |  50.379394   |   0.003390   |   0.019849   |
|     210      |  -1.073011   | -316.543066  |  50.379683   |  50.379394   |   0.003390   |   0.019849   |
|     211      |  -1.073122   | -316.594455  |  50.387862   |  50.387573   |   0.003390   |   0.019846   |
|     212      |  -1.073122   |  316.594455  |  50.387862   |  50.387573   |   0.003390   |   0.019846   |
|     213      |  -1.075633   |  324.572398  |  51.657585   |  51.657302   |   0.003314   |   0.019358   |
|     214      |  -1.075633   | -324.572398  |  51.657585   |  51.657302   |   0.003314   |   0.019358   |
|     215      |  -1.076300   | -324.607705  |  51.663205   |  51.662921   |   0.003316   |   0.019356   |
|     216      |  -1.076300   |  324.607705  |  51.663205   |  51.662921   |   0.003316   |   0.019356   |
|     217      |  -1.078724   |  320.140186  |  50.952182   |  50.951893   |   0.003370   |   0.019626   |
|     218      |  -1.078724   | -320.140186  |  50.952182   |  50.951893   |   0.003370   |   0.019626   |
|     219      |  -1.078925   |  319.933158  |  50.919233   |  50.918944   |   0.003372   |   0.019639   |
|     220      |  -1.078925   | -319.933158  |  50.919233   |  50.918944   |   0.003372   |   0.019639   |
|     221      |  -1.080029   |  309.288686  |  49.225123   |  49.224823   |   0.003492   |   0.020315   |
|     222      |  -1.080029   | -309.288686  |  49.225123   |  49.224823   |   0.003492   |   0.020315   |
|     223      |  -1.080630   |  309.618139  |  49.277557   |  49.277257   |   0.003490   |   0.020293   |
|     224      |  -1.080630   | -309.618139  |  49.277557   |  49.277257   |   0.003490   |   0.020293   |
|     225      |  -1.080975   |  309.794320  |  49.305598   |  49.305297   |   0.003489   |   0.020282   |
|     226      |  -1.080975   | -309.794320  |  49.305598   |  49.305297   |   0.003489   |   0.020282   |
|     227      |  -1.081038   |  309.828767  |  49.311080   |  49.310780   |   0.003489   |   0.020280   |
|     228      |  -1.081038   | -309.828767  |  49.311080   |  49.310780   |   0.003489   |   0.020280   |
|     229      |  -1.082433   |  310.602445  |  49.434215   |  49.433914   |   0.003485   |   0.020229   |
|     230      |  -1.082433   | -310.602445  |  49.434215   |  49.433914   |   0.003485   |   0.020229   |
|     231      |  -1.084088   |  322.662762  |  51.353663   |  51.353373   |   0.003360   |   0.019473   |
|     232      |  -1.084088   | -322.662762  |  51.353663   |  51.353373   |   0.003360   |   0.019473   |
|     233      |  -1.084503   | -322.669036  |  51.354662   |  51.354372   |   0.003361   |   0.019473   |
|     234      |  -1.084503   |  322.669036  |  51.354662   |  51.354372   |   0.003361   |   0.019473   |
|     235      |  -1.085005   | -319.745514  |  50.889372   |  50.889079   |   0.003393   |   0.019651   |
|     236      |  -1.085005   |  319.745514  |  50.889372   |  50.889079   |   0.003393   |   0.019651   |
|     237      |  -1.085145   |  319.750916  |  50.890232   |  50.889939   |   0.003394   |   0.019650   |
|     238      |  -1.085145   | -319.750916  |  50.890232   |  50.889939   |   0.003394   |   0.019650   |
|     239      |  -1.086265   | -329.094966  |  52.377376   |  52.377091   |   0.003301   |   0.019092   |
|     240      |  -1.086265   |  329.094966  |  52.377376   |  52.377091   |   0.003301   |   0.019092   |
|     241      |  -1.086372   | -326.932381  |  52.033192   |  52.032904   |   0.003323   |   0.019219   |
|     242      |  -1.086372   |  326.932381  |  52.033192   |  52.032904   |   0.003323   |   0.019219   |
|     243      |  -1.086417   |  329.063936  |  52.372437   |  52.372152   |   0.003302   |   0.019094   |
|     244      |  -1.086417   | -329.063936  |  52.372437   |  52.372152   |   0.003302   |   0.019094   |
|     245      |  -1.087051   |  313.245575  |  49.854882   |  49.854582   |   0.003470   |   0.020058   |
|     246      |  -1.087051   | -313.245575  |  49.854882   |  49.854582   |   0.003470   |   0.020058   |
|     247      |  -1.087414   |  313.457338  |  49.888585   |  49.888285   |   0.003469   |   0.020045   |
|     248      |  -1.087414   | -313.457338  |  49.888585   |  49.888285   |   0.003469   |   0.020045   |
|     249      |  -1.087499   |  313.508013  |  49.896650   |  49.896350   |   0.003469   |   0.020042   |
|     250      |  -1.087499   | -313.508013  |  49.896650   |  49.896350   |   0.003469   |   0.020042   |
|     251      |  -1.087543   |  313.538425  |  49.901490   |  49.901190   |   0.003469   |   0.020040   |
|     252      |  -1.087543   | -313.538425  |  49.901490   |  49.901190   |   0.003469   |   0.020040   |
|     253      |  -1.087735   |  326.918220  |  52.030939   |  52.030651   |   0.003327   |   0.019219   |
|     254      |  -1.087735   | -326.918220  |  52.030939   |  52.030651   |   0.003327   |   0.019219   |
|     255      |  -1.089451   |  314.692046  |  50.085095   |  50.084795   |   0.003462   |   0.019966   |
|     256      |  -1.089451   | -314.692046  |  50.085095   |  50.084795   |   0.003462   |   0.019966   |
|     257      |  -1.089795   | -330.845038  |  52.655909   |  52.655623   |   0.003294   |   0.018991   |
|     258      |  -1.089795   |  330.845038  |  52.655909   |  52.655623   |   0.003294   |   0.018991   |
|     259      |  -1.091434   | -330.806905  |  52.649841   |  52.649554   |   0.003299   |   0.018994   |
|     260      |  -1.091434   |  330.806905  |  52.649841   |  52.649554   |   0.003299   |   0.018994   |
|     261      |  -1.091577   |  323.712470  |  51.520733   |  51.520440   |   0.003372   |   0.019410   |
|     262      |  -1.091577   | -323.712470  |  51.520733   |  51.520440   |   0.003372   |   0.019410   |
|     263      |  -1.091720   | -327.088590  |  52.058056   |  52.057766   |   0.003338   |   0.019209   |
|     264      |  -1.091720   |  327.088590  |  52.058056   |  52.057766   |   0.003338   |   0.019209   |
|     265      |  -1.091742   | -323.846011  |  51.541986   |  51.541693   |   0.003371   |   0.019402   |
|     266      |  -1.091742   |  323.846011  |  51.541986   |  51.541693   |   0.003371   |   0.019402   |
|     267      |  -1.092874   |  327.210801  |  52.077507   |  52.077216   |   0.003340   |   0.019202   |
|     268      |  -1.092874   | -327.210801  |  52.077507   |  52.077216   |   0.003340   |   0.019202   |
|     269      |  -1.092906   | -316.871195  |  50.431917   |  50.431617   |   0.003449   |   0.019829   |
|     270      |  -1.092906   |  316.871195  |  50.431917   |  50.431617   |   0.003449   |   0.019829   |
|     271      |  -1.092933   |  316.892539  |  50.435314   |  50.435014   |   0.003449   |   0.019827   |
|     272      |  -1.092933   | -316.892539  |  50.435314   |  50.435014   |   0.003449   |   0.019827   |
|     273      |  -1.092962   |  316.907185  |  50.437645   |  50.437345   |   0.003449   |   0.019827   |
|     274      |  -1.092962   | -316.907185  |  50.437645   |  50.437345   |   0.003449   |   0.019827   |
|     275      |  -1.092985   | -316.926030  |  50.440644   |  50.440344   |   0.003449   |   0.019825   |
|     276      |  -1.092985   |  316.926030  |  50.440644   |  50.440344   |   0.003449   |   0.019825   |
|     277      |  -1.093283   | -332.332221  |  52.892602   |  52.892316   |   0.003290   |   0.018906   |
|     278      |  -1.093283   |  332.332221  |  52.892602   |  52.892316   |   0.003290   |   0.018906   |
|     279      |  -1.093458   |  332.343157  |  52.894343   |  52.894056   |   0.003290   |   0.018906   |
|     280      |  -1.093458   | -332.343157  |  52.894343   |  52.894056   |   0.003290   |   0.018906   |
|     281      |  -1.094656   |  325.174138  |  51.753365   |  51.753071   |   0.003366   |   0.019323   |
|     282      |  -1.094656   | -325.174138  |  51.753365   |  51.753071   |   0.003366   |   0.019323   |
|     283      |  -1.095311   |  325.124568  |  51.745476   |  51.745182   |   0.003369   |   0.019325   |
|     284      |  -1.095311   | -325.124568  |  51.745476   |  51.745182   |   0.003369   |   0.019325   |
|     285      |  -1.096829   | -332.066508  |  52.850314   |  52.850026   |   0.003303   |   0.018921   |
|     286      |  -1.096829   |  332.066508  |  52.850314   |  52.850026   |   0.003303   |   0.018921   |
|     287      |  -1.097490   | -319.989534  |  50.928216   |  50.927916   |   0.003430   |   0.019636   |
|     288      |  -1.097490   |  319.989534  |  50.928216   |  50.927916   |   0.003430   |   0.019636   |
|     289      |  -1.097493   |  319.994348  |  50.928982   |  50.928682   |   0.003430   |   0.019635   |
|     290      |  -1.097493   | -319.994348  |  50.928982   |  50.928682   |   0.003430   |   0.019635   |
|     291      |  -1.097519   | -320.011922  |  50.931779   |  50.931479   |   0.003430   |   0.019634   |
|     292      |  -1.097519   |  320.011922  |  50.931779   |  50.931479   |   0.003430   |   0.019634   |
|     293      |  -1.097543   | -320.026563  |  50.934109   |  50.933809   |   0.003430   |   0.019633   |
|     294      |  -1.097543   |  320.026563  |  50.934109   |  50.933809   |   0.003430   |   0.019633   |
|     295      |  -1.098669   | -331.385423  |  52.741918   |  52.741628   |   0.003315   |   0.018960   |
|     296      |  -1.098669   |  331.385423  |  52.741918   |  52.741628   |   0.003315   |   0.018960   |
|     297      |  -1.100859   | -326.436651  |  51.954302   |  51.954007   |   0.003372   |   0.019248   |
|     298      |  -1.100859   |  326.436651  |  51.954302   |  51.954007   |   0.003372   |   0.019248   |
|     299      |  -1.101053   | -326.436812  |  51.954328   |  51.954032   |   0.003373   |   0.019248   |
|     300      |  -1.101053   |  326.436812  |  51.954328   |  51.954032   |   0.003373   |   0.019248   |
|     301      |  -1.101292   |  322.822286  |  51.379062   |  51.378763   |   0.003411   |   0.019463   |
|     302      |  -1.101292   | -322.822286  |  51.379062   |  51.378763   |   0.003411   |   0.019463   |
|     303      |  -1.101293   |  322.823898  |  51.379318   |  51.379019   |   0.003411   |   0.019463   |
|     304      |  -1.101293   | -322.823898  |  51.379318   |  51.379019   |   0.003411   |   0.019463   |
|     305      |  -1.101309   |  322.834412  |  51.380991   |  51.380692   |   0.003411   |   0.019463   |
|     306      |  -1.101309   | -322.834412  |  51.380991   |  51.380692   |   0.003411   |   0.019463   |
|     307      |  -1.101331   |  322.849724  |  51.383428   |  51.383129   |   0.003411   |   0.019462   |
|     308      |  -1.101331   | -322.849724  |  51.383428   |  51.383129   |   0.003411   |   0.019462   |
|     309      |  -1.102161   | -330.407444  |  52.586271   |  52.585978   |   0.003336   |   0.019016   |
|     310      |  -1.102161   |  330.407444  |  52.586271   |  52.585978   |   0.003336   |   0.019016   |
|     311      |  -1.102206   | -328.348838  |  52.258635   |  52.258341   |   0.003357   |   0.019136   |
|     312      |  -1.102206   |  328.348838  |  52.258635   |  52.258341   |   0.003357   |   0.019136   |
|     313      |  -1.102281   | -328.322944  |  52.254514   |  52.254220   |   0.003357   |   0.019137   |
|     314      |  -1.102281   |  328.322944  |  52.254514   |  52.254220   |   0.003357   |   0.019137   |
|     315      |  -1.103460   |  330.498141  |  52.600706   |  52.600413   |   0.003339   |   0.019011   |
|     316      |  -1.103460   | -330.498141  |  52.600706   |  52.600413   |   0.003339   |   0.019011   |
|     317      |  -1.104404   | -325.357719  |  51.782588   |  51.782289   |   0.003394   |   0.019312   |
|     318      |  -1.104404   |  325.357719  |  51.782588   |  51.782289   |   0.003394   |   0.019312   |
|     319      |  -1.104408   | -325.362658  |  51.783374   |  51.783075   |   0.003394   |   0.019311   |
|     320      |  -1.104408   |  325.362658  |  51.783374   |  51.783075   |   0.003394   |   0.019311   |
|     321      |  -1.104432   |  325.380976  |  51.786289   |  51.785991   |   0.003394   |   0.019310   |
|     322      |  -1.104432   | -325.380976  |  51.786289   |  51.785991   |   0.003394   |   0.019310   |
|     323      |  -1.104447   | -325.392512  |  51.788125   |  51.787827   |   0.003394   |   0.019310   |
|     324      |  -1.104447   |  325.392512  |  51.788125   |  51.787827   |   0.003394   |   0.019310   |
|     325      |  -1.104643   |  329.605095  |  52.458575   |  52.458280   |   0.003351   |   0.019063   |
|     326      |  -1.104643   | -329.605095  |  52.458575   |  52.458280   |   0.003351   |   0.019063   |
|     327      |  -1.104721   |  329.588858  |  52.455991   |  52.455696   |   0.003352   |   0.019064   |
|     328      |  -1.104721   | -329.588858  |  52.455991   |  52.455696   |   0.003352   |   0.019064   |
|     329      |  -1.106744   | -327.432658  |  52.112824   |  52.112526   |   0.003380   |   0.019189   |
|     330      |  -1.106744   |  327.432658  |  52.112824   |  52.112526   |   0.003380   |   0.019189   |
|     331      |  -1.106932   |  327.609429  |  52.140958   |  52.140660   |   0.003379   |   0.019179   |
|     332      |  -1.106932   | -327.609429  |  52.140958   |  52.140660   |   0.003379   |   0.019179   |
|     333      |  -1.106956   | -327.628565  |  52.144003   |  52.143706   |   0.003379   |   0.019178   |
|     334      |  -1.106956   |  327.628565  |  52.144003   |  52.143706   |   0.003379   |   0.019178   |
|     335      |  -1.106973   |  327.644199  |  52.146491   |  52.146194   |   0.003379   |   0.019177   |
|     336      |  -1.106973   | -327.644199  |  52.146491   |  52.146194   |   0.003379   |   0.019177   |
|     337      |  -1.107211   | -327.869981  |  52.182426   |  52.182128   |   0.003377   |   0.019164   |
|     338      |  -1.107211   |  327.869981  |  52.182426   |  52.182128   |   0.003377   |   0.019164   |
|     339      |  -1.107565   |  331.532240  |  52.765289   |  52.764995   |   0.003341   |   0.018952   |
|     340      |  -1.107565   | -331.532240  |  52.765289   |  52.764995   |   0.003341   |   0.018952   |
|     341      |  -1.107916   | -333.461804  |  53.072387   |  53.072094   |   0.003322   |   0.018842   |
|     342      |  -1.107916   |  333.461804  |  53.072387   |  53.072094   |   0.003322   |   0.018842   |
|     343      |  -1.108211   |  331.513313  |  52.762277   |  52.761983   |   0.003343   |   0.018953   |
|     344      |  -1.108211   | -331.513313  |  52.762277   |  52.761983   |   0.003343   |   0.018953   |
|     345      |  -1.108216   | -333.455247  |  53.071344   |  53.071051   |   0.003323   |   0.018843   |
|     346      |  -1.108216   |  333.455247  |  53.071344   |  53.071051   |   0.003323   |   0.018843   |
|     347      |  -1.108440   |  329.055252  |  52.371067   |  52.370770   |   0.003369   |   0.019095   |
|     348      |  -1.108440   | -329.055252  |  52.371067   |  52.370770   |   0.003369   |   0.019095   |
|     349      |  -1.108951   |  329.564068  |  52.452047   |  52.451750   |   0.003365   |   0.019065   |
|     350      |  -1.108951   | -329.564068  |  52.452047   |  52.451750   |   0.003365   |   0.019065   |
|     351      |  -1.108969   |  329.582680  |  52.455010   |  52.454713   |   0.003365   |   0.019064   |
|     352      |  -1.108969   | -329.582680  |  52.455010   |  52.454713   |   0.003365   |   0.019064   |
|     353      |  -1.108985   |  329.604673  |  52.458510   |  52.458213   |   0.003365   |   0.019063   |
|     354      |  -1.108985   | -329.604673  |  52.458510   |  52.458213   |   0.003365   |   0.019063   |
|     355      |  -1.109008   |  329.624636  |  52.461687   |  52.461390   |   0.003364   |   0.019062   |
|     356      |  -1.109008   | -329.624636  |  52.461687   |  52.461390   |   0.003364   |   0.019062   |
|     357      |  -1.109656   | -334.561471  |  53.247405   |  53.247112   |   0.003317   |   0.018780   |
|     358      |  -1.109656   |  334.561471  |  53.247405   |  53.247112   |   0.003317   |   0.018780   |
|     359      |  -1.109672   | -334.545407  |  53.244848   |  53.244555   |   0.003317   |   0.018781   |
|     360      |  -1.109672   |  334.545407  |  53.244848   |  53.244555   |   0.003317   |   0.018781   |
|     361      |  -1.110193   | -333.282365  |  53.043830   |  53.043536   |   0.003331   |   0.018852   |
|     362      |  -1.110193   |  333.282365  |  53.043830   |  53.043536   |   0.003331   |   0.018852   |
|     363      |  -1.110333   | -331.008434  |  52.681925   |  52.681628   |   0.003354   |   0.018982   |
|     364      |  -1.110333   |  331.008434  |  52.681925   |  52.681628   |   0.003354   |   0.018982   |
|     365      |  -1.110341   |  331.018034  |  52.683453   |  52.683156   |   0.003354   |   0.018981   |
|     366      |  -1.110341   | -331.018034  |  52.683453   |  52.683156   |   0.003354   |   0.018981   |
|     367      |  -1.110385   | -333.294673  |  53.045789   |  53.045495   |   0.003332   |   0.018852   |
|     368      |  -1.110385   |  333.294673  |  53.045789   |  53.045495   |   0.003332   |   0.018852   |
|     369      |  -1.110518   |  331.208602  |  52.713783   |  52.713486   |   0.003353   |   0.018970   |
|     370      |  -1.110518   | -331.208602  |  52.713783   |  52.713486   |   0.003353   |   0.018970   |
|     371      |  -1.110520   |  331.214085  |  52.714655   |  52.714359   |   0.003353   |   0.018970   |
|     372      |  -1.110520   | -331.214085  |  52.714655   |  52.714359   |   0.003353   |   0.018970   |
|     373      |  -1.110649   |  331.351732  |  52.736562   |  52.736266   |   0.003352   |   0.018962   |
|     374      |  -1.110649   | -331.351732  |  52.736562   |  52.736266   |   0.003352   |   0.018962   |
|     375      |  -1.110652   | -331.363928  |  52.738503   |  52.738207   |   0.003352   |   0.018962   |
|     376      |  -1.110652   |  331.363928  |  52.738503   |  52.738207   |   0.003352   |   0.018962   |
|     377      |  -1.111317   | -332.101213  |  52.855846   |  52.855550   |   0.003346   |   0.018919   |
|     378      |  -1.111317   |  332.101213  |  52.855846   |  52.855550   |   0.003346   |   0.018919   |
|     379      |  -1.111358   | -332.145988  |  52.862972   |  52.862676   |   0.003346   |   0.018917   |
|     380      |  -1.111358   |  332.145988  |  52.862972   |  52.862676   |   0.003346   |   0.018917   |
|     381      |  -1.111730   | -332.575059  |  52.931260   |  52.930965   |   0.003343   |   0.018893   |
|     382      |  -1.111730   |  332.575059  |  52.931260   |  52.930965   |   0.003343   |   0.018893   |
|     383      |  -1.111730   |  332.577756  |  52.931690   |  52.931394   |   0.003343   |   0.018892   |
|     384      |  -1.111730   | -332.577756  |  52.931690   |  52.931394   |   0.003343   |   0.018892   |
|     385      |  -1.111733   | -332.582902  |  52.932509   |  52.932213   |   0.003343   |   0.018892   |
|     386      |  -1.111733   |  332.582902  |  52.932509   |  52.932213   |   0.003343   |   0.018892   |
|     387      |  -1.111733   |  332.581750  |  52.932325   |  52.932029   |   0.003343   |   0.018892   |
|     388      |  -1.111733   | -332.581750  |  52.932325   |  52.932029   |   0.003343   |   0.018892   |
|     389      |  -1.111895   | -335.183640  |  53.346427   |  53.346133   |   0.003317   |   0.018746   |
|     390      |  -1.111895   |  335.183640  |  53.346427   |  53.346133   |   0.003317   |   0.018746   |
|     391      |  -1.111918   | -335.185684  |  53.346752   |  53.346459   |   0.003317   |   0.018745   |
|     392      |  -1.111918   |  335.185684  |  53.346752   |  53.346459   |   0.003317   |   0.018745   |
|     393      |  -1.111977   | -337.042524  |  53.642276   |  53.641984   |   0.003299   |   0.018642   |
|     394      |  -1.111977   |  337.042524  |  53.642276   |  53.641984   |   0.003299   |   0.018642   |
|     395      |  -1.111984   |  337.038066  |  53.641566   |  53.641274   |   0.003299   |   0.018642   |
|     396      |  -1.111984   | -337.038066  |  53.641566   |  53.641274   |   0.003299   |   0.018642   |
|     397      |  -1.113433   |  336.128317  |  53.496777   |  53.496483   |   0.003313   |   0.018693   |
|     398      |  -1.113433   | -336.128317  |  53.496777   |  53.496483   |   0.003313   |   0.018693   |
|     399      |  -1.113437   |  336.131297  |  53.497251   |  53.496957   |   0.003312   |   0.018693   |
|     400      |  -1.113437   | -336.131297  |  53.497251   |  53.496957   |   0.003312   |   0.018693   |
|     401      |  -1.113648   | -338.105396  |  53.811437   |  53.811145   |   0.003294   |   0.018584   |
|     402      |  -1.113648   |  338.105396  |  53.811437   |  53.811145   |   0.003294   |   0.018584   |
|     403      |  -1.113653   | -338.102774  |  53.811020   |  53.810728   |   0.003294   |   0.018584   |
|     404      |  -1.113653   |  338.102774  |  53.811020   |  53.810728   |   0.003294   |   0.018584   |
|     405      |  -1.113881   |  335.273046  |  53.360657   |  53.360363   |   0.003322   |   0.018741   |
|     406      |  -1.113881   | -335.273046  |  53.360657   |  53.360363   |   0.003322   |   0.018741   |
|     407      |  -1.114271   |  335.810669  |  53.446222   |  53.445928   |   0.003318   |   0.018710   |
|     408      |  -1.114271   | -335.810669  |  53.446222   |  53.445928   |   0.003318   |   0.018710   |
|     409      |  -1.114682   | -337.420697  |  53.702465   |  53.702172   |   0.003304   |   0.018621   |
|     410      |  -1.114682   |  337.420697  |  53.702465   |  53.702172   |   0.003304   |   0.018621   |
|     411      |  -1.114685   | -337.421129  |  53.702534   |  53.702241   |   0.003304   |   0.018621   |
|     412      |  -1.114685   |  337.421129  |  53.702534   |  53.702241   |   0.003304   |   0.018621   |
|     413      |  -1.114745   | -339.534726  |  54.038921   |  54.038630   |   0.003283   |   0.018505   |
|     414      |  -1.114745   |  339.534726  |  54.038921   |  54.038630   |   0.003283   |   0.018505   |
|     415      |  -1.114754   |  339.527234  |  54.037729   |  54.037438   |   0.003283   |   0.018506   |
|     416      |  -1.114754   | -339.527234  |  54.037729   |  54.037438   |   0.003283   |   0.018506   |
|     417      |  -1.115312   |  74.207184   |  11.811774   |  11.810440   |   0.015028   |   0.084671   |
|     418      |  -1.115312   |  -74.207184  |  11.811774   |  11.810440   |   0.015028   |   0.084671   |
|     419      |  -1.115588   |  338.574851  |  53.886154   |  53.885861   |   0.003295   |   0.018558   |
|     420      |  -1.115588   | -338.574851  |  53.886154   |  53.885861   |   0.003295   |   0.018558   |
|     421      |  -1.115590   |  338.573805  |  53.885987   |  53.885695   |   0.003295   |   0.018558   |
|     422      |  -1.115590   | -338.573805  |  53.885987   |  53.885695   |   0.003295   |   0.018558   |
|     423      |  -1.115783   | -340.920059  |  54.259403   |  54.259113   |   0.003273   |   0.018430   |
|     424      |  -1.115783   |  340.920059  |  54.259403   |  54.259113   |   0.003273   |   0.018430   |
|     425      |  -1.115870   |  341.161924  |  54.297897   |  54.297607   |   0.003271   |   0.018417   |
|     426      |  -1.115870   | -341.161924  |  54.297897   |  54.297607   |   0.003271   |   0.018417   |
|     427      |  -1.115916   |  340.879701  |  54.252980   |  54.252689   |   0.003274   |   0.018432   |
|     428      |  -1.115916   | -340.879701  |  54.252980   |  54.252689   |   0.003274   |   0.018432   |
|     429      |  -1.116022   | -341.105628  |  54.288937   |  54.288647   |   0.003272   |   0.018420   |
|     430      |  -1.116022   |  341.105628  |  54.288937   |  54.288647   |   0.003272   |   0.018420   |
|     431      |  -1.116122   |  339.695422  |  54.064497   |  54.064206   |   0.003286   |   0.018497   |
|     432      |  -1.116122   | -339.695422  |  54.064497   |  54.064206   |   0.003286   |   0.018497   |
|     433      |  -1.116123   |  339.694299  |  54.064319   |  54.064027   |   0.003286   |   0.018497   |
|     434      |  -1.116123   | -339.694299  |  54.064319   |  54.064027   |   0.003286   |   0.018497   |
|     435      |  -1.116483   | -339.281941  |  53.998690   |  53.998398   |   0.003291   |   0.018519   |
|     436      |  -1.116483   |  339.281941  |  53.998690   |  53.998398   |   0.003291   |   0.018519   |
|     437      |  -1.116592   | -340.579316  |  54.205173   |  54.204882   |   0.003278   |   0.018449   |
|     438      |  -1.116592   |  340.579316  |  54.205173   |  54.204882   |   0.003278   |   0.018449   |
|     439      |  -1.116631   | -339.550217  |  54.041388   |  54.041095   |   0.003289   |   0.018504   |
|     440      |  -1.116631   |  339.550217  |  54.041388   |  54.041095   |   0.003289   |   0.018504   |
|     441      |  -1.116657   | -340.591235  |  54.207070   |  54.206779   |   0.003279   |   0.018448   |
|     442      |  -1.116657   |  340.591235  |  54.207070   |  54.206779   |   0.003279   |   0.018448   |
|     443      |  -1.117075   |  342.131792  |  54.452256   |  54.451966   |   0.003265   |   0.018365   |
|     444      |  -1.117075   | -342.131792  |  54.452256   |  54.451966   |   0.003265   |   0.018365   |
|     445      |  -1.117094   |  342.130820  |  54.452101   |  54.451811   |   0.003265   |   0.018365   |
|     446      |  -1.117094   | -342.130820  |  54.452101   |  54.451811   |   0.003265   |   0.018365   |
|     447      |  -1.117293   | -341.489178  |  54.349982   |  54.349691   |   0.003272   |   0.018399   |
|     448      |  -1.117293   |  341.489178  |  54.349982   |  54.349691   |   0.003272   |   0.018399   |
|     449      |  -1.117322   |  341.487729  |  54.349751   |  54.349460   |   0.003272   |   0.018399   |
|     450      |  -1.117322   | -341.487729  |  54.349751   |  54.349460   |   0.003272   |   0.018399   |
|     451      |  -1.117513   | -342.198690  |  54.462903   |  54.462613   |   0.003266   |   0.018361   |
|     452      |  -1.117513   |  342.198690  |  54.462903   |  54.462613   |   0.003266   |   0.018361   |
|     453      |  -1.117532   | -342.200560  |  54.463201   |  54.462911   |   0.003266   |   0.018361   |
|     454      |  -1.117532   |  342.200560  |  54.463201   |  54.462911   |   0.003266   |   0.018361   |
|     455      |  -1.117646   |  343.037593  |  54.596418   |  54.596129   |   0.003258   |   0.018316   |
|     456      |  -1.117646   | -343.037593  |  54.596418   |  54.596129   |   0.003258   |   0.018316   |
|     457      |  -1.117646   | -343.037592  |  54.596418   |  54.596128   |   0.003258   |   0.018316   |
|     458      |  -1.117646   |  343.037592  |  54.596418   |  54.596128   |   0.003258   |   0.018316   |
|     459      |  -1.117777   | -341.853412  |  54.407951   |  54.407660   |   0.003270   |   0.018380   |
|     460      |  -1.117777   |  341.853412  |  54.407951   |  54.407660   |   0.003270   |   0.018380   |
|     461      |  -1.117846   | -342.009266  |  54.432756   |  54.432465   |   0.003268   |   0.018371   |
|     462      |  -1.117846   |  342.009266  |  54.432756   |  54.432465   |   0.003268   |   0.018371   |
|     463      |  -1.118011   | -342.479554  |  54.507604   |  54.507314   |   0.003264   |   0.018346   |
|     464      |  -1.118011   |  342.479554  |  54.507604   |  54.507314   |   0.003264   |   0.018346   |
|     465      |  -1.118029   | -342.507545  |  54.512059   |  54.511769   |   0.003264   |   0.018345   |
|     466      |  -1.118029   |  342.507545  |  54.512059   |  54.511769   |   0.003264   |   0.018345   |
|     467      |  -1.118087   | -343.710417  |  54.703501   |  54.703212   |   0.003253   |   0.018280   |
|     468      |  -1.118087   |  343.710417  |  54.703501   |  54.703212   |   0.003253   |   0.018280   |
|     469      |  -1.118087   |  343.710417  |  54.703501   |  54.703212   |   0.003253   |   0.018280   |
|     470      |  -1.118087   | -343.710417  |  54.703501   |  54.703212   |   0.003253   |   0.018280   |
|     471      |  -1.118088   | -342.821813  |  54.562076   |  54.561786   |   0.003261   |   0.018328   |
|     472      |  -1.118088   |  342.821813  |  54.562076   |  54.561786   |   0.003261   |   0.018328   |
|     473      |  -1.118088   |  342.822024  |  54.562110   |  54.561820   |   0.003261   |   0.018328   |
|     474      |  -1.118088   | -342.822024  |  54.562110   |  54.561820   |   0.003261   |   0.018328   |
|     475      |  -1.118409   | -344.494693  |  54.828322   |  54.828033   |   0.003247   |   0.018239   |
|     476      |  -1.118409   |  344.494693  |  54.828322   |  54.828033   |   0.003247   |   0.018239   |
|     477      |  -1.118409   | -344.494693  |  54.828322   |  54.828033   |   0.003247   |   0.018239   |
|     478      |  -1.118409   |  344.494693  |  54.828322   |  54.828033   |   0.003247   |   0.018239   |
|     479      |  -1.118504   | -343.644764  |  54.693053   |  54.692763   |   0.003255   |   0.018284   |
|     480      |  -1.118504   |  343.644764  |  54.693053   |  54.692763   |   0.003255   |   0.018284   |
|     481      |  -1.118539   | -343.740135  |  54.708231   |  54.707942   |   0.003254   |   0.018279   |
|     482      |  -1.118539   |  343.740135  |  54.708231   |  54.707942   |   0.003254   |   0.018279   |
|     483      |  -1.118797   |  345.352018  |  54.964769   |  54.964481   |   0.003240   |   0.018194   |
|     484      |  -1.118797   | -345.352018  |  54.964769   |  54.964481   |   0.003240   |   0.018194   |
|     485      |  -1.118797   |  345.352018  |  54.964769   |  54.964481   |   0.003240   |   0.018194   |
|     486      |  -1.118797   | -345.352018  |  54.964769   |  54.964481   |   0.003240   |   0.018194   |
|     487      |  -1.118942   | -344.942716  |  54.899627   |  54.899338   |   0.003244   |   0.018215   |
|     488      |  -1.118942   |  344.942716  |  54.899627   |  54.899338   |   0.003244   |   0.018215   |
|     489      |  -1.118960   | -345.001926  |  54.909051   |  54.908762   |   0.003243   |   0.018212   |
|     490      |  -1.118960   |  345.001926  |  54.909051   |  54.908762   |   0.003243   |   0.018212   |
|     491      |  -1.119142   |  346.233999  |  55.105140   |  55.104852   |   0.003232   |   0.018147   |
|     492      |  -1.119142   | -346.233999  |  55.105140   |  55.104852   |   0.003232   |   0.018147   |
|     493      |  -1.119142   |  346.233999  |  55.105140   |  55.104852   |   0.003232   |   0.018147   |
|     494      |  -1.119142   | -346.233999  |  55.105140   |  55.104852   |   0.003232   |   0.018147   |
|     495      |  -1.119223   |  345.921418  |  55.055392   |  55.055104   |   0.003235   |   0.018164   |
|     496      |  -1.119223   | -345.921418  |  55.055392   |  55.055104   |   0.003235   |   0.018164   |
|     497      |  -1.119232   |  345.957711  |  55.061168   |  55.060880   |   0.003235   |   0.018162   |
|     498      |  -1.119232   | -345.957711  |  55.061168   |  55.060880   |   0.003235   |   0.018162   |
|     499      |  -1.119414   | -346.692126  |  55.178053   |  55.177766   |   0.003229   |   0.018123   |
|     500      |  -1.119414   |  346.692126  |  55.178053   |  55.177766   |   0.003229   |   0.018123   |
|     501      |  -1.119419   | -346.714128  |  55.181555   |  55.181267   |   0.003229   |   0.018122   |
|     502      |  -1.119419   |  346.714128  |  55.181555   |  55.181267   |   0.003229   |   0.018122   |
|     503      |  -1.119436   | -347.160911  |  55.252662   |  55.252375   |   0.003225   |   0.018099   |
|     504      |  -1.119436   |  347.160911  |  55.252662   |  55.252375   |   0.003225   |   0.018099   |
|     505      |  -1.119436   | -347.160911  |  55.252662   |  55.252375   |   0.003225   |   0.018099   |
|     506      |  -1.119436   |  347.160911  |  55.252662   |  55.252375   |   0.003225   |   0.018099   |
|     507      |  -1.119550   | -347.324058  |  55.278628   |  55.278341   |   0.003223   |   0.018090   |
|     508      |  -1.119550   |  347.324058  |  55.278628   |  55.278341   |   0.003223   |   0.018090   |
|     509      |  -1.119554   | -347.339241  |  55.281044   |  55.280757   |   0.003223   |   0.018089   |
|     510      |  -1.119554   |  347.339241  |  55.281044   |  55.280757   |   0.003223   |   0.018089   |
|     511      |  -1.119645   |  347.818682  |  55.357349   |  55.357063   |   0.003219   |   0.018065   |
|     512      |  -1.119645   | -347.818682  |  55.357349   |  55.357063   |   0.003219   |   0.018065   |
|     513      |  -1.119648   |  347.835778  |  55.360070   |  55.359783   |   0.003219   |   0.018064   |
|     514      |  -1.119648   | -347.835778  |  55.360070   |  55.359783   |   0.003219   |   0.018064   |
|     515      |  -1.119700   |  348.136761  |  55.407973   |  55.407686   |   0.003216   |   0.018048   |
|     516      |  -1.119700   | -348.136761  |  55.407973   |  55.407686   |   0.003216   |   0.018048   |
|     517      |  -1.119702   |  348.145161  |  55.409310   |  55.409023   |   0.003216   |   0.018048   |
|     518      |  -1.119702   | -348.145161  |  55.409310   |  55.409023   |   0.003216   |   0.018048   |
|     519      |  -1.119747   |  348.428886  |  55.454466   |  55.454180   |   0.003214   |   0.018033   |
|     520      |  -1.119747   | -348.428886  |  55.454466   |  55.454180   |   0.003214   |   0.018033   |
|     521      |  -1.119747   |  348.429776  |  55.454608   |  55.454321   |   0.003214   |   0.018033   |
|     522      |  -1.119747   | -348.429776  |  55.454608   |  55.454321   |   0.003214   |   0.018033   |
|     523      |  -1.119798   | -348.784816  |  55.511114   |  55.510828   |   0.003211   |   0.018015   |
|     524      |  -1.119798   |  348.784816  |  55.511114   |  55.510828   |   0.003211   |   0.018015   |
|     525      |  -1.119799   |  348.788549  |  55.511708   |  55.511422   |   0.003211   |   0.018014   |
|     526      |  -1.119799   | -348.788549  |  55.511708   |  55.511422   |   0.003211   |   0.018014   |
|     527      |  -1.119838   |  349.087485  |  55.559285   |  55.558999   |   0.003208   |   0.017999   |
|     528      |  -1.119838   | -349.087485  |  55.559285   |  55.558999   |   0.003208   |   0.017999   |
|     529      |  -1.119838   |  349.088940  |  55.559516   |  55.559230   |   0.003208   |   0.017999   |
|     530      |  -1.119838   | -349.088940  |  55.559516   |  55.559230   |   0.003208   |   0.017999   |
|     531      |  -1.119864   |  349.305750  |  55.594023   |  55.593737   |   0.003206   |   0.017988   |
|     532      |  -1.119864   | -349.305750  |  55.594023   |  55.593737   |   0.003206   |   0.017988   |
|     533      |  -1.119864   |  349.306973  |  55.594217   |  55.593931   |   0.003206   |   0.017988   |
|     534      |  -1.119864   | -349.306973  |  55.594217   |  55.593931   |   0.003206   |   0.017988   |
|     535      |  -1.119888   | -349.526188  |  55.629106   |  55.628821   |   0.003204   |   0.017976   |
|     536      |  -1.119888   |  349.526188  |  55.629106   |  55.628821   |   0.003204   |   0.017976   |
|     537      |  -1.119888   | -349.527157  |  55.629260   |  55.628975   |   0.003204   |   0.017976   |
|     538      |  -1.119888   |  349.527157  |  55.629260   |  55.628975   |   0.003204   |   0.017976   |
|     539      |  -1.119908   | -349.726171  |  55.660934   |  55.660649   |   0.003202   |   0.017966   |
|     540      |  -1.119908   |  349.726171  |  55.660934   |  55.660649   |   0.003202   |   0.017966   |
|     541      |  -1.119908   | -349.726960  |  55.661060   |  55.660774   |   0.003202   |   0.017966   |
|     542      |  -1.119908   |  349.726960  |  55.661060   |  55.660774   |   0.003202   |   0.017966   |
|     543      |  -1.119924   |  349.905629  |  55.689496   |  55.689211   |   0.003201   |   0.017957   |
|     544      |  -1.119924   | -349.905629  |  55.689496   |  55.689211   |   0.003201   |   0.017957   |
|     545      |  -1.119924   | -349.906343  |  55.689609   |  55.689324   |   0.003201   |   0.017957   |
|     546      |  -1.119924   |  349.906343  |  55.689609   |  55.689324   |   0.003201   |   0.017957   |
|     547      |  -1.119938   |  350.066095  |  55.715034   |  55.714749   |   0.003199   |   0.017949   |
|     548      |  -1.119938   | -350.066095  |  55.715034   |  55.714749   |   0.003199   |   0.017949   |
|     549      |  -1.119938   |  350.067052  |  55.715187   |  55.714902   |   0.003199   |   0.017949   |
|     550      |  -1.119938   | -350.067052  |  55.715187   |  55.714902   |   0.003199   |   0.017949   |
|     551      |  -1.119946   | -350.175587  |  55.732461   |  55.732176   |   0.003198   |   0.017943   |
|     552      |  -1.119946   |  350.175587  |  55.732461   |  55.732176   |   0.003198   |   0.017943   |
|     553      |  -1.119947   |  350.185229  |  55.733995   |  55.733710   |   0.003198   |   0.017942   |
|     554      |  -1.119947   | -350.185229  |  55.733995   |  55.733710   |   0.003198   |   0.017942   |
|     555      |  -1.119950   | -350.224672  |  55.740273   |  55.739988   |   0.003198   |   0.017940   |
|     556      |  -1.119950   |  350.224672  |  55.740273   |  55.739988   |   0.003198   |   0.017940   |
|     557      |  -1.119950   | -350.225655  |  55.740429   |  55.740144   |   0.003198   |   0.017940   |
|     558      |  -1.119950   |  350.225655  |  55.740429   |  55.740144   |   0.003198   |   0.017940   |
|     559      |  -1.119959   | -350.360870  |  55.761949   |  55.761664   |   0.003197   |   0.017933   |
|     560      |  -1.119959   |  350.360870  |  55.761949   |  55.761664   |   0.003197   |   0.017933   |
|     561      |  -1.119959   | -350.360874  |  55.761950   |  55.761665   |   0.003197   |   0.017933   |
|     562      |  -1.119959   |  350.360874  |  55.761950   |  55.761665   |   0.003197   |   0.017933   |
|     563      |  -1.119968   | -350.498253  |  55.783814   |  55.783530   |   0.003195   |   0.017926   |
|     564      |  -1.119968   |  350.498253  |  55.783814   |  55.783530   |   0.003195   |   0.017926   |
|     565      |  -1.119968   | -350.498253  |  55.783814   |  55.783530   |   0.003195   |   0.017926   |
|     566      |  -1.119968   |  350.498253  |  55.783814   |  55.783530   |   0.003195   |   0.017926   |
|     567      |  -1.202238   |  215.725167  |  34.334260   |  34.333727   |   0.005573   |   0.029126   |
|     568      |  -1.202238   | -215.725167  |  34.334260   |  34.333727   |   0.005573   |   0.029126   |
|     569      |  -1.211213   |  218.125851  |  34.716343   |  34.715807   |   0.005553   |   0.028805   |
|     570      |  -1.211213   | -218.125851  |  34.716343   |  34.715807   |   0.005553   |   0.028805   |
|     571      |  -1.314901   |  27.808792   |   4.430852   |   4.425907   |   0.047231   |   0.225942   |
|     572      |  -1.314901   |  -27.808792  |   4.430852   |   4.425907   |   0.047231   |   0.225942   |
|     573      |  -1.331926   | -193.853508  |  30.853472   |  30.852744   |   0.006871   |   0.032412   |
|     574      |  -1.331926   |  193.853508  |  30.853472   |  30.852744   |   0.006871   |   0.032412   |
|     575      |  -1.387904   | -100.607607  |  16.013722   |  16.012198   |   0.013794   |   0.062452   |
|     576      |  -1.387904   |  100.607607  |  16.013722   |  16.012198   |   0.013794   |   0.062452   |
|     577      |  -1.429024   |  181.697099  |  28.918886   |  28.917992   |   0.007865   |   0.034581   |
|     578      |  -1.429024   | -181.697099  |  28.918886   |  28.917992   |   0.007865   |   0.034581   |
|     579      |  -1.467702   |  -29.975101  |   4.776401   |   4.770685   |   0.048905   |   0.209613   |
|     580      |  -1.467702   |  29.975101   |   4.776401   |   4.770685   |   0.048905   |   0.209613   |
|     581      |  -1.475946   | -189.568142  |  30.171621   |  30.170707   |   0.007786   |   0.033145   |
|     582      |  -1.475946   |  189.568142  |  30.171621   |  30.170707   |   0.007786   |   0.033145   |
|     583      |  -1.552107   |  121.192652  |  19.289991   |  19.288410   |   0.012806   |   0.051845   |
|     584      |  -1.552107   | -121.192652  |  19.289991   |  19.288410   |   0.012806   |   0.051845   |
|     585      |  -1.569138   |  147.912741  |  23.542368   |  23.541044   |   0.010608   |   0.042479   |
|     586      |  -1.569138   | -147.912741  |  23.542368   |  23.541044   |   0.010608   |   0.042479   |
|     587      |  -1.679571   | -166.822478  |  26.551968   |  26.550622   |   0.010068   |   0.037664   |
|     588      |  -1.679571   |  166.822478  |  26.551968   |  26.550622   |   0.010068   |   0.037664   |
|     589      |  -1.900781   |  146.675612  |  23.346109   |  23.344149   |   0.012958   |   0.042837   |
|     590      |  -1.900781   | -146.675612  |  23.346109   |  23.344149   |   0.012958   |   0.042837   |
|     591      |  -3.829164   |   6.037090   |   1.137807   |   0.960833   |   0.535618   |   1.040764   |
|     592      |  -3.829164   |  -6.037090   |   1.137807   |   0.960833   |   0.535618   |   1.040764   |
|     593      |  -10.569038  |  -2.319301   |   1.722140   |   0.369128   |   0.976758   |   2.709085   |
|     594      |  -10.569038  |   2.319301   |   1.722140   |   0.369128   |   0.976758   |   2.709085   |
|     595      |  -15.876819  |   0.420548   |   2.527760   |   0.066932   |   0.999649   |  14.940485   |
|     596      |  -15.876819  |  -0.420548   |   2.527760   |   0.066932   |   0.999649   |  14.940485   |
|     597      |  -22.629853  |   0.000000   |   3.601653   |   0.000000   |   1.000000   |     inf      |
|     598      |  -26.267735  |   0.000000   |   4.180640   |   0.000000   |   1.000000   |     inf      |
|     599      |  -29.470709  |   0.000000   |   4.690409   |   0.000000   |   1.000000   |     inf      |
|     600      |  -30.882640  |  -35.322709  |   7.467456   |   5.621784   |   0.658206   |   0.177879   |
|     601      |  -30.882640  |  35.322709   |   7.467456   |   5.621784   |   0.658206   |   0.177879   |
|     602      |  -32.639619  |   0.000000   |   5.194757   |   0.000000   |   1.000000   |     inf      |
|     603      |  -34.172137  |  34.458728   |   7.723753   |   5.484277   |   0.704148   |   0.182339   |
|     604      |  -34.172137  |  -34.458728  |   7.723753   |   5.484277   |   0.704148   |   0.182339   |
|     605      |  -35.603269  |   0.000000   |   5.666436   |   0.000000   |   1.000000   |     inf      |
|     606      |  -36.439642  |  -71.349091  |  12.750825   |  11.355561   |   0.454837   |   0.088063   |
|     607      |  -36.439642  |  71.349091   |  12.750825   |  11.355561   |   0.454837   |   0.088063   |
|     608      |  -37.441913  |  34.065477   |   8.056375   |   5.421689   |   0.739671   |   0.184444   |
|     609      |  -37.441913  |  -34.065477  |   8.056375   |   5.421689   |   0.739671   |   0.184444   |
|     610      |  -38.677028  |   0.000000   |   6.155640   |   0.000000   |   1.000000   |     inf      |
|     611      |  -39.517763  |  106.863529  |  18.133516   |  17.007859   |   0.346841   |   0.058796   |
|     612      |  -39.517763  | -106.863529  |  18.133516   |  17.007859   |   0.346841   |   0.058796   |
|     613      |  -40.027452  |  70.647916   |  12.923269   |  11.243965   |   0.492953   |   0.088937   |
|     614      |  -40.027452  |  -70.647916  |  12.923269   |  11.243965   |   0.492953   |   0.088937   |
|     615      |  -40.915687  |  -33.727014  |   8.439122   |   5.367821   |   0.771636   |   0.186295   |
|     616      |  -40.915687  |  33.727014   |   8.439122   |   5.367821   |   0.771636   |   0.186295   |
|     617      |  -41.445961  | -142.148833  |  23.565714   |  22.623689   |   0.279912   |   0.044201   |
|     618      |  -41.445961  |  142.148833  |  23.565714   |  22.623689   |   0.279912   |   0.044201   |
|     619      |  -41.867200  |   0.000000   |   6.663372   |   0.000000   |   1.000000   |     inf      |
|     620      |  -42.728119  | -177.201966  |  29.010864   |  28.202569   |   0.234408   |   0.035458   |
|     621      |  -42.728119  |  177.201966  |  29.010864   |  28.202569   |   0.234408   |   0.035458   |
|     622      |  -43.280388  | -106.316208  |  18.269108   |  16.920750   |   0.377046   |   0.059099   |
|     623      |  -43.280388  |  106.316208  |  18.269108   |  16.920750   |   0.377046   |   0.059099   |
|     624      |  -43.336124  |  70.371812   |  13.153375   |  11.200022   |   0.524364   |   0.089286   |
|     625      |  -43.336124  |  -70.371812  |  13.153375   |  11.200022   |   0.524364   |   0.089286   |
|     626      |  -43.703283  | -212.025014  |  34.454227   |  33.744829   |   0.201879   |   0.029634   |
|     627      |  -43.703283  |  212.025014  |  34.454227   |  33.744829   |   0.201879   |   0.029634   |
|     628      |  -44.464423  |  -33.642593  |   8.874096   |   5.354385   |   0.797460   |   0.186763   |
|     629      |  -44.464423  |  33.642593   |   8.874096   |   5.354385   |   0.797460   |   0.186763   |
|     630      |  -44.565889  |  246.761554  |  39.908680   |  39.273321   |   0.177728   |   0.025463   |
|     631      |  -44.565889  | -246.761554  |  39.908680   |  39.273321   |   0.177728   |   0.025463   |
|     632      |  -45.337149  | -281.615994  |  45.397682   |  44.820577   |   0.158943   |   0.022311   |
|     633      |  -45.337149  |  281.615994  |  45.397682   |  44.820577   |   0.158943   |   0.022311   |
|     634      |  -45.383435  | -141.762571  |  23.690192   |  22.562214   |   0.304894   |   0.044322   |
|     635      |  -45.383435  |  141.762571  |  23.690192   |  22.562214   |   0.304894   |   0.044322   |
|     636      |  -45.635849  |   0.000000   |   7.263171   |   0.000000   |   1.000000   |     inf      |
|     637      |  -45.889180  |  316.668954  |  50.925862   |  50.399429   |   0.143414   |   0.019841   |
|     638      |  -45.889180  | -316.668954  |  50.925862   |  50.399429   |   0.143414   |   0.019841   |
|     639      |  -46.088938  |  351.858377  |  56.478371   |  56.000000   |   0.129878   |   0.017857   |
|     640      |  -46.676008  |  106.038788  |  18.439235   |  16.876597   |   0.402876   |   0.059254   |
|     641      |  -46.676008  | -106.038788  |  18.439235   |  16.876597   |   0.402876   |   0.059254   |
|     642      |  -46.767036  |  70.167150   |  13.420626   |  11.167449   |   0.554609   |   0.089546   |
|     643      |  -46.767036  |  -70.167150  |  13.420626   |  11.167449   |   0.554609   |   0.089546   |
|     644      |  -46.853578  | -176.902076  |  29.125616   |  28.154840   |   0.256028   |   0.035518   |
|     645      |  -46.853578  |  176.902076  |  29.125616   |  28.154840   |   0.256028   |   0.035518   |
|     646      |  -47.914776  |  211.777248  |  34.557310   |  33.705396   |   0.220673   |   0.029669   |
|     647      |  -47.914776  | -211.777248  |  34.557310   |  33.705396   |   0.220673   |   0.029669   |
|     648      |  -48.163221  |  33.591764   |   9.345665   |   5.346295   |   0.820211   |   0.187045   |
|     649      |  -48.163221  |  -33.591764  |   9.345665   |   5.346295   |   0.820211   |   0.187045   |
|     650      |  -48.252213  |   0.000000   |   7.679578   |   0.000000   |   1.000000   |     inf      |
|     651      |  -48.812816  |  246.582271  |  40.006344   |  39.244787   |   0.194189   |   0.025481   |
|     652      |  -48.812816  | -246.582271  |  40.006344   |  39.244787   |   0.194189   |   0.025481   |
|     653      |  -48.813029  | -141.441198  |  23.813922   |  22.511066   |   0.326231   |   0.044423   |
|     654      |  -48.813029  |  141.441198  |  23.813922   |  22.511066   |   0.326231   |   0.044423   |
|     655      |  -49.598916  |  281.503089  |  45.492720   |  44.802608   |   0.173520   |   0.022320   |
|     656      |  -49.598916  | -281.503089  |  45.492720   |  44.802608   |   0.173520   |   0.022320   |
|     657      |  -50.130642  | -105.892724  |  18.646515   |  16.853351   |   0.427884   |   0.059335   |
|     658      |  -50.130642  |  105.892724  |  18.646515   |  16.853351   |   0.427884   |   0.059335   |
|     659      |  -50.155612  |  316.615486  |  51.019264   |  50.390920   |   0.156461   |   0.019845   |
|     660      |  -50.155612  | -316.615486  |  51.019264   |  50.390920   |   0.156461   |   0.019845   |
|     661      |  -50.199758  |  70.036291   |  13.714223   |  11.146622   |   0.582573   |   0.089713   |
|     662      |  -50.199758  |  -70.036291  |  13.714223   |  11.146622   |   0.582573   |   0.089713   |
|     663      |  -50.274891  | -176.631667  |  29.228367   |  28.111803   |   0.273758   |   0.035572   |
|     664      |  -50.274891  |  176.631667  |  29.228367   |  28.111803   |   0.273758   |   0.035572   |
|     665      |  -50.356641  |  351.858377  |  56.570596   |  56.000000   |   0.141673   |   0.017857   |
|     666      |  -50.561744  |   0.000000   |   8.047151   |   0.000000   |   1.000000   |     inf      |
|     667      |  -51.384725  | -211.606085  |  34.656889   |  33.678154   |   0.235974   |   0.029693   |
|     668      |  -51.384725  |  211.606085  |  34.656889   |  33.678154   |   0.235974   |   0.029693   |
|     669      |  -52.064864  |  33.485400   |   9.852221   |   5.329367   |   0.841067   |   0.187640   |
|     670      |  -52.064864  |  -33.485400  |   9.852221   |   5.329367   |   0.841067   |   0.187640   |
|     671      |  -52.270240  | -141.316069  |  23.980382   |  22.491151   |   0.346911   |   0.044462   |
|     672      |  -52.270240  |  141.316069  |  23.980382   |  22.491151   |   0.346911   |   0.044462   |
|     673      |  -52.308018  | -246.494054  |  40.104345   |  39.230747   |   0.207585   |   0.025490   |
|     674      |  -52.308018  |  246.494054  |  40.104345   |  39.230747   |   0.207585   |   0.025490   |
|     675      |  -53.091325  | -281.471463  |  45.587508   |  44.797575   |   0.185352   |   0.022323   |
|     676      |  -53.091325  |  281.471463  |  45.587508   |  44.797575   |   0.185352   |   0.022323   |
|     677      |  -53.523354  |  105.809988  |  18.872114   |  16.840183   |   0.451381   |   0.059382   |
|     678      |  -53.523354  | -105.809988  |  18.872114   |  16.840183   |   0.451381   |   0.059382   |
|     679      |  -53.632759  | -316.607749  |  51.107559   |  50.389688   |   0.167019   |   0.019845   |
|     680      |  -53.632759  |  316.607749  |  51.107559   |  50.389688   |   0.167019   |   0.019845   |
|     681      |  -53.713623  |  176.509633  |  29.364326   |  28.092381   |   0.291128   |   0.035597   |
|     682      |  -53.713623  | -176.509633  |  29.364326   |  28.092381   |   0.291128   |   0.035597   |
|     683      |  -53.826264  |  351.858377  |  56.651466   |  56.000000   |   0.151218   |   0.017857   |
|     684      |  -53.844578  |  69.950619   |  14.049269   |  11.132987   |   0.609970   |   0.089823   |
|     685      |  -53.844578  |  -69.950619  |  14.049269   |  11.132987   |   0.609970   |   0.089823   |
|     686      |  -53.932606  |   0.000000   |   8.583641   |   0.000000   |   1.000000   |     inf      |
|     687      |  -54.796128  |  211.491959  |  34.771427   |  33.659991   |   0.250812   |   0.029709   |
|     688      |  -54.796128  | -211.491959  |  34.771427   |  33.659991   |   0.250812   |   0.029709   |
|     689      |  -55.610859  |  33.325370   |  10.318284   |   5.303897   |   0.857773   |   0.188541   |
|     690      |  -55.610859  |  -33.325370  |  10.318284   |   5.303897   |   0.857773   |   0.188541   |
|     691      |  -55.689855  |  141.250770  |  24.164910   |  22.480758   |   0.366785   |   0.044482   |
|     692      |  -55.689855  | -141.250770  |  24.164910   |  22.480758   |   0.366785   |   0.044482   |
|     693      |  -55.734550  | -246.399761  |  40.206452   |  39.215740   |   0.220622   |   0.025500   |
|     694      |  -55.734550  |  246.399761  |  40.206452   |  39.215740   |   0.220622   |   0.025500   |
|     695      |  -56.557649  |  281.398311  |  45.681566   |  44.785932   |   0.197047   |   0.022328   |
|     696      |  -56.557649  | -281.398311  |  45.681566   |  44.785932   |   0.197047   |   0.022328   |
|     697      |  -57.110723  | -105.753973  |  19.128767   |  16.831268   |   0.475172   |   0.059413   |
|     698      |  -57.110723  |  105.753973  |  19.128767   |  16.831268   |   0.475172   |   0.059413   |
|     699      |  -57.130384  |  316.567088  |  51.197105   |  50.383217   |   0.177600   |   0.019848   |
|     700      |  -57.130384  | -316.567088  |  51.197105   |  50.383217   |   0.177600   |   0.019848   |
|     701      |  -57.151223  | -176.440063  |  29.517711   |  28.081308   |   0.308151   |   0.035611   |
|     702      |  -57.151223  |  176.440063  |  29.517711   |  28.081308   |   0.308151   |   0.035611   |
|     703      |  -57.334973  |  351.858377  |  56.738596   |  56.000000   |   0.160828   |   0.017857   |
|     704      |  -57.797155  |  69.873743   |  14.432160   |  11.120752   |   0.637375   |   0.089922   |
|     705      |  -57.797155  |  -69.873743  |  14.432160   |  11.120752   |   0.637375   |   0.089922   |
|     706      |  -58.238487  | -211.435876  |  34.904261   |  33.651065   |   0.265553   |   0.029717   |
|     707      |  -58.238487  |  211.435876  |  34.904261   |  33.651065   |   0.265553   |   0.029717   |
|     708      |  -58.985465  |  -33.192087  |  10.772097   |   5.282685   |   0.871495   |   0.189298   |
|     709      |  -58.985465  |  33.192087   |  10.772097   |   5.282685   |   0.871495   |   0.189298   |
|     710      |  -59.167429  | -246.361687  |  40.324620   |  39.209680   |   0.233525   |   0.025504   |
|     711      |  -59.167429  |  246.361687  |  40.324620   |  39.209680   |   0.233525   |   0.025504   |
|     712      |  -59.256196  | -141.231341  |  24.375965   |  22.477666   |   0.386894   |   0.044489   |
|     713      |  -59.256196  |  141.231341  |  24.375965   |  22.477666   |   0.386894   |   0.044489   |
|     714      |  -59.966273  |  281.381357  |  45.788914   |  44.783234   |   0.208433   |   0.022330   |
|     715      |  -59.966273  | -281.381357  |  45.788914   |  44.783234   |   0.208433   |   0.022330   |
|     716      |  -60.004171  |   1.461338   |   9.552792   |   0.232579   |   0.999704   |   4.299611   |
|     717      |  -60.004171  |  -1.461338   |   9.552792   |   0.232579   |   0.999704   |   4.299611   |
|     718      |  -60.524592  |  316.563727  |  51.295275   |  50.382682   |   0.187791   |   0.019848   |
|     719      |  -60.524592  | -316.563727  |  51.295275   |  50.382682   |   0.187791   |   0.019848   |
|     720      |  -60.724664  |  351.858377  |  56.827855   |  56.000000   |   0.170069   |   0.017857   |
|     721      |  -60.725048  | -176.425011  |  29.695649   |  28.078913   |   0.325458   |   0.035614   |
|     722      |  -60.725048  |  176.425011  |  29.695649   |  28.078913   |   0.325458   |   0.035614   |
|     723      |  -61.050615  |  105.665542  |  19.422371   |  16.817193   |   0.500274   |   0.059463   |
|     724      |  -61.050615  | -105.665542  |  19.422371   |  16.817193   |   0.500274   |   0.059463   |
|     725      |  -61.075659  |   0.000000   |   9.720493   |   0.000000   |   1.000000   |     inf      |
|     726      |  -61.346469  |  69.792184   |  14.788859   |  11.107771   |   0.660199   |   0.090027   |
|     727      |  -61.346469  |  -69.792184  |  14.788859   |  11.107771   |   0.660199   |   0.090027   |
|     728      |  -61.829886  | -211.392322  |  35.053727   |  33.644133   |   0.280727   |   0.029723   |
|     729      |  -61.829886  |  211.392322  |  35.053727   |  33.644133   |   0.280727   |   0.029723   |
|     730      |  -62.781634  |  246.294823  |  40.452501   |  39.199039   |   0.247006   |   0.025511   |
|     731      |  -62.781634  | -246.294823  |  40.452501   |  39.199039   |   0.247006   |   0.025511   |
|     732      |  -62.929241  |  32.946966   |  11.305147   |   5.243673   |   0.885924   |   0.190706   |
|     733      |  -62.929241  |  -32.946966  |  11.305147   |   5.243673   |   0.885924   |   0.190706   |
|     734      |  -63.197906  |  141.166186  |  24.616011   |  22.467296   |   0.408606   |   0.044509   |
|     735      |  -63.197906  | -141.166186  |  24.616011   |  22.467296   |   0.408606   |   0.044509   |
|     736      |  -63.604162  |  281.320050  |  45.903569   |  44.773477   |   0.220526   |   0.022335   |
|     737      |  -63.604162  | -281.320050  |  45.903569   |  44.773477   |   0.220526   |   0.022335   |
|     738      |  -64.180338  | -316.529779  |  51.402419   |  50.377279   |   0.198719   |   0.019850   |
|     739      |  -64.180338  |  316.529779  |  51.402419   |  50.377279   |   0.198719   |   0.019850   |
|     740      |  -64.386941  |  351.858377  |  56.929880   |  56.000000   |   0.180002   |   0.017857   |
|     741      |  -64.589799  |  105.551154  |  19.694669   |  16.798988   |   0.521958   |   0.059527   |
|     742      |  -64.589799  | -105.551154  |  19.694669   |  16.798988   |   0.521958   |   0.059527   |
|     743      |  -64.637285  |  69.696959   |  15.128634   |  11.092615   |   0.679992   |   0.090150   |
|     744      |  -64.637285  |  -69.696959  |  15.128634   |  11.092615   |   0.679992   |   0.090150   |
|     745      |  -64.694697  | -176.381060  |  29.900670   |  28.071918   |   0.344356   |   0.035623   |
|     746      |  -64.694697  |  176.381060  |  29.900670   |  28.071918   |   0.344356   |   0.035623   |
|     747      |  -64.771747  |   0.000000   |  10.308744   |   0.000000   |   1.000000   |     inf      |
|     748      |  -65.832104  | -211.365674  |  35.233797   |  33.639892   |   0.297371   |   0.029727   |
|     749      |  -65.832104  |  211.365674  |  35.233797   |  33.639892   |   0.297371   |   0.029727   |
|     750      |  -66.701546  |  141.026543  |  24.828978   |  22.445071   |   0.427560   |   0.044553   |
|     751      |  -66.701546  | -141.026543  |  24.828978   |  22.445071   |   0.427560   |   0.044553   |
|     752      |  -66.800140  | -246.281319  |  40.613132   |  39.196889   |   0.261777   |   0.025512   |
|     753      |  -66.800140  |  246.281319  |  40.613132   |  39.196889   |   0.261777   |   0.025512   |
|     754      |  -67.619843  | -281.313309  |  46.047687   |  44.772404   |   0.233715   |   0.022335   |
|     755      |  -67.619843  |  281.313309  |  46.047687   |  44.772404   |   0.233715   |   0.022335   |
|     756      |  -67.868949  | -105.428356  |  19.955601   |  16.779444   |   0.541286   |   0.059597   |
|     757      |  -67.868949  |  105.428356  |  19.955601   |  16.779444   |   0.541286   |   0.059597   |
|     758      |  -68.186016  |  316.527115  |  51.532480   |  50.376855   |   0.210588   |   0.019850   |
|     759      |  -68.186016  | -316.527115  |  51.532480   |  50.376855   |   0.210588   |   0.019850   |
|     760      |  -68.198245  |  176.244217  |  30.076926   |  28.050138   |   0.360878   |   0.035650   |
|     761      |  -68.198245  | -176.244217  |  30.076926   |  28.050138   |   0.360878   |   0.035650   |
|     762      |  -68.388553  |  351.858377  |  57.047959   |  56.000000   |   0.190793   |   0.017857   |
|     763      |  -68.578841  |  -32.592349  |  12.084586   |   5.187233   |   0.903189   |   0.192781   |
|     764      |  -68.578841  |  32.592349   |  12.084586   |   5.187233   |   0.903189   |   0.192781   |
|     765      |  -68.595368  |  -69.515583  |  15.543288   |  11.063749   |   0.702380   |   0.090385   |
|     766      |  -68.595368  |  69.515583   |  15.543288   |  11.063749   |   0.702380   |   0.090385   |
|     767      |  -69.371175  |  211.255741  |  35.388755   |  33.622396   |   0.311985   |   0.029742   |
|     768      |  -69.371175  | -211.255741  |  35.388755   |  33.622396   |   0.311985   |   0.029742   |
|     769      |  -69.970974  | -140.859652  |  25.032082   |  22.418510   |   0.444878   |   0.044606   |
|     770      |  -69.970974  |  140.859652  |  25.032082   |  22.418510   |   0.444878   |   0.044606   |
|     771      |  -70.388014  |  246.207763  |  40.755083   |  39.185182   |   0.274876   |   0.025520   |
|     772      |  -70.388014  | -246.207763  |  40.755083   |  39.185182   |   0.274876   |   0.025520   |
|     773      |  -71.236074  |  281.270855  |  46.179040   |  44.765647   |   0.245513   |   0.022339   |
|     774      |  -71.236074  | -281.270855  |  46.179040   |  44.765647   |   0.245513   |   0.022339   |
|     775      |  -71.291210  |   3.919085   |  11.363480   |   0.623742   |   0.998492   |   1.603228   |
|     776      |  -71.291210  |  -3.919085   |  11.363480   |   0.623742   |   0.998492   |   1.603228   |
|     777      |  -71.480906  |  176.099249  |  30.248010   |  28.027066   |   0.376109   |   0.035680   |
|     778      |  -71.480906  | -176.099249  |  30.248010   |  28.027066   |   0.376109   |   0.035680   |
|     779      |  -71.511939  |  -32.497012  |  12.501530   |   5.172060   |   0.910407   |   0.193347   |
|     780      |  -71.511939  |  32.497012   |  12.501530   |   5.172060   |   0.910407   |   0.193347   |
|     781      |  -71.808080  |  316.508402  |  51.654047   |  50.373877   |   0.221253   |   0.019852   |
|     782      |  -71.808080  | -316.508402  |  51.654047   |  50.373877   |   0.221253   |   0.019852   |
|     783      |  -71.851202  |  105.271767  |  20.285070   |  16.754522   |   0.563738   |   0.059685   |
|     784      |  -71.851202  | -105.271767  |  20.285070   |  16.754522   |   0.563738   |   0.059685   |
|     785      |  -72.010158  |  351.858377  |  57.160732   |  56.000000   |   0.200501   |   0.017857   |
|     786      |  -72.173154  |  -32.720681  |  12.612070   |   5.207658   |   0.910772   |   0.192025   |
|     787      |  -72.173154  |  32.720681   |  12.612070   |   5.207658   |   0.910772   |   0.192025   |
|     788      |  -72.681232  |  211.168850  |  35.543559   |  33.608566   |   0.325448   |   0.029754   |
|     789      |  -72.681232  | -211.168850  |  35.543559   |  33.608566   |   0.325448   |   0.029754   |
|     790      |  -73.692957  |  246.188140  |  40.899802   |  39.182059   |   0.286764   |   0.025522   |
|     791      |  -73.692957  | -246.188140  |  40.899802   |  39.182059   |   0.286764   |   0.025522   |
|     792      |  -73.972481  |  -2.000937   |  11.777392   |   0.318459   |   0.999634   |   3.140121   |
|     793      |  -73.972481  |   2.000937   |  11.777392   |   0.318459   |   0.999634   |   3.140121   |
|     794      |  -73.984999  | -140.684708  |  25.298111   |  22.390667   |   0.465453   |   0.044661   |
|     795      |  -73.984999  |  140.684708  |  25.298111   |  22.390667   |   0.465453   |   0.044661   |
|     796      |  -74.508606  | -281.292379  |  46.312977   |  44.769073   |   0.256049   |   0.022337   |
|     797      |  -74.508606  |  281.292379  |  46.312977   |  44.769073   |   0.256049   |   0.022337   |
|     798      |  -74.757158  |  69.289437   |  16.222612   |  11.027756   |   0.733419   |   0.090680   |
|     799      |  -74.757158  |  -69.289437  |  16.222612   |  11.027756   |   0.733419   |   0.090680   |
|     800      |  -75.045687  | -316.530852  |  51.773970   |  50.377450   |   0.230693   |   0.019850   |
|     801      |  -75.045687  |  316.530852  |  51.773970   |  50.377450   |   0.230693   |   0.019850   |
|     802      |  -75.233144  |  351.858377  |  57.265785   |  56.000000   |   0.209090   |   0.017857   |
|     803      |  -75.487405  |  175.907873  |  30.465569   |  27.996608   |   0.394353   |   0.035719   |
|     804      |  -75.487405  | -175.907873  |  30.465569   |  27.996608   |   0.394353   |   0.035719   |
|     805      |  -76.676467  | -211.007198  |  35.731372   |  33.582839   |   0.341533   |   0.029777   |
|     806      |  -76.676467  |  211.007198  |  35.731372   |  33.582839   |   0.341533   |   0.029777   |
|     807      |  -77.232425  |  69.389625   |  16.524367   |  11.043702   |   0.743866   |   0.090549   |
|     808      |  -77.232425  |  -69.389625  |  16.524367   |  11.043702   |   0.743866   |   0.090549   |
|     809      |  -77.356873  |  -69.260283  |  16.525367   |  11.023116   |   0.745020   |   0.090718   |
|     810      |  -77.356873  |  69.260283   |  16.525367   |  11.023116   |   0.745020   |   0.090718   |
|     811      |  -77.358540  |  -32.280256  |  13.340905   |   5.137562   |   0.922875   |   0.194645   |
|     812      |  -77.358540  |  32.280256   |  13.340905   |   5.137562   |   0.922875   |   0.194645   |
|     813      |  -77.690399  |  246.077645  |  41.069996   |  39.164474   |   0.301067   |   0.025533   |
|     814      |  -77.690399  | -246.077645  |  41.069996   |  39.164474   |   0.301067   |   0.025533   |
|     815      |  -78.253904  |  105.127152  |  20.858038   |  16.731506   |   0.597108   |   0.059767   |
|     816      |  -78.253904  | -105.127152  |  20.858038   |  16.731506   |   0.597108   |   0.059767   |
|     817      |  -78.514848  | -281.228183  |  46.470483   |  44.758856   |   0.268902   |   0.022342   |
|     818      |  -78.514848  |  281.228183  |  46.470483   |  44.758856   |   0.268902   |   0.022342   |
|     819      |  -79.058786  |  316.501686  |  51.920531   |  50.372808   |   0.242343   |   0.019852   |
|     820      |  -79.058786  | -316.501686  |  51.920531   |  50.372808   |   0.242343   |   0.019852   |
|     821      |  -79.248414  |  351.858377  |  57.402806   |  56.000000   |   0.219724   |   0.017857   |
|     822      |  -80.292059  | -105.140847  |  21.055070   |  16.733686   |   0.606926   |   0.059760   |
|     823      |  -80.292059  |  105.140847  |  21.055070   |  16.733686   |   0.606926   |   0.059760   |
|     824      |  -80.376065  | -140.569414  |  25.771344   |  22.372317   |   0.496375   |   0.044698   |
|     825      |  -80.376065  |  140.569414  |  25.771344   |  22.372317   |   0.496375   |   0.044698   |
|     826      |  -80.738344  | -105.068490  |  21.089122   |  16.722169   |   0.609314   |   0.059801   |
|     827      |  -80.738344  |  105.068490  |  21.089122   |  16.722169   |   0.609314   |   0.059801   |
|     828      |  -81.728740  |  175.741308  |  30.846755   |  27.970098   |   0.421682   |   0.035752   |
|     829      |  -81.728740  | -175.741308  |  30.846755   |  27.970098   |   0.421682   |   0.035752   |
|     830      |  -82.328091  |  -4.824289   |  13.125400   |   0.767809   |   0.998288   |   1.302406   |
|     831      |  -82.328091  |   4.824289   |  13.125400   |   0.767809   |   0.998288   |   1.302406   |
|     832      |  -82.600442  |  140.579658  |  25.950297   |  22.373948   |   0.506594   |   0.044695   |
|     833      |  -82.600442  | -140.579658  |  25.950297   |  22.373948   |   0.506594   |   0.044695   |
|     834      |  -82.777733  |  -69.111821  |  17.162628   |  10.999488   |   0.767626   |   0.090913   |
|     835      |  -82.777733  |  69.111821   |  17.162628   |  10.999488   |   0.767626   |   0.090913   |
|     836      |  -82.862711  |  210.764530  |  36.043558   |  33.544217   |   0.365891   |   0.029811   |
|     837      |  -82.862711  | -210.764530  |  36.043558   |  33.544217   |   0.365891   |   0.029811   |
|     838      |  -82.995671  |  140.490869  |  25.970052   |  22.359816   |   0.508631   |   0.044723   |
|     839      |  -82.995671  | -140.490869  |  25.970052   |  22.359816   |   0.508631   |   0.044723   |
|     840      |  -84.019349  |  245.657331  |  41.321103   |  39.097579   |   0.323614   |   0.025577   |
|     841      |  -84.019349  | -245.657331  |  41.321103   |  39.097579   |   0.323614   |   0.025577   |
|     842      |  -84.263147  |  25.881773   |  14.029257   |   4.119212   |   0.955923   |   0.242765   |
|     843      |  -84.263147  |  -25.881773  |  14.029257   |   4.119212   |   0.955923   |   0.242765   |
|     844      |  -84.334363  |   3.013423   |  13.430797   |   0.479601   |   0.999362   |   2.085066   |
|     845      |  -84.334363  |  -3.013423   |  13.430797   |   0.479601   |   0.999362   |   2.085066   |
|     846      |  -84.417542  | -175.895762  |  31.051794   |  27.994680   |   0.432679   |   0.035721   |
|     847      |  -84.417542  |  175.895762  |  31.051794   |  27.994680   |   0.432679   |   0.035721   |
|     848      |  -84.577439  | -175.688159  |  31.033040   |  27.961639   |   0.433761   |   0.035763   |
|     849      |  -84.577439  |  175.688159  |  31.033040   |  27.961639   |   0.433761   |   0.035763   |
|     850      |  -85.105900  |  280.538672  |  46.658453   |  44.649116   |   0.290302   |   0.022397   |
|     851      |  -85.105900  | -280.538672  |  46.658453   |  44.649116   |   0.290302   |   0.022397   |
|     852      |  -85.168644  |  38.197052   |  14.855827   |   6.079250   |   0.912437   |   0.164494   |
|     853      |  -85.168644  |  -38.197052  |  14.855827   |   6.079250   |   0.912437   |   0.164494   |
|     854      |  -85.665558  |  211.188899  |  36.271736   |  33.611757   |   0.375888   |   0.029751   |
|     855      |  -85.665558  | -211.188899  |  36.271736   |  33.611757   |   0.375888   |   0.029751   |
|     856      |  -85.756665  | -210.815246  |  36.222096   |  33.552289   |   0.376803   |   0.029804   |
|     857      |  -85.756665  |  210.815246  |  36.222096   |  33.552289   |   0.376803   |   0.029804   |
|     858      |  -85.966733  | -315.560139  |  52.053273   |  50.222956   |   0.262847   |   0.019911   |
|     859      |  -85.966733  |  315.560139  |  52.053273   |  50.222956   |   0.262847   |   0.019911   |
|     860      |  -85.974527  |  105.007973  |  21.599556   |  16.712538   |   0.633498   |   0.059835   |
|     861      |  -85.974527  | -105.007973  |  21.599556   |  16.712538   |   0.633498   |   0.059835   |
|     862      |  -86.375776  |  246.597853  |  41.585233   |  39.247267   |   0.330577   |   0.025479   |
|     863      |  -86.375776  | -246.597853  |  41.585233   |  39.247267   |   0.330577   |   0.025479   |
|     864      |  -86.519761  |  350.775137  |  57.500737   |  55.827597   |   0.239476   |   0.017912   |
|     865      |  -86.519761  | -350.775137  |  57.500737   |  55.827597   |   0.239476   |   0.017912   |
|     866      |  -86.708900  |  282.092865  |  46.969538   |  44.896474   |   0.293811   |   0.022273   |
|     867      |  -86.708900  | -282.092865  |  46.969538   |  44.896474   |   0.293811   |   0.022273   |
|     868      |  -86.734242  | -245.973742  |  41.510438   |  39.147937   |   0.332547   |   0.025544   |
|     869      |  -86.734242  |  245.973742  |  41.510438   |  39.147937   |   0.332547   |   0.025544   |
|     870      |  -86.757772  | -317.567748  |  52.394664   |  50.542477   |   0.263537   |   0.019785   |
|     871      |  -86.757772  |  317.567748  |  52.394664   |  50.542477   |   0.263537   |   0.019785   |
|     872      |  -87.524583  |  281.194311  |  46.871277   |  44.753465   |   0.297196   |   0.022345   |
|     873      |  -87.524583  | -281.194311  |  46.871277   |  44.753465   |   0.297196   |   0.022345   |
|     874      |  -88.040412  | -316.496355  |  52.284532   |  50.371959   |   0.267996   |   0.019852   |
|     875      |  -88.040412  |  316.496355  |  52.284532   |  50.371959   |   0.267996   |   0.019852   |
|     876      |  -88.170415  |  140.558523  |  26.407599   |  22.370584   |   0.531391   |   0.044702   |
|     877      |  -88.170415  | -140.558523  |  26.407599   |  22.370584   |   0.531391   |   0.044702   |
|     878      |  -88.219075  |  351.858377  |  57.733315   |  56.000000   |   0.243196   |   0.017857   |
|     879      |  -88.657831  |  27.265548   |  14.762529   |   4.339447   |   0.955821   |   0.230444   |
|     880      |  -88.657831  |  -27.265548  |  14.762529   |   4.339447   |   0.955821   |   0.230444   |
|     881      |  -89.526558  |  36.237090   |  15.371543   |   5.767312   |   0.926946   |   0.173391   |
|     882      |  -89.526558  |  -36.237090  |  15.371543   |   5.767312   |   0.926946   |   0.173391   |
|     883      |  -89.792477  |  175.890513  |  31.430648   |  27.993845   |   0.454681   |   0.035722   |
|     884      |  -89.792477  | -175.890513  |  31.430648   |  27.993845   |   0.454681   |   0.035722   |
|     885      |  -90.026130  |  -62.325176  |  17.426653   |   9.919360   |   0.822195   |   0.100813   |
|     886      |  -90.026130  |  62.325176   |  17.426653   |   9.919360   |   0.822195   |   0.100813   |
|     887      |  -90.376140  |  75.533052   |  18.745918   |  12.021459   |   0.767304   |   0.083185   |
|     888      |  -90.376140  |  -75.533052  |  18.745918   |  12.021459   |   0.767304   |   0.083185   |
|     889      |  -90.531744  |   0.000000   |  14.408575   |   0.000000   |   1.000000   |     inf      |
|     890      |  -91.010852  | -211.042064  |  36.578546   |  33.588388   |   0.395992   |   0.029772   |
|     891      |  -91.010852  |  211.042064  |  36.578546   |  33.588388   |   0.395992   |   0.029772   |
|     892      |  -91.898481  | -246.139516  |  41.815668   |  39.174321   |   0.349776   |   0.025527   |
|     893      |  -91.898481  |  246.139516  |  41.815668   |  39.174321   |   0.349776   |   0.025527   |
|     894      |  -92.541781  | -281.308683  |  47.132053   |  44.771668   |   0.312494   |   0.022336   |
|     895      |  -92.541781  |  281.308683  |  47.132053   |  44.771668   |   0.312494   |   0.022336   |
|     896      |  -92.956744  | -316.560408  |  52.509422   |  50.382154   |   0.281750   |   0.019848   |
|     897      |  -92.956744  |  316.560408  |  52.509422   |  50.382154   |   0.281750   |   0.019848   |
|     898      |  -93.101793  |  351.858377  |  57.927209   |  56.000000   |   0.255797   |   0.017857   |
|     899      |  -93.387365  |  -98.033026  |  21.548706   |  15.602441   |   0.689743   |   0.064093   |
|     900      |  -93.387365  |  98.033026   |  21.548706   |  15.602441   |   0.689743   |   0.064093   |
|     901      |  -93.532091  | -111.580776  |  23.172502   |  17.758632   |   0.642403   |   0.056311   |
|     902      |  -93.532091  |  111.580776  |  23.172502   |  17.758632   |   0.642403   |   0.056311   |
|     903      |  -93.692886  |  -4.289078   |  14.927302   |   0.682628   |   0.998954   |   1.464927   |
|     904      |  -93.692886  |   4.289078   |  14.927302   |   0.682628   |   0.998954   |   1.464927   |
|     905      |  -94.349268  |  63.861696   |  18.132562   |  10.163905   |   0.828132   |   0.098387   |
|     906      |  -94.349268  |  -63.861696  |  18.132562   |  10.163905   |   0.828132   |   0.098387   |
|     907      |  -94.745043  |  73.683778   |  19.102520   |  11.727138   |   0.789380   |   0.085272   |
|     908      |  -94.745043  |  -73.683778  |  19.102520   |  11.727138   |   0.789380   |   0.085272   |
|     909      |  -95.202577  |   6.142057   |  15.183461   |   0.977539   |   0.997925   |   1.022977   |
|     910      |  -95.202577  |  -6.142057   |  15.183461   |   0.977539   |   0.997925   |   1.022977   |
|     911      |  -95.692689  |  133.532122  |  26.145974   |  21.252297   |   0.582497   |   0.047054   |
|     912      |  -95.692689  | -133.532122  |  26.145974   |  21.252297   |   0.582497   |   0.047054   |
|     913      |  -95.747216  | -147.119968  |  27.936936   |  23.414870   |   0.545466   |   0.042708   |
|     914      |  -95.747216  |  147.119968  |  27.936936   |  23.414870   |   0.545466   |   0.042708   |
|     915      |  -97.319856  |  168.949269  |  31.031137   |  26.889111   |   0.499142   |   0.037190   |
|     916      |  -97.319856  | -168.949269  |  31.031137   |  26.889111   |   0.499142   |   0.037190   |
|     917      |  -97.471196  |  182.439238  |  32.920349   |  29.036107   |   0.471229   |   0.034440   |
|     918      |  -97.471196  | -182.439238  |  32.920349   |  29.036107   |   0.471229   |   0.034440   |
|     919      |  -97.628457  |  -99.626238  |  22.200091   |  15.856008   |   0.699909   |   0.063068   |
|     920      |  -97.628457  |  99.626238   |  22.200091   |  15.856008   |   0.699909   |   0.063068   |
|     921      |  -97.948677  |  -19.505992  |  15.895131   |   3.104475   |   0.980742   |   0.322116   |
|     922      |  -97.948677  |  19.505992   |  15.895131   |   3.104475   |   0.980742   |   0.322116   |
|     923      |  -97.952152  | -109.843672  |  23.423508   |  17.482163   |   0.665552   |   0.057201   |
|     924      |  -97.952152  |  109.843672  |  23.423508   |  17.482163   |   0.665552   |   0.057201   |
|     925      |  -98.399975  |  204.263076  |  36.085013   |  32.509478   |   0.433999   |   0.030760   |
|     926      |  -98.399975  | -204.263076  |  36.085013   |  32.509478   |   0.433999   |   0.030760   |
|     927      |  -98.873793  | -217.775410  |  38.065044   |  34.660033   |   0.413404   |   0.028852   |
|     928      |  -98.873793  |  217.775410  |  38.065044   |  34.660033   |   0.413404   |   0.028852   |
|     929      |  -99.104578  | -239.370236  |  41.233058   |  38.096956   |   0.382532   |   0.026249   |
|     930      |  -99.104578  |  239.370236  |  41.233058   |  38.096956   |   0.382532   |   0.026249   |
|     931      |  -99.299795  |  -43.283124  |  17.240145   |   6.888723   |   0.916701   |   0.145165   |
|     932      |  -99.299795  |  43.283124   |  17.240145   |   6.888723   |   0.916701   |   0.145165   |
|     933      |  -99.680943  | -274.334108  |  46.454570   |  43.661629   |   0.341510   |   0.022903   |
|     934      |  -99.680943  |  274.334108  |  46.454570   |  43.661629   |   0.341510   |   0.022903   |
|     935      |  -99.833988  | -135.101920  |  26.735830   |  21.502138   |   0.594299   |   0.046507   |
|     936      |  -99.833988  |  135.101920  |  26.735830   |  21.502138   |   0.594299   |   0.046507   |
|     937      |  -99.860702  |  253.218384  |  43.321645   |  40.300958   |   0.366868   |   0.024813   |
|     938      |  -99.860702  | -253.218384  |  43.321645   |  40.300958   |   0.366868   |   0.024813   |
|     939      | -100.175662  | -309.342071  |  51.750492   |  49.233320   |   0.308083   |   0.020311   |
|     940      | -100.175662  |  309.342071  |  51.750492   |  49.233320   |   0.308083   |   0.020311   |
|     941      | -100.185518  | -145.532934  |  28.120014   |  23.162286   |   0.567035   |   0.043174   |
|     942      | -100.185518  |  145.532934  |  28.120014   |  23.162286   |   0.567035   |   0.043174   |
|     943      | -100.392397  |  288.649950  |  48.639330   |  45.940066   |   0.328498   |   0.021767   |
|     944      | -100.392397  | -288.649950  |  48.639330   |  45.940066   |   0.328498   |   0.021767   |
|     945      | -100.497591  | -344.475254  |  57.110455   |  54.824939   |   0.280066   |   0.018240   |
|     946      | -100.497591  |  344.475254  |  57.110455   |  54.824939   |   0.280066   |   0.018240   |
|     947      | -100.581039  |  323.994069  |  53.992878   |  51.565258   |   0.296483   |   0.019393   |
|     948      | -100.581039  | -323.994069  |  53.992878   |  51.565258   |   0.296483   |   0.019393   |
|     949      | -101.426917  |  170.408514  |  31.561866   |  27.121357   |   0.511459   |   0.036871   |
|     950      | -101.426917  | -170.408514  |  31.561866   |  27.121357   |   0.511459   |   0.036871   |
|     951      | -101.798814  |  180.982879  |  33.048247   |  28.804320   |   0.490246   |   0.034717   |
|     952      | -101.798814  | -180.982879  |  33.048247   |  28.804320   |   0.490246   |   0.034717   |
|     953      | -101.883732  |   6.664475   |  16.249954   |   1.060684   |   0.997867   |   0.942788   |
|     954      | -101.883732  |  -6.664475   |  16.249954   |   1.060684   |   0.997867   |   0.942788   |
|     955      | -102.388876  |  20.965247   |  16.633804   |   3.336723   |   0.979673   |   0.299695   |
|     956      | -102.388876  |  -20.965247  |  16.633804   |   3.336723   |   0.979673   |   0.299695   |
|     957      | -102.649996  | -205.587598  |  36.572158   |  32.720283   |   0.446713   |   0.030562   |
|     958      | -102.649996  |  205.587598  |  36.572158   |  32.720283   |   0.446713   |   0.030562   |
|     959      | -102.964960  | -216.303713  |  38.127187   |  34.425805   |   0.429808   |   0.029048   |
|     960      | -102.964960  |  216.303713  |  38.127187   |  34.425805   |   0.429808   |   0.029048   |
|     961      | -103.611476  |  240.711782  |  41.708769   |  38.310470   |   0.395367   |   0.026103   |
|     962      | -103.611476  | -240.711782  |  41.708769   |  38.310470   |   0.395367   |   0.026103   |
|     963      | -103.754665  |  -56.004045  |  18.765092   |   8.913321   |   0.879989   |   0.112192   |
|     964      | -103.754665  |  56.004045   |  18.765092   |   8.913321   |   0.879989   |   0.112192   |
|     965      | -103.791363  |   4.588853   |  16.535046   |   0.730339   |   0.999024   |   1.369228   |
|     966      | -103.791363  |  -4.588853   |  16.535046   |   0.730339   |   0.999024   |   1.369228   |
|     967      | -103.792027  |  41.452110   |  17.787701   |   6.597308   |   0.928676   |   0.151577   |
|     968      | -103.792027  |  -41.452110  |  17.787701   |   6.597308   |   0.928676   |   0.151577   |
|     969      | -103.817204  | -251.551913  |  43.311314   |  40.035730   |   0.381494   |   0.024978   |
|     970      | -103.817204  |  251.551913  |  43.311314   |  40.035730   |   0.381494   |   0.024978   |
|     971      | -103.986268  |  -34.363132  |  17.430169   |   5.469062   |   0.949499   |   0.182847   |
|     972      | -103.986268  |  34.363132   |  17.430169   |   5.469062   |   0.949499   |   0.182847   |
|     973      | -104.260819  |  -80.880610  |  21.001212   |  12.872549   |   0.790127   |   0.077685   |
|     974      | -104.260819  |  80.880610   |  21.001212   |  12.872549   |   0.790127   |   0.077685   |
|     975      | -104.322107  |  275.875236  |  46.941333   |  43.906907   |   0.353705   |   0.022775   |
|     976      | -104.322107  | -275.875236  |  46.941333   |  43.906907   |   0.353705   |   0.022775   |
|     977      | -104.432405  | -286.781615  |  48.574814   |  45.642712   |   0.342172   |   0.021909   |
|     978      | -104.432405  |  286.781615  |  48.574814   |  45.642712   |   0.342172   |   0.021909   |
|     979      | -104.765916  | -311.109362  |  52.246700   |  49.514593   |   0.319140   |   0.020196   |
|     980      | -104.765916  |  311.109362  |  52.246700   |  49.514593   |   0.319140   |   0.020196   |
|     981      | -104.812659  | -322.040367  |  53.900610   |  51.254316   |   0.309485   |   0.019511   |
|     982      | -104.812659  |  322.040367  |  53.900610   |  51.254316   |   0.309485   |   0.019511   |
|     983      | -104.929967  |  346.389833  |  57.603584   |  55.129654   |   0.289915   |   0.018139   |
|     984      | -104.929967  | -346.389833  |  57.603584   |  55.129654   |   0.289915   |   0.018139   |
|     985      | -105.208237  |   0.000000   |  16.744411   |   0.000000   |   1.000000   |     inf      |
|     986      | -106.069332  |  34.680255   |  17.760881   |   5.519534   |   0.950485   |   0.181175   |
|     987      | -106.069332  |  -34.680255  |  17.760881   |   5.519534   |   0.950485   |   0.181175   |
|     988      | -106.442343  |  -69.300672  |  20.214906   |  11.029544   |   0.838036   |   0.090666   |
|     989      | -106.442343  |  69.300672   |  20.214906   |  11.029544   |   0.838036   |   0.090666   |
|     990      | -107.170073  |  91.634457   |  22.441580   |  14.584077   |   0.760047   |   0.068568   |
|     991      | -107.170073  |  -91.634457  |  22.441580   |  14.584077   |   0.760047   |   0.068568   |
|     992      | -107.393409  |  117.085123  |  25.286245   |  18.634676   |   0.675948   |   0.053663   |
|     993      | -107.393409  | -117.085123  |  25.286245   |  18.634676   |   0.675948   |   0.053663   |
|     994      | -108.092648  |  57.766084   |  19.506022   |   9.193758   |   0.881957   |   0.108769   |
|     995      | -108.092648  |  -57.766084  |  19.506022   |   9.193758   |   0.881957   |   0.108769   |
|     996      | -108.203753  |  32.422115   |  17.977638   |   5.160140   |   0.957921   |   0.193793   |
|     997      | -108.203753  |  -32.422115  |  17.977638   |   5.160140   |   0.957921   |   0.193793   |
|     998      | -108.324174  |  69.398551   |  20.474951   |  11.045122   |   0.842020   |   0.090538   |
|     999      | -108.324174  |  -69.398551  |  20.474951   |  11.045122   |   0.842020   |   0.090538   |
Generating an instance of StabilityDerivatives
Variable print_info has no assigned value in the settings file.
    will default to the value: c_bool(True)
Variable folder has no assigned value in the settings file.
    will default to the value: ./output/
/home/ng213/code/sharpy/sharpy/postproc/asymptoticstability.py:171: UserWarning: Plotting modes is under development
  warn.warn('Plotting modes is under development')



|==============|==============|==============|==============|==============|==============|==============|
|     der      |      X       |      Y       |      Z       |      L       |      M       |      N       |
|==============|==============|==============|==============|==============|==============|==============|
|      u       |  -0.000000   |  -0.032063   |   0.000000   |  103.702544  |  -0.000000   |   0.215455   |
|      v       |  131.843986  |   0.000000   | -982.084813  |  -0.000000   | 1279.474176  |  -0.000000   |
|      w       |   0.000000   | -187.481605  |  -0.000000   |-22078.785295 |   0.000000   | -3334.924961 |
|      p       | -187.422614  |   0.000000   | 1572.771760  |   0.000000   | -2857.778575 |   0.000000   |
|      q       |   0.000000   |  -2.610892   |   0.000000   | 1127.543337  |  -0.000000   |  -38.871906  |
|      r       |   0.000000   |   0.000000   |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |
|    flap1     |  -0.000000   |   1.108474   |   0.000000   |  271.384778  |  -0.000000   |  23.331888   |



|==============|==============|==============|==============|==============|==============|==============|
|     der      |     C_D      |     C_Y      |     C_L      |     C_l      |     C_m      |     C_n      |
|==============|==============|==============|==============|==============|==============|==============|
|      u       |  -0.000000   |  -0.000006   |   0.000000   |   0.001009   |  -0.000000   |  -0.000078   |
|      v       |   0.010573   |   0.000000   |  -0.193187   |  -0.000000   |   0.347457   |  -0.000000   |
|      w       |   0.000000   |  -0.036606   |  -0.000000   |  -0.217442   |   0.000000   |  -0.015495   |
|      p       |  -0.479599   |   0.000000   |  12.034020   |   0.000000   |  -30.222290  |   0.000000   |
|      q       |   0.000000   |  -0.019853   |   0.000000   |   0.010944   |  -0.000000   |  -0.001245   |
|      r       |   0.000000   |   0.000000   |  -0.000000   |   0.000000   |   0.000000   |   0.000000   |
|    alpha     |   0.000000   |  -1.024980   |  -0.000000   |  -6.088362   |   0.000000   |  -0.433847   |
|     beta     |   0.296049   |   0.000000   |  -5.409222   |  -0.000000   |   9.728798   |  -0.000000   |
FINISHED - Elapsed time = 29.3233356 seconds
FINISHED - CPU process time = 69.2634336 seconds
Post-processing
Nonlinear Equilibrium

The files can be opened with Paraview to see the deformation and aerodynamic loading on the flying wing in trim conditions.

Asymptotic Stability
[18]:
eigenvalues_trim = np.loadtxt('./output/horten_u_inf2800_M4N11Msf5/stability/eigenvalues.dat')

Flight Dynamics modes

The flight dynamics modes can be found close to the origin of the Argand diagram. In particular, the phugoid is the mode that is closest to the imaginary axis. An exercise is left to the user to compare this phugoid predicition with the nonlinear response!

[19]:
fig = plt.figure()
plt.scatter(eigenvalues_trim[:, 0], eigenvalues_trim[:, 1],
           marker='x',
           color='k')
plt.xlim(-0.5, 0.5)
plt.ylim(-0.5, 0.5)
plt.grid()
plt.xlabel('Real Part, $Re(\lambda)$ [rad/s]')
plt.ylabel('Imaginary Part, $Im(\lambda)$ [rad/s]');
_images/content_example_notebooks_linear_horten_39_0.png
Structural Modes

Looking further out on the plot, the structural modes appear. There is a curve given the Newmark-\(\beta\) integration scheme and on top of it several modes are damped by the presence of the aerodynamics.

Try changing newmark_damp in the LinearAssembler settings to see how this plot changes!

[20]:
fig = plt.figure()
plt.scatter(eigenvalues_trim[:, 0], eigenvalues_trim[:, 1],
           marker='x',
           color='k')
plt.xlim(-5, 0.5)
plt.ylim(-200, 200)
plt.grid()
plt.xlabel('Real Part, $Re(\lambda)$ [rad/s]')
plt.ylabel('Imaginary Part, $Im(\lambda)$ [rad/s]');
_images/content_example_notebooks_linear_horten_41_0.png
Stability Derivatives

Stability derivatives are calculated using the steady-state frequency response of the UVLM system. The output is saved in ./output/<case_name>/stability/. Note that stability derivatives are expressed in the SHARPy Frame of Reference, which is South East Up (not the conventional in flight dynamics literature).

This body attached frame of reference has:

  • \(x\) positive downstream
  • \(y\) positive towards the right wing
  • \(z\) positive up

Simulation NREL 5MW wind turbine

[1]:
%config InlineBackend.figure_format = 'svg'
from IPython.display import Image
url = 'https://raw.githubusercontent.com/ImperialCollegeLondon/sharpy/dev_doc/docs/source/content/example_notebooks/images/turbulence_no_legend.png'
Image(url=url, width=800)
[1]:

In this notebook the blade loads on the NREL-5MW reference wind turbine computed with SHARPy and OpenFAST will be compared. However, zero-drag airfoils have been used.

OpenFAST: https://openfast.readthedocs.io

NREL-5MW: Jonkman, J.; Butterfield, S.; Musial, W. and Scott, G.. Definition of a 5-MW Reference Wind Turbine for Offshore System Development, Technical Report, NREL 2009

Load the required packages:

[2]:
# Required packages
import numpy as np
import os
import matplotlib.pyplot as plt

# Required SHARPy modules
import sharpy.sharpy_main
import sharpy.utils.algebra as algebra
import sharpy.utils.generate_cases as gc
import cases.templates.template_wt as template_wt

These are the results from the OpenFAST simulation for comparison: out-of-plane of_cNdrR and in-plane of_cTdrR coefficients along the blade and thrust of_ct and power of_cp rotor coefficients

[3]:
of_rR = np.array([0.20158356, 0.3127131, 0.40794048, 0.5984148, 0.6936519, 0.85238045, 0.899999, 0.95555407, 0.98729974, 1.0])
of_cNdrR = np.array([0.08621394, 0.14687876, 0.19345148, 0.2942731, 0.36003628, 0.43748564, 0.44762507, 0.38839236, 0.29782477, 0.0])
of_cTdrR = np.array([0.048268348, 0.051957503, 0.05304592, 0.052862607, 0.056001827, 0.0536646, 0.050112925, 0.038993906, 0.023664437, 0.0])

of_ct = 0.69787693
of_cp = 0.48813498
Create SHARPy case

Definition of parameters

[4]:
# Mathematical constants
deg2rad = np.pi/180.

# Case
case = 'rotor'
# route = os.path.dirname(os.path.realpath(__file__)) + '/'
route = './'

# Geometry discretization
chord_panels = np.array([8], dtype=int)
revs_in_wake = 5

# Operation
rotation_velocity = 12.1*2*np.pi/60
pitch_deg = 0. #degrees

# Wind
WSP = 12.
air_density = 1.225

# Simulation
dphi = 4.*deg2rad
revs_to_simulate = 5

Computation of associated parameters

[5]:
dt = dphi/rotation_velocity
time_steps = int(revs_to_simulate*2.*np.pi/dphi)
mstar = int(revs_in_wake*2.*np.pi/dphi)

Generation of the rotor geometry based on the information in the excel file

[6]:
rotor = template_wt.rotor_from_excel_type02(
                                  chord_panels,
                                  rotation_velocity,
                                  pitch_deg,
                                  excel_file_name= 'source/type02_db_NREL5MW_v01.xlsx',
                                  excel_sheet_parameters = 'parameters',
                                  excel_sheet_structural_blade = 'structural_blade',
                                  excel_sheet_discretization_blade = 'discretization_blade',
                                  excel_sheet_aero_blade = 'aero_blade',
                                  excel_sheet_airfoil_info = 'airfoil_info',
                                  excel_sheet_airfoil_coord = 'airfoil_coord',
                                  m_distribution = 'uniform',
                                  n_points_camber = 100,
                                  tol_remove_points = 1e-8,
                                  wsp = WSP,
                                  dt = dt)
WARNING: The poisson cofficient is assumed equal to 0.3
WARNING: Cross-section area is used as shear area
WARNING: Using perpendicular axis theorem to compute the inertia around xB
WARNING: Replacing node  49 by node  0
WARNING: Replacing node  98 by node  0

Define simulation details. The steady simulation is faster than the dynamic simulation. However, the dynamic simulation includes wake self-induction and provides more accurate results.

[7]:
steady_simulation = False
[8]:
SimInfo = gc.SimulationInformation()
SimInfo.set_default_values()

if steady_simulation:
    SimInfo.solvers['SHARPy']['flow'] = ['BeamLoader',
                            'AerogridLoader',
                            'StaticCoupledRBM',
                            'BeamPlot',
                            'AerogridPlot',
                            'SaveData']
else:
    SimInfo.solvers['SHARPy']['flow'] = ['BeamLoader',
                            'AerogridLoader',
                            'StaticCoupledRBM',
                            'DynamicCoupled']

SimInfo.solvers['SHARPy']['case'] = case
SimInfo.solvers['SHARPy']['route'] = route
SimInfo.solvers['SHARPy']['write_log'] = True
SimInfo.set_variable_all_dicts('dt', dt)
SimInfo.set_variable_all_dicts('rho', air_density)

SimInfo.solvers['SteadyVelocityField']['u_inf'] = WSP
SimInfo.solvers['SteadyVelocityField']['u_inf_direction'] = np.array([0., 0., 1.])

SimInfo.solvers['BeamLoader']['unsteady'] = 'on'

SimInfo.solvers['AerogridLoader']['unsteady'] = 'on'
SimInfo.solvers['AerogridLoader']['mstar'] = mstar
SimInfo.solvers['AerogridLoader']['freestream_dir'] = np.array([0.,0.,0.])

SimInfo.solvers['StaticCoupledRBM']['structural_solver'] = 'RigidDynamicPrescribedStep'
SimInfo.solvers['StaticCoupledRBM']['structural_solver_settings'] = SimInfo.solvers['RigidDynamicPrescribedStep']
SimInfo.solvers['StaticCoupledRBM']['aero_solver'] = 'SHWUvlm'
SimInfo.solvers['StaticCoupledRBM']['aero_solver_settings'] = SimInfo.solvers['SHWUvlm']

SimInfo.solvers['StaticCoupledRBM']['tolerance'] = 1e-8
SimInfo.solvers['StaticCoupledRBM']['n_load_steps'] = 0
SimInfo.solvers['StaticCoupledRBM']['relaxation_factor'] = 0.

SimInfo.solvers['SHWUvlm']['convection_scheme'] = 2
SimInfo.solvers['SHWUvlm']['num_cores'] = 8
SimInfo.solvers['SHWUvlm']['rot_vel'] = rotation_velocity
SimInfo.solvers['SHWUvlm']['rot_axis'] = np.array([0.,0.,1.])
SimInfo.solvers['SHWUvlm']['rot_center'] = np.zeros((3),)
SimInfo.solvers['SHWUvlm']['velocity_field_generator'] = 'SteadyVelocityField'
SimInfo.solvers['SHWUvlm']['velocity_field_input'] = SimInfo.solvers['SteadyVelocityField']

SimInfo.solvers['SaveData']['compress_float'] = True

# Only used for steady_simulation = False
SimInfo.solvers['StepUvlm']['convection_scheme'] = 3
SimInfo.solvers['StepUvlm']['num_cores'] = 8
SimInfo.solvers['StepUvlm']['velocity_field_generator'] = 'SteadyVelocityField'
SimInfo.solvers['StepUvlm']['velocity_field_input'] = SimInfo.solvers['SteadyVelocityField']

SimInfo.solvers['DynamicCoupled']['structural_solver'] = 'RigidDynamicPrescribedStep'
SimInfo.solvers['DynamicCoupled']['structural_solver_settings'] = SimInfo.solvers['RigidDynamicPrescribedStep']
SimInfo.solvers['DynamicCoupled']['aero_solver'] = 'StepUvlm'
SimInfo.solvers['DynamicCoupled']['aero_solver_settings'] = SimInfo.solvers['StepUvlm']
SimInfo.solvers['DynamicCoupled']['postprocessors'] = ['BeamPlot', 'AerogridPlot', 'Cleanup', 'SaveData']
SimInfo.solvers['DynamicCoupled']['postprocessors_settings'] = {'BeamPlot': SimInfo.solvers['BeamPlot'],
                                                             'AerogridPlot': SimInfo.solvers['AerogridPlot'],
                                                             'Cleanup': SimInfo.solvers['Cleanup'],
                                                             'SaveData': SimInfo.solvers['SaveData']}
SimInfo.solvers['DynamicCoupled']['minimum_steps'] = 0
SimInfo.solvers['DynamicCoupled']['include_unsteady_force_contribution'] = True
SimInfo.solvers['DynamicCoupled']['relaxation_factor'] = 0.
SimInfo.solvers['DynamicCoupled']['final_relaxation_factor'] = 0.
SimInfo.solvers['DynamicCoupled']['dynamic_relaxation'] = False
SimInfo.solvers['DynamicCoupled']['relaxation_steps'] = 0

# Define dynamic simulation (used regardless the value of "steady_simulation" variable)
SimInfo.define_num_steps(time_steps)
SimInfo.with_forced_vel = True
SimInfo.for_vel = np.zeros((time_steps,6), dtype=float)
SimInfo.for_vel[:,5] = rotation_velocity
SimInfo.for_acc = np.zeros((time_steps,6), dtype=float)
SimInfo.with_dynamic_forces = True
SimInfo.dynamic_forces = np.zeros((time_steps,rotor.StructuralInformation.num_node,6), dtype=float)

Generate simulation files

[9]:
gc.clean_test_files(SimInfo.solvers['SHARPy']['route'], SimInfo.solvers['SHARPy']['case'])
rotor.generate_h5_files(SimInfo.solvers['SHARPy']['route'], SimInfo.solvers['SHARPy']['case'])
SimInfo.generate_solver_file()
SimInfo.generate_dyn_file(time_steps)
Run SHARPy case
[10]:
sharpy_output = sharpy.sharpy_main.main(['', SimInfo.solvers['SHARPy']['route'] + SimInfo.solvers['SHARPy']['case'] + '.sharpy'])
--------------------------------------------------------------------------------
            ######  ##     ##    ###    ########  ########  ##    ##
           ##    ## ##     ##   ## ##   ##     ## ##     ##  ##  ##
           ##       ##     ##  ##   ##  ##     ## ##     ##   ####
            ######  ######### ##     ## ########  ########     ##
                 ## ##     ## ######### ##   ##   ##           ##
           ##    ## ##     ## ##     ## ##    ##  ##           ##
            ######  ##     ## ##     ## ##     ## ##           ##
--------------------------------------------------------------------------------
Aeroelastics Lab, Aeronautics Department.
    Copyright (c), Imperial College London.
    All rights reserved.
    License available at https://github.com/imperialcollegelondon/sharpy
Running SHARPy from /home/arturo/code/sharpy/docs/source/content/example_notebooks
SHARPy being run is in /home/arturo/code/sharpy
The branch being run is dev_doc
The version and commit hash are: v0.1-1816-g6185d82-6185d82
The available solvers on this session are:
_BaseStructural 
AerogridLoader 
BeamLoader 
DynamicCoupled 
DynamicUVLM 
LinDynamicSim 
LinearAssembler 
Modal 
NoAero 
NonLinearDynamic 
NonLinearDynamicCoupledStep 
NonLinearDynamicMultibody 
NonLinearDynamicPrescribedStep 
NonLinearStatic 
NonLinearStaticMultibody 
PrescribedUvlm 
RigidDynamicPrescribedStep 
SHWUvlm 
StaticCoupled 
StaticCoupledRBM 
StaticTrim 
StaticUvlm 
StepLinearUVLM 
StepUvlm 
Trim 
FrequencyResponse 
WriteVariablesTime 
BeamPlot 
LiftDistribution 
AeroForcesCalculator 
CreateSnapshot 
StabilityDerivatives 
Cleanup 
AsymptoticStability 
PickleData 
SaveData 
StallCheck 
BeamLoads 
PlotFlowField 
AerogridPlot 
PreSharpy 
Generating an instance of BeamLoader
Generating an instance of AerogridLoader
The aerodynamic grid contains 3 surfaces
  Surface 0, M=8, N=48
     Wake 0, M=450, N=48
  Surface 1, M=8, N=48
     Wake 1, M=450, N=48
  Surface 2, M=8, N=48
     Wake 2, M=450, N=48
  In total: 1152 bound panels
  In total: 64800 wake panels
  Total number of panels = 65952
Generating an instance of StaticCoupledRBM
Generating an instance of RigidDynamicPrescribedStep
Generating an instance of SHWUvlm
i_step: 0, i_iter: 0
i_step: 0, i_iter: 1
Pos res     = 0.000000e+00. Psi res     = 0.000000e+00.
Pos_dot res = 0.000000e+00. Psi_dot res = 0.000000e+00.
Resultant forces and moments: (array([1.19344329e-02, 4.42818203e-03, 8.51720587e+05]), array([-2.23034084e-02,  8.00768152e-03,  6.02114389e+06]))
Generating an instance of DynamicCoupled
Generating an instance of RigidDynamicPrescribedStep
Generating an instance of StepUvlm
Generating an instance of BeamPlot
Generating an instance of AerogridPlot
Generating an instance of Cleanup
Generating an instance of SaveData
Variable save_linear has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable save_linear_uvlm has no assigned value in the settings file.
    will default to the value: c_bool(False)
Variable skip_attr has no assigned value in the settings file.
    will default to the value: ['fortran', 'airfoils', 'airfoil_db', 'settings_types', 'ct_dynamic_forces_list', 'ct_gamma_dot_list', 'ct_gamma_list', 'ct_gamma_star_list', 'ct_normals_list', 'ct_u_ext_list', 'ct_u_ext_star_list', 'ct_zeta_dot_list', 'ct_zeta_list', 'ct_zeta_star_list', 'dynamic_input', ['fortran', 'airfoils', 'airfoil_db', 'settings_types', 'ct_dynamic_forces_list', 'ct_forces_list', 'ct_gamma_dot_list', 'ct_gamma_list', 'ct_gamma_star_list', 'ct_normals_list', 'ct_u_ext_list', 'ct_u_ext_star_list', 'ct_zeta_dot_list', 'ct_zeta_list', 'ct_zeta_star_list', 'dynamic_input']]
Variable format has no assigned value in the settings file.
    will default to the value: h5



|=======|========|======|==============|==============|==============|==============|==============|
|  ts   |   t    | iter | struc ratio  |  iter time   | residual vel |  FoR_vel(x)  |  FoR_vel(z)  |
|=======|========|======|==============|==============|==============|==============|==============|
/home/arturo/code/sharpy/sharpy/solvers/dynamiccoupled.py:449: RuntimeWarning: divide by zero encountered in log10
  np.log10(self.res_dqdt),
|   1   | 0.0551 |  1   |   0.000689   |  46.721959   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   2   | 0.1102 |  1   |   0.000686   |  46.839166   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   3   | 0.1653 |  1   |   0.000687   |  46.816562   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   4   | 0.2204 |  1   |   0.000666   |  48.386563   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   5   | 0.2755 |  1   |   0.000683   |  47.135425   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   6   | 0.3306 |  1   |   0.000707   |  46.560263   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   7   | 0.3857 |  1   |   0.000697   |  46.562699   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   8   | 0.4408 |  1   |   0.000692   |  46.757933   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|   9   | 0.4959 |  1   |   0.000691   |  46.622405   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  10   | 0.5510 |  1   |   0.000700   |  46.480478   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  11   | 0.6061 |  1   |   0.000703   |  46.450803   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  12   | 0.6612 |  1   |   0.000708   |  46.466538   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  13   | 0.7163 |  1   |   0.000576   |  55.899692   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  14   | 0.7713 |  1   |   0.000642   |  50.701285   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  15   | 0.8264 |  1   |   0.000671   |  47.593583   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  16   | 0.8815 |  1   |   0.000699   |  47.287386   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  17   | 0.9366 |  1   |   0.000691   |  46.559619   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  18   | 0.9917 |  1   |   0.000681   |  46.953868   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  19   | 1.0468 |  1   |   0.000693   |  46.526422   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  20   | 1.1019 |  1   |   0.000692   |  46.634115   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  21   | 1.1570 |  1   |   0.000691   |  46.424641   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  22   | 1.2121 |  1   |   0.000684   |  46.882152   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  23   | 1.2672 |  1   |   0.000694   |  46.586424   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  24   | 1.3223 |  1   |   0.000687   |  46.776280   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  25   | 1.3774 |  1   |   0.000692   |  46.704067   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  26   | 1.4325 |  1   |   0.000679   |  46.886657   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  27   | 1.4876 |  1   |   0.000684   |  46.516365   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  28   | 1.5427 |  1   |   0.000682   |  46.684166   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  29   | 1.5978 |  1   |   0.000683   |  47.033028   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  30   | 1.6529 |  1   |   0.000694   |  46.291923   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  31   | 1.7080 |  1   |   0.000687   |  46.680159   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  32   | 1.7631 |  1   |   0.000683   |  46.629501   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  33   | 1.8182 |  1   |   0.000682   |  46.806173   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  34   | 1.8733 |  1   |   0.000687   |  46.757005   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  35   | 1.9284 |  1   |   0.000683   |  47.033428   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  36   | 1.9835 |  1   |   0.000659   |  48.662729   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  37   | 2.0386 |  1   |   0.000659   |  48.571643   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  38   | 2.0937 |  1   |   0.000673   |  47.434747   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  39   | 2.1488 |  1   |   0.000661   |  48.286789   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  40   | 2.2039 |  1   |   0.000679   |  47.779096   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  41   | 2.2590 |  1   |   0.000677   |  48.413777   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  42   | 2.3140 |  1   |   0.000671   |  47.798777   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  43   | 2.3691 |  1   |   0.000710   |  46.501405   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  44   | 2.4242 |  1   |   0.000690   |  46.611010   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  45   | 2.4793 |  1   |   0.000688   |  46.704990   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  46   | 2.5344 |  1   |   0.000728   |  46.796206   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  47   | 2.5895 |  1   |   0.000693   |  46.510013   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  48   | 2.6446 |  1   |   0.000692   |  46.604489   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  49   | 2.6997 |  1   |   0.000693   |  46.648462   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  50   | 2.7548 |  1   |   0.000703   |  46.233052   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  51   | 2.8099 |  1   |   0.000696   |  46.494563   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  52   | 2.8650 |  1   |   0.000689   |  46.427002   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  53   | 2.9201 |  1   |   0.000685   |  46.556616   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  54   | 2.9752 |  1   |   0.000688   |  46.986618   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  55   | 3.0303 |  1   |   0.000685   |  47.021588   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  56   | 3.0854 |  1   |   0.000695   |  46.501523   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  57   | 3.1405 |  1   |   0.000690   |  46.545832   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  58   | 3.1956 |  1   |   0.000688   |  46.394942   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  59   | 3.2507 |  1   |   0.000690   |  46.572368   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  60   | 3.3058 |  1   |   0.000689   |  46.388416   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  61   | 3.3609 |  1   |   0.000674   |  47.326130   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  62   | 3.4160 |  1   |   0.000691   |  46.475252   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  63   | 3.4711 |  1   |   0.000692   |  46.700463   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  64   | 3.5262 |  1   |   0.000684   |  46.761324   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  65   | 3.5813 |  1   |   0.000690   |  46.305145   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  66   | 3.6364 |  1   |   0.000681   |  47.033500   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  67   | 3.6915 |  1   |   0.000690   |  46.707418   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  68   | 3.7466 |  1   |   0.000687   |  46.829002   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  69   | 3.8017 |  1   |   0.000686   |  46.771566   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  70   | 3.8567 |  1   |   0.000687   |  46.798868   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  71   | 3.9118 |  1   |   0.000687   |  46.656061   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  72   | 3.9669 |  1   |   0.000689   |  46.650955   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  73   | 4.0220 |  1   |   0.000689   |  46.676483   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  74   | 4.0771 |  1   |   0.000701   |  46.733123   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  75   | 4.1322 |  1   |   0.000693   |  46.613006   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  76   | 4.1873 |  1   |   0.000691   |  46.569005   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  77   | 4.2424 |  1   |   0.000691   |  46.714434   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  78   | 4.2975 |  1   |   0.000691   |  46.564491   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  79   | 4.3526 |  1   |   0.000691   |  46.293432   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  80   | 4.4077 |  1   |   0.000691   |  46.444557   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  81   | 4.4628 |  1   |   0.000685   |  46.583821   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  82   | 4.5179 |  1   |   0.000692   |  46.464751   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  83   | 4.5730 |  1   |   0.000691   |  46.614111   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  84   | 4.6281 |  1   |   0.000682   |  47.093682   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  85   | 4.6832 |  1   |   0.000668   |  47.848219   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  86   | 4.7383 |  1   |   0.000690   |  46.453935   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  87   | 4.7934 |  1   |   0.000671   |  47.508853   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  88   | 4.8485 |  1   |   0.000704   |  46.453028   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  89   | 4.9036 |  1   |   0.000686   |  46.783497   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  90   | 4.9587 |  1   |   0.000695   |  46.473095   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  91   | 5.0138 |  1   |   0.000699   |  46.384601   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  92   | 5.0689 |  1   |   0.000671   |  48.773508   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  93   | 5.1240 |  1   |   0.000682   |  46.843241   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  94   | 5.1791 |  1   |   0.000691   |  46.690389   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  95   | 5.2342 |  1   |   0.000685   |  46.811431   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  96   | 5.2893 |  1   |   0.000683   |  46.832472   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  97   | 5.3444 |  1   |   0.000690   |  46.410221   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  98   | 5.3994 |  1   |   0.000693   |  46.644631   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  99   | 5.4545 |  1   |   0.000695   |  46.328560   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  100  | 5.5096 |  1   |   0.000693   |  46.709863   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  101  | 5.5647 |  1   |   0.000696   |  46.303366   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  102  | 5.6198 |  1   |   0.000688   |  46.450453   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  103  | 5.6749 |  1   |   0.000704   |  46.611641   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  104  | 5.7300 |  1   |   0.000686   |  46.622834   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  105  | 5.7851 |  1   |   0.000693   |  46.442312   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  106  | 5.8402 |  1   |   0.000697   |  46.894939   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  107  | 5.8953 |  1   |   0.000695   |  46.583571   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  108  | 5.9504 |  1   |   0.000692   |  46.596199   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  109  | 6.0055 |  1   |   0.000689   |  46.675746   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  110  | 6.0606 |  1   |   0.000688   |  46.948383   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  111  | 6.1157 |  1   |   0.000708   |  46.583486   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  112  | 6.1708 |  1   |   0.000687   |  46.777358   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  113  | 6.2259 |  1   |   0.000696   |  46.655726   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  114  | 6.2810 |  1   |   0.000692   |  46.488556   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  115  | 6.3361 |  1   |   0.000687   |  46.641207   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  116  | 6.3912 |  1   |   0.000699   |  46.693835   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  117  | 6.4463 |  1   |   0.000717   |  47.359647   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  118  | 6.5014 |  1   |   0.000689   |  46.684606   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  119  | 6.5565 |  1   |   0.000686   |  46.892280   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  120  | 6.6116 |  1   |   0.000690   |  46.391236   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  121  | 6.6667 |  1   |   0.000687   |  46.619935   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  122  | 6.7218 |  1   |   0.000685   |  46.847298   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  123  | 6.7769 |  1   |   0.000698   |  46.383369   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  124  | 6.8320 |  1   |   0.000690   |  46.623488   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  125  | 6.8871 |  1   |   0.000689   |  46.456695   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  126  | 6.9421 |  1   |   0.000748   |  46.666541   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  127  | 6.9972 |  1   |   0.000695   |  46.393158   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  128  | 7.0523 |  1   |   0.000632   |  50.929908   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  129  | 7.1074 |  1   |   0.000685   |  47.093784   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  130  | 7.1625 |  1   |   0.000688   |  46.682273   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  131  | 7.2176 |  1   |   0.000690   |  46.667180   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  132  | 7.2727 |  1   |   0.000689   |  46.673738   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  133  | 7.3278 |  1   |   0.000690   |  46.813912   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  134  | 7.3829 |  1   |   0.000698   |  46.399704   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  135  | 7.4380 |  1   |   0.000687   |  46.776766   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  136  | 7.4931 |  1   |   0.000687   |  46.979810   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  137  | 7.5482 |  1   |   0.000693   |  46.578824   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  138  | 7.6033 |  1   |   0.000689   |  46.882381   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  139  | 7.6584 |  1   |   0.000676   |  48.142078   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  140  | 7.7135 |  1   |   0.000693   |  46.784018   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  141  | 7.7686 |  1   |   0.000688   |  46.642419   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  142  | 7.8237 |  1   |   0.000689   |  46.662693   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  143  | 7.8788 |  1   |   0.000689   |  46.802617   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  144  | 7.9339 |  1   |   0.000690   |  46.776085   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  145  | 7.9890 |  1   |   0.000701   |  46.875717   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  146  | 8.0441 |  1   |   0.000685   |  46.822466   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  147  | 8.0992 |  1   |   0.000677   |  47.384767   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  148  | 8.1543 |  1   |   0.000675   |  47.679214   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  149  | 8.2094 |  1   |   0.000689   |  46.763218   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  150  | 8.2645 |  1   |   0.000679   |  46.940251   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  151  | 8.3196 |  1   |   0.000686   |  46.627359   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  152  | 8.3747 |  1   |   0.000687   |  46.664798   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  153  | 8.4298 |  1   |   0.000687   |  46.633910   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  154  | 8.4848 |  1   |   0.000679   |  46.877187   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  155  | 8.5399 |  1   |   0.000696   |  46.384902   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  156  | 8.5950 |  1   |   0.000690   |  46.680191   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  157  | 8.6501 |  1   |   0.000690   |  46.595866   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  158  | 8.7052 |  1   |   0.000711   |  46.561896   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  159  | 8.7603 |  1   |   0.000682   |  46.789459   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  160  | 8.8154 |  1   |   0.000712   |  46.585605   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  161  | 8.8705 |  1   |   0.000674   |  47.731465   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  162  | 8.9256 |  1   |   0.000679   |  47.806239   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  163  | 8.9807 |  1   |   0.000687   |  46.597511   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  164  | 9.0358 |  1   |   0.000695   |  46.662126   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  165  | 9.0909 |  1   |   0.000678   |  47.138759   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  166  | 9.1460 |  1   |   0.000687   |  46.654425   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  167  | 9.2011 |  1   |   0.000683   |  47.072656   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  168  | 9.2562 |  1   |   0.000688   |  46.655192   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  169  | 9.3113 |  1   |   0.000683   |  46.990134   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  170  | 9.3664 |  1   |   0.000704   |  46.960453   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  171  | 9.4215 |  1   |   0.000688   |  46.615369   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  172  | 9.4766 |  1   |   0.000686   |  46.761498   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  173  | 9.5317 |  1   |   0.000686   |  46.698208   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  174  | 9.5868 |  1   |   0.000686   |  46.964062   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  175  | 9.6419 |  1   |   0.000693   |  46.608047   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  176  | 9.6970 |  1   |   0.000684   |  46.848123   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  177  | 9.7521 |  1   |   0.000687   |  46.693659   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  178  | 9.8072 |  1   |   0.000682   |  46.766093   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  179  | 9.8623 |  1   |   0.000689   |  46.497713   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  180  | 9.9174 |  1   |   0.000694   |  46.824867   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  181  | 9.9725 |  1   |   0.000686   |  46.686000   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  182  |10.0275 |  1   |   0.000687   |  46.847956   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  183  |10.0826 |  1   |   0.000696   |  46.639555   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  184  |10.1377 |  1   |   0.000694   |  46.582859   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  185  |10.1928 |  1   |   0.000692   |  46.696143   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  186  |10.2479 |  1   |   0.000688   |  47.038347   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  187  |10.3030 |  1   |   0.000662   |  48.575645   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  188  |10.3581 |  1   |   0.000662   |  48.531096   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  189  |10.4132 |  1   |   0.000674   |  47.867980   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  190  |10.4683 |  1   |   0.000683   |  47.185120   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  191  |10.5234 |  1   |   0.000680   |  47.472356   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  192  |10.5785 |  1   |   0.000671   |  48.044142   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  193  |10.6336 |  1   |   0.000679   |  47.648927   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  194  |10.6887 |  1   |   0.000669   |  48.052096   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  195  |10.7438 |  1   |   0.000672   |  47.870581   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  196  |10.7989 |  1   |   0.000688   |  47.670530   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  197  |10.8540 |  1   |   0.000669   |  47.552862   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  198  |10.9091 |  1   |   0.000668   |  47.895285   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  199  |10.9642 |  1   |   0.000677   |  47.475987   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  200  |11.0193 |  1   |   0.000689   |  47.705888   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  201  |11.0744 |  1   |   0.000677   |  47.488158   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  202  |11.1295 |  1   |   0.000712   |  48.576639   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  203  |11.1846 |  1   |   0.000673   |  47.734807   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  204  |11.2397 |  1   |   0.000670   |  47.568058   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  205  |11.2948 |  1   |   0.000663   |  48.250896   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  206  |11.3499 |  1   |   0.000670   |  47.559952   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  207  |11.4050 |  1   |   0.000670   |  47.573367   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  208  |11.4601 |  1   |   0.000687   |  46.850101   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  209  |11.5152 |  1   |   0.000685   |  46.660332   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  210  |11.5702 |  1   |   0.000685   |  46.485644   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  211  |11.6253 |  1   |   0.000687   |  46.798719   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  212  |11.6804 |  1   |   0.000688   |  46.841973   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  213  |11.7355 |  1   |   0.000685   |  46.615664   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  214  |11.7906 |  1   |   0.000685   |  46.819705   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  215  |11.8457 |  1   |   0.000695   |  46.534639   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  216  |11.9008 |  1   |   0.000687   |  47.054001   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  217  |11.9559 |  1   |   0.000685   |  46.458661   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  218  |12.0110 |  1   |   0.000685   |  46.475964   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  219  |12.0661 |  1   |   0.000681   |  46.980705   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  220  |12.1212 |  1   |   0.000683   |  46.885118   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  221  |12.1763 |  1   |   0.000690   |  46.385044   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  222  |12.2314 |  1   |   0.000687   |  46.472218   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  223  |12.2865 |  1   |   0.000711   |  46.681981   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  224  |12.3416 |  1   |   0.000686   |  46.755873   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  225  |12.3967 |  1   |   0.000684   |  47.479635   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  226  |12.4518 |  1   |   0.000697   |  46.237011   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  227  |12.5069 |  1   |   0.000681   |  46.954574   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  228  |12.5620 |  1   |   0.000665   |  47.804645   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  229  |12.6171 |  1   |   0.000683   |  46.649178   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  230  |12.6722 |  1   |   0.000619   |  51.822896   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  231  |12.7273 |  1   |   0.000691   |  46.453337   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  232  |12.7824 |  1   |   0.000688   |  46.512926   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  233  |12.8375 |  1   |   0.000693   |  46.372334   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  234  |12.8926 |  1   |   0.000691   |  46.443784   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  235  |12.9477 |  1   |   0.000685   |  46.595713   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  236  |13.0028 |  1   |   0.000685   |  46.675990   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  237  |13.0579 |  1   |   0.000673   |  47.477098   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  238  |13.1129 |  1   |   0.000685   |  46.907466   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  239  |13.1680 |  1   |   0.000679   |  46.745359   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  240  |13.2231 |  1   |   0.000667   |  47.812544   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  241  |13.2782 |  1   |   0.000676   |  46.828156   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  242  |13.3333 |  1   |   0.000674   |  47.228874   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  243  |13.3884 |  1   |   0.000675   |  47.213317   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  244  |13.4435 |  1   |   0.000685   |  46.946864   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  245  |13.4986 |  1   |   0.000686   |  46.518108   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  246  |13.5537 |  1   |   0.000683   |  46.918194   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  247  |13.6088 |  1   |   0.000681   |  46.772611   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  248  |13.6639 |  1   |   0.000681   |  46.738571   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  249  |13.7190 |  1   |   0.000701   |  46.844015   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  250  |13.7741 |  1   |   0.000692   |  46.682392   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  251  |13.8292 |  1   |   0.000684   |  46.749444   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  252  |13.8843 |  1   |   0.000690   |  46.676376   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  253  |13.9394 |  1   |   0.000688   |  46.902780   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  254  |13.9945 |  1   |   0.000700   |  46.342343   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  255  |14.0496 |  1   |   0.000676   |  47.290718   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  256  |14.1047 |  1   |   0.000690   |  46.483884   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  257  |14.1598 |  1   |   0.000687   |  46.475610   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  258  |14.2149 |  1   |   0.000697   |  46.243039   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  259  |14.2700 |  1   |   0.000691   |  46.327818   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  260  |14.3251 |  1   |   0.000684   |  47.023605   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  261  |14.3802 |  1   |   0.000684   |  46.992628   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  262  |14.4353 |  1   |   0.000689   |  46.655423   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  263  |14.4904 |  1   |   0.000687   |  46.780777   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  264  |14.5455 |  1   |   0.000687   |  46.914670   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  265  |14.6006 |  1   |   0.000688   |  46.680806   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  266  |14.6556 |  1   |   0.000678   |  47.492095   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  267  |14.7107 |  1   |   0.000688   |  46.786733   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  268  |14.7658 |  1   |   0.000680   |  47.164431   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  269  |14.8209 |  1   |   0.000708   |  45.651456   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  270  |14.8760 |  1   |   0.000684   |  47.118467   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  271  |14.9311 |  1   |   0.000686   |  46.986024   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  272  |14.9862 |  1   |   0.000705   |  45.811613   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  273  |15.0413 |  1   |   0.000701   |  45.809912   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  274  |15.0964 |  1   |   0.000698   |  46.075125   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  275  |15.1515 |  1   |   0.000697   |  46.349127   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  276  |15.2066 |  1   |   0.000707   |  45.612900   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  277  |15.2617 |  1   |   0.000699   |  45.962354   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  278  |15.3168 |  1   |   0.000703   |  45.854950   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  279  |15.3719 |  1   |   0.000688   |  46.591173   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  280  |15.4270 |  1   |   0.000691   |  46.439605   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  281  |15.4821 |  1   |   0.000700   |  45.609099   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  282  |15.5372 |  1   |   0.000705   |  45.473630   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  283  |15.5923 |  1   |   0.000704   |  45.499228   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  284  |15.6474 |  1   |   0.000707   |  45.474494   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  285  |15.7025 |  1   |   0.000690   |  46.229681   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  286  |15.7576 |  1   |   0.000699   |  45.890873   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  287  |15.8127 |  1   |   0.000693   |  46.117946   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  288  |15.8678 |  1   |   0.000698   |  45.995581   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  289  |15.9229 |  1   |   0.000707   |  45.766717   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  290  |15.9780 |  1   |   0.000726   |  45.936229   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  291  |16.0331 |  1   |   0.000709   |  46.439345   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  292  |16.0882 |  1   |   0.000690   |  46.546813   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  293  |16.1433 |  1   |   0.000693   |  46.523355   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  294  |16.1983 |  1   |   0.000709   |  45.438468   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  295  |16.2534 |  1   |   0.000698   |  46.057489   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  296  |16.3085 |  1   |   0.000692   |  46.396248   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  297  |16.3636 |  1   |   0.000671   |  47.804347   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  298  |16.4187 |  1   |   0.000700   |  45.745559   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  299  |16.4738 |  1   |   0.000695   |  46.054604   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  300  |16.5289 |  1   |   0.000705   |  45.744685   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  301  |16.5840 |  1   |   0.000698   |  45.782885   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  302  |16.6391 |  1   |   0.000694   |  46.331677   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  303  |16.6942 |  1   |   0.000693   |  46.501020   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  304  |16.7493 |  1   |   0.000697   |  45.868491   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  305  |16.8044 |  1   |   0.000699   |  46.378612   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  306  |16.8595 |  1   |   0.000695   |  46.308039   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  307  |16.9146 |  1   |   0.000691   |  46.526447   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  308  |16.9697 |  1   |   0.000696   |  46.122122   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  309  |17.0248 |  1   |   0.000684   |  46.856025   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  310  |17.0799 |  1   |   0.000701   |  46.113206   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  311  |17.1350 |  1   |   0.000692   |  46.398112   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  312  |17.1901 |  1   |   0.000767   |  45.619590   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  313  |17.2452 |  1   |   0.000675   |  47.797250   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  314  |17.3003 |  1   |   0.000685   |  46.677846   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  315  |17.3554 |  1   |   0.000689   |  46.488186   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  316  |17.4105 |  1   |   0.000711   |  46.798838   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  317  |17.4656 |  1   |   0.000690   |  46.569277   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  318  |17.5207 |  1   |   0.000695   |  46.209487   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  319  |17.5758 |  1   |   0.000698   |  45.909949   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  320  |17.6309 |  1   |   0.000679   |  47.280223   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  321  |17.6860 |  1   |   0.000696   |  45.957118   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  322  |17.7410 |  1   |   0.000689   |  46.661208   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  323  |17.7961 |  1   |   0.000689   |  46.485928   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  324  |17.8512 |  1   |   0.000702   |  45.910141   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  325  |17.9063 |  1   |   0.000698   |  46.091762   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  326  |17.9614 |  1   |   0.000697   |  46.191874   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  327  |18.0165 |  1   |   0.000697   |  46.020327   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  328  |18.0716 |  1   |   0.000683   |  47.056295   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  329  |18.1267 |  1   |   0.000679   |  47.225815   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  330  |18.1818 |  1   |   0.000687   |  46.711211   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  331  |18.2369 |  1   |   0.000683   |  46.838738   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  332  |18.2920 |  1   |   0.000690   |  46.530371   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  333  |18.3471 |  1   |   0.000682   |  47.151909   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  334  |18.4022 |  1   |   0.000705   |  46.465808   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  335  |18.4573 |  1   |   0.000698   |  46.918384   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  336  |18.5124 |  1   |   0.000680   |  46.982040   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  337  |18.5675 |  1   |   0.000688   |  46.834463   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  338  |18.6226 |  1   |   0.000685   |  47.082787   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  339  |18.6777 |  1   |   0.000667   |  47.776211   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  340  |18.7328 |  1   |   0.000694   |  46.342369   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  341  |18.7879 |  1   |   0.000679   |  47.334009   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  342  |18.8430 |  1   |   0.000676   |  47.224326   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  343  |18.8981 |  1   |   0.000681   |  47.006368   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  344  |18.9532 |  1   |   0.000682   |  46.777730   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  345  |19.0083 |  1   |   0.000694   |  46.232870   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  346  |19.0634 |  1   |   0.000692   |  46.253289   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  347  |19.1185 |  1   |   0.000693   |  46.055296   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  348  |19.1736 |  1   |   0.000687   |  46.546440   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  349  |19.2287 |  1   |   0.000685   |  46.769534   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  350  |19.2837 |  1   |   0.000698   |  45.705568   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  351  |19.3388 |  1   |   0.000699   |  45.612452   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  352  |19.3939 |  1   |   0.000689   |  46.311269   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  353  |19.4490 |  1   |   0.000704   |  45.581321   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  354  |19.5041 |  1   |   0.000692   |  46.268870   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  355  |19.5592 |  1   |   0.000695   |  45.857139   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  356  |19.6143 |  1   |   0.000672   |  47.383261   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  357  |19.6694 |  1   |   0.000697   |  46.039425   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  358  |19.7245 |  1   |   0.000673   |  47.209931   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  359  |19.7796 |  1   |   0.000693   |  46.166173   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  360  |19.8347 |  1   |   0.000689   |  46.307711   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  361  |19.8898 |  1   |   0.000690   |  46.204995   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  362  |19.9449 |  1   |   0.000707   |  45.873240   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  363  |20.0000 |  1   |   0.000702   |  45.896570   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  364  |20.0551 |  1   |   0.000703   |  45.762990   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  365  |20.1102 |  1   |   0.000689   |  46.398000   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  366  |20.1653 |  1   |   0.000698   |  45.893426   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  367  |20.2204 |  1   |   0.000690   |  46.226002   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  368  |20.2755 |  1   |   0.000694   |  46.151370   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  369  |20.3306 |  1   |   0.000688   |  46.556177   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  370  |20.3857 |  1   |   0.000707   |  45.573970   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  371  |20.4408 |  1   |   0.000693   |  46.446767   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  372  |20.4959 |  1   |   0.000694   |  46.152634   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  373  |20.5510 |  1   |   0.000696   |  46.155208   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  374  |20.6061 |  1   |   0.000705   |  45.472315   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  375  |20.6612 |  1   |   0.000676   |  47.016364   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  376  |20.7163 |  1   |   0.000700   |  45.441678   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  377  |20.7713 |  1   |   0.000705   |  45.608852   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  378  |20.8264 |  1   |   0.000693   |  46.611538   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  379  |20.8815 |  1   |   0.000701   |  46.255489   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  380  |20.9366 |  1   |   0.000688   |  46.646919   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  381  |20.9917 |  1   |   0.000585   |  54.423797   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  382  |21.0468 |  1   |   0.000667   |  47.716783   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  383  |21.1019 |  1   |   0.000700   |  46.025102   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  384  |21.1570 |  1   |   0.000699   |  45.861447   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  385  |21.2121 |  1   |   0.000698   |  46.278300   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  386  |21.2672 |  1   |   0.000699   |  45.952605   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  387  |21.3223 |  1   |   0.000704   |  45.592786   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  388  |21.3774 |  1   |   0.000689   |  46.150288   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  389  |21.4325 |  1   |   0.000697   |  45.931689   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  390  |21.4876 |  1   |   0.000697   |  45.977116   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  391  |21.5427 |  1   |   0.000690   |  45.976451   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  392  |21.5978 |  1   |   0.000690   |  46.597288   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  393  |21.6529 |  1   |   0.000681   |  46.697688   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  394  |21.7080 |  1   |   0.000696   |  47.318465   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  395  |21.7631 |  1   |   0.000699   |  46.267378   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  396  |21.8182 |  1   |   0.000689   |  46.555969   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  397  |21.8733 |  1   |   0.000679   |  47.319640   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  398  |21.9284 |  1   |   0.000671   |  47.558353   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  399  |21.9835 |  1   |   0.000689   |  46.302612   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  400  |22.0386 |  1   |   0.000667   |  47.758410   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  401  |22.0937 |  1   |   0.000687   |  46.813205   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  402  |22.1488 |  1   |   0.000689   |  46.336472   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  403  |22.2039 |  1   |   0.000707   |  46.668331   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  404  |22.2590 |  1   |   0.000688   |  46.649211   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  405  |22.3140 |  1   |   0.000691   |  46.482820   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  406  |22.3691 |  1   |   0.000681   |  46.947114   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  407  |22.4242 |  1   |   0.000689   |  46.618766   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  408  |22.4793 |  1   |   0.000680   |  46.817495   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  409  |22.5344 |  1   |   0.000686   |  46.703945   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  410  |22.5895 |  1   |   0.000675   |  47.620927   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  411  |22.6446 |  1   |   0.000689   |  46.717914   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  412  |22.6997 |  1   |   0.000674   |  47.499379   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  413  |22.7548 |  1   |   0.000683   |  46.991697   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  414  |22.8099 |  1   |   0.000844   |  47.362969   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  415  |22.8650 |  1   |   0.000681   |  47.379998   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  416  |22.9201 |  1   |   0.000688   |  46.840415   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  417  |22.9752 |  1   |   0.000696   |  46.394910   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  418  |23.0303 |  1   |   0.000680   |  47.481963   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  419  |23.0854 |  1   |   0.000677   |  47.425381   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  420  |23.1405 |  1   |   0.000675   |  47.313570   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  421  |23.1956 |  1   |   0.000680   |  47.051804   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  422  |23.2507 |  1   |   0.000692   |  46.392776   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  423  |23.3058 |  1   |   0.000700   |  46.097488   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  424  |23.3609 |  1   |   0.000704   |  45.675144   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  425  |23.4160 |  1   |   0.000678   |  47.188528   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  426  |23.4711 |  1   |   0.000674   |  47.721276   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  427  |23.5262 |  1   |   0.000679   |  47.517682   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  428  |23.5813 |  1   |   0.000699   |  47.314847   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  429  |23.6364 |  1   |   0.000677   |  46.942705   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  430  |23.6915 |  1   |   0.000685   |  46.500190   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  431  |23.7466 |  1   |   0.000690   |  46.497821   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  432  |23.8017 |  1   |   0.000681   |  46.785045   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  433  |23.8567 |  1   |   0.000695   |  45.813771   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  434  |23.9118 |  1   |   0.000710   |  45.188591   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  435  |23.9669 |  1   |   0.000692   |  46.043509   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  436  |24.0220 |  1   |   0.000703   |  45.755100   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  437  |24.0771 |  1   |   0.000696   |  45.757484   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  438  |24.1322 |  1   |   0.000683   |  46.637429   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  439  |24.1873 |  1   |   0.000688   |  46.360789   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  440  |24.2424 |  1   |   0.000691   |  46.138279   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  441  |24.2975 |  1   |   0.000697   |  46.142083   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  442  |24.3526 |  1   |   0.000699   |  46.033069   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  443  |24.4077 |  1   |   0.000685   |  46.517459   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  444  |24.4628 |  1   |   0.000699   |  45.831956   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  445  |24.5179 |  1   |   0.000683   |  47.009859   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  446  |24.5730 |  1   |   0.000703   |  46.299859   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  447  |24.6281 |  1   |   0.000684   |  46.631679   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  448  |24.6832 |  1   |   0.000696   |  46.171868   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  449  |24.7383 |  1   |   0.000704   |  45.749519   |     -inf     | 0.000000e+00 | 0.000000e+00 |
|  450  |24.7934 |  1   |   0.000673   |  47.822073   |     -inf     | 0.000000e+00 | 0.000000e+00 |
...Finished
FINISHED - Elapsed time = 21435.5371006 seconds
FINISHED - CPU process time = 165060.5815336 seconds
Postprocessing

Read the structural and aerodynamic information of the last time step

[11]:
tstep = sharpy_output.structure.timestep_info[-1]
astep = sharpy_output.aero.timestep_info[-1]

Separate the structure into blades

[12]:
# Define beams
ielem = 0
nblades = np.max(sharpy_output.structure.beam_number) + 1
nodes_blade = []
first_node = 0
for iblade in range(nblades):
    nodes_blade.append(np.zeros((sharpy_output.structure.num_node,), dtype=bool))
    while sharpy_output.structure.beam_number[ielem] <= iblade:
        ielem += 1
        if ielem == sharpy_output.structure.num_elem:
            break
    nodes_blade[iblade][first_node:sharpy_output.structure.connectivities[ielem-1,1]+1] = True
    first_node = sharpy_output.structure.connectivities[ielem-1,1]+1

Compute the radial position of the nodes and initialise the rest of the variables

[13]:
r = []
c = []
dr = []
forces = []
CN_drR = []
CTan_drR = []
CP_drR = []
nodes_num = []
for iblade in range(nblades):
    forces.append(tstep.steady_applied_forces[nodes_blade[iblade]].copy())

    nodes_num.append(np.arange(0, sharpy_output.structure.num_node, 1)[nodes_blade[iblade]])

    r.append(np.linalg.norm(tstep.pos[nodes_blade[iblade], :], axis=1))
    dr.append(np.zeros(np.sum(nodes_blade[iblade])))
    dr[iblade][0] = 0.5*(r[iblade][1]-r[iblade][0])
    dr[iblade][-1] = 0.5 * (r[iblade][-1] - r[iblade][-2])
    for inode in range(1,len(r[iblade]) - 1):
        dr[iblade][inode] = 0.5*(r[iblade][inode+1] - r[iblade][inode-1])

    CN_drR.append(np.zeros(len(r[iblade])))
    c.append(np.zeros(len(r[iblade])))
    CTan_drR.append(np.zeros(len(r[iblade])))
    CP_drR.append(np.zeros(len(r[iblade])))

Transform the loads computed by SHARPy into out-of-plane and in-plane components

[14]:
rho = sharpy_output.settings['StaticCoupledRBM']['aero_solver_settings']['rho'].value
uinf = sharpy_output.settings['StaticCoupledRBM']['aero_solver_settings']['velocity_field_input']['u_inf'].value
R = np.max(r[0])
Cp = 0
Ct = 0

global_force_factor = 0.5 * rho * uinf** 2 * np.pi * R**2
global_power_factor = global_force_factor*uinf
for iblade in range(nblades):
    for inode in range(len(r[iblade])):
        forces[iblade][inode, 0] *= 0. # Discard the spanwise component

        node_global_index = nodes_num[iblade][inode]
        ielem = sharpy_output.structure.node_master_elem[node_global_index, 0]
        inode_in_elem = sharpy_output.structure.node_master_elem[node_global_index, 1]
        CAB = algebra.crv2rotation(tstep.psi[ielem, inode_in_elem, :])

        c[iblade][inode] = sharpy_output.aero.aero_dict['chord'][ielem,inode_in_elem]

        forces_AFoR = np.dot(CAB, forces[iblade][inode, 0:3])

        CN_drR[iblade][inode] = forces_AFoR[2]/dr[iblade][inode]*R / global_force_factor
        CTan_drR[iblade][inode] = np.linalg.norm(forces_AFoR[0:2])/dr[iblade][inode]*R  / global_force_factor
        CP_drR[iblade][inode] = np.linalg.norm(forces_AFoR[0:2])/dr[iblade][inode]*R  * r[iblade][inode]*rotation_velocity / global_power_factor

    Cp += np.sum(CP_drR[iblade]*dr[iblade]/R)
    Ct += np.sum(CN_drR[iblade]*dr[iblade]/R)
Results

Plot of the loads along the blade

[15]:
fig, list_plots = plt.subplots(1, 2, figsize=(12, 3))

list_plots[0].grid()
list_plots[0].set_xlabel("r/R [-]")
list_plots[0].set_ylabel("CN/d(r/R) [-]")
list_plots[0].plot(r[0]/R, CN_drR[0], '-', label='SHARPy')
list_plots[0].plot(of_rR, of_cNdrR, '-', label='OpenFAST')
list_plots[0].legend()

list_plots[1].grid()
list_plots[1].set_xlabel("r/R [-]")
list_plots[1].set_ylabel("CT/d(r/R) [-]")
list_plots[1].plot(r[0]/R, CTan_drR[0], '-', label='SHARPy')
list_plots[1].plot(of_rR, of_cTdrR, '-', label='OpenFAST')
list_plots[1].legend()

plt.show()
_images/content_example_notebooks_wind_turbine_34_0.svg

Print the rotor thrust and power coefficients

[16]:
print("      OpenFAST SHARPy")
print("Cp[-] %.2f       %.2f" % (of_cp, Cp))
print("Ct[-] %.2f       %.2f" % (of_ct, Ct))
      OpenFAST SHARPy
Cp[-] 0.49       0.55
Ct[-] 0.70       0.76

Contributing to SHARPy

Bug fixes and features

SHARPy is a collaborative effort, and this means that some coding practices need to be encouraged so that the code is kept tidy and consistent. Any user is welcome to raise issues for bug fixes and feature proposals through Github.

If you are submitting a bug report:

  1. Make sure your SHARPy, xbeam and uvlm local copies are up to date and in the same branch.
  2. Double check that your python distribution is updated by comparing with the utils/environment_*.yml file.
  3. Try to assemble a minimal working example that can be run quickly and easily.
  4. Describe as accurately as possible your setup (OS, path, compilers…) and the problem.
  5. Raise an issue with all this information in the Github repo and label it potential bug.

Please bear in mind that we do not have the resources to provide support for user modifications of the code through Github. If you have doubts about how to modify certain parts of the code, contact us through email and we will help you as much as we can.

If you are fixing a bug:

  1. THANKS!
  2. Please create a pull request from your modified fork, and describe in a few lines which bug you are fixing, a minimal example that triggers the bug and how you are fixing it. We will review it ASAP and hopefully it will be incorporated in the code!

If you have an idea for new functionality but do not know how to implement it:

  1. We welcome tips and suggestions from users, as it allow us to broaden the scope of the code. The more people using it, the better!
  2. Feel free to fill an issue in Github, and tag it as feature proposal. Please understand that the more complete the description of the potential feature, the more likely it is that some of the developers will give it a go.

If you have developed new functionality and you want to share it with the world:

  1. AWESOME! Please follow the same instructions than for the bug fix submission. If you have some peer-reviewed references related to the new code, even better, as it will save us some precious time.

Code formatting

We try to follow the PEP8 standards (with spaces, no tabs please!) and Google Python Style Guide. We do not ask you to freak out over formatting, but please, try to keep it tidy and descriptive. A good tip is to run pylint https://www.pylint.org/ to make sure there are no obvious formatting problems.

Documentation

Contributing to SHARPy’s documentation benefits everyone. As a developer, writing documentation helps you better understand what you have done and whether your functions etc make logical sense. As a user, any documentation is better than digging through the code. The more we have documented, the easier the code is to use and the more users we can have.

If you want to contribute by documenting code, you have come to the right place.

SHARPy is documented using Sphinx and it extracts the documentation directly from the source code. It is then sorted into directories automatically and a human readable website generated. The amount of work you need to do is minimal. That said, the recipe for a successfully documented class, function, module is the following:

  1. Your documentation has to be written in ReStructuredText (rst). I know, another language… hence I will leave a few tips:

    • Inline code is written using two backticks ``

    • Inline math is written as :math:`1+\exp^{i\pi} = 0`. Don’t forget the backticks!

    • Math in a single or multiple lines is simple:

          .. math:: 1 + \exp{i\pi} = 0
      
    • Lists in ReStructuredText are tricky, I must admit. Therefore, I will link to some examples. The key resides in not forgetting the spaces, in particular when you go onto a second line!

    • The definite example list can be found here.

  2. Titles and docstrings, the bare minimum:

    • Start docstrings with r such that they are interpreted raw:

      r"""
      My docstring
      """
      
    • All functions, modules and classes should be given a title that goes in the first line of the docstring

    • If you are writing a whole package with an __init__.py file, even if it’s empty, give it a human readable docstring. This will then be imported into the documentation

    • For modules with several functions, the module docstring has to be at the very top of the file, prior to the import statements.

  3. We use the Google documentation style. See description.

  4. Function arguments and returns:

    • Function arguments are simple to describe:

      def func(arg1, arg2):
      """Summary line.
      
      Extended description of function.
      
      Args:
        arg1 (int): Description of arg1
        arg2 (str): Description of arg2
      
      Returns:
        bool: Description of return value
      
      """
      return True
      
  5. Solver settings:

    • If your code has a settings dictionary, with defaults and types then make sure that:

      • They are defined as class variables and not instance attributes.

      • Define a settings_types, settings_default and settings_description dictionaries.

      • After all your settings, update the docstring with the automatically generated settings table. You will need to import the sharpy.utils.settings module

        settings_types = dict()
        settings_default = dict()
        settings_description = dict()
        
        # keep adding settings
        
        settings_table = sharpy.utils.settings.SettingsTable()
        __doc__ += settings_table.generate(settings_types, settings_default ,settings_description)
        
  6. See how your docs looks like!

    • Once you are done, run the following SHARPy command:
    sharpy any_string -d
    
    • If you are making minor updates to docstrings (i.e. you are not documenting a previously undocumented function/class/module) you can simply change directory to sharpy/docs and run
    make html
    
    • Your documentation will compile and warnings will appear etc. You can check the result by opening
    docs/build/index.html
    

    and navigating to your recently created page.

    • Make sure that before committing any changes in the documentation you update the entire docs directory by running
    sharpy any_string -d
    

Thank you for reading through this and contributing to make SHARPy a better documented, more user friendly code!

Git branching model

For the development of SHARPy, we try to follow this branching model summarised by the schematic

https://nvie.com/img/git-model@2x.pngBranchingModel Credit: Vincent Driessen https://nvie.com/posts/a-successful-git-branching-model/

Therefore, attending to this model our branches have the following versions of the code:

  • master: latest stable release - paired with the appropriate tag.
  • develop: latest stable development build. Features get merged to develop.
  • rc-**: release candidate branch. Prior to releasing tests are performed on this branch.
  • dev_doc: documentation development branch. All work relating to documentation gets done here.
  • fix_**: hotfix branch.
  • dev_**: feature development branch.

If you contribute, please make sure you know what branch to work from. If in doubt please ask!

The SHARPy Case files

SHARPy takes as input a series of .h5 files that contain the numerical data and a .sharpy file that contains the settings for each of the solvers. How these files are generated is at the user’s discretion, though templates are provided, and all methods are valid as long as the required variables are provided with the appropriate format.

Modular Framework

SHARPy is built with a modular framework in mind. The following diagram shows the strutuctre of a nonlinear, time marching aeroelastic simulation

SHARPy's modular structure

Each of the blocks correspond to individual solvers with specific settings. How we choose which solvers to run, in which order and with what settings is done through the solver configuration file, explained in the next section.

Solver configuration file

The solver configuration file is the main input to SHARPy. It is a ConfigObj formatted file with the .sharpy extension. It contains the settings for each of the solvers and the order in which to run them.

A typical way to assemble the solver configuration file is to place all your desired settings in a dictionary and then convert to and write your ConfigObj. If a setting is not provided the default value will be used. The settings that each solver takes, its type and default value are explained in their relevant documentation pages.

import configobj
filename = '<case_route>/<case_name>.sharpy'
config = configobj.ConfigObj()
config.filename = filename
config['SHARPy'] = {'case': '<your SHARPy case name>',  # an example setting
                    # Rest of your settings for the PreSHARPy class
                    }
config['BeamLoader'] = {'orientation': [1., 0., 0.],  # an example setting
                        # Rest of settings for the BeamLoader solver
                        }
# Continue as above for the remainder of solvers that you would like to include

# finally, write the config file
config.write()

The resulting .sharpy file is a plain text file with your specified settings for each of the solvers.

Note that, therefore, if one of your settings is a np.array, it will get transformed into a string of plain text before being read by SHARPy. However, any setting with list(float) specified as its setting type will get converted into a np.array once it is read by SHARPy.

FEM file

The case.fem.h5 file has several components. We go one by one:

  • num_node_elem [int] : number of nodes per element.

    Always 3 in our case (3 nodes per structural elements - quadratic beam elements).

  • num_elem [int] : number of structural elements.

  • num_node [int] : number of nodes.

    For simple structures, it is num_elem*(num_node_elem - 1) - 1. For more complicated ones, you need to calculate it properly.

  • coordinates [num_node, 3]: coordinates of the nodes in body-attached FoR (A).

  • connectivites [num_elem, num_node_elem] : Beam element’s connectivities.

    Every row refers to an element, and the three integers in that row are the indices of the three nodes belonging to that elem. Now, the catch: the ordering is not as you’d think. Order them as [0, 2, 1]. That means, first one, last one, central one. The following image shows the node indices inside the circles representing the nodes, the element indices in blue and the resulting connectivities matrix next to it. Connectivities are tricky when considering complex configurations. Pay attention at the beginning and you’ll save yourself a lot of trouble.

  • stiffness_db [:, 6, 6]: database of stiffness matrices.

    The first dimension has as many elements as different stiffness matrices are in the model.

  • elem_stiffness [num_elem] : array of indices (starting at 0).

    It links every element (index) to the stiffness matrix index in stiffness_db. For example elem_stiffness[0] = 0 ; elem_stiffness[2] = 1 means that the element 0 has a stiffness matrix equal to stiffness_db[0, :, :] , and the second element has a stiffness matrix equal to stiffness_db[1, :, :].

    The shape of a stiffness matrix, \(\mathrm{S}\) is:

    \[\begin{split}\mathrm{S} = \begin{bmatrix} EA & & & & & \\ & GA_y & & & & \\ & & GA_z & & & \\ & & & GJ & & \\ & & & & EI_y & \\ & & & & & EI_z \\ \end{bmatrix}\end{split}\]

    with the cross terms added if needed.

    mass_db and elem_mass follow the same scheme than the stiffness, but the mass matrix is given by:

    \[\begin{split}\mathrm{M} = \begin{bmatrix} m\mathbf{I} & -\tilde{\boldsymbol{\xi}}_{cg}m \\ \tilde{\boldsymbol{\xi}}_{cg}m & \mathbf{J}\\ \end{bmatrix}\end{split}\]

    where \(m\) is the distributed mass per unit length \(kg/m\) , \((\tilde{\bullet})\) is the skew-symmetric matrix of a vector and \(\boldsymbol{\xi}_{cg}\) is the location of the centre of gravity with respect to the elastic axis in MATERIAL (local) FoR. And what is the Material FoR? This is an important point, because all the inputs that move WITH the beam are in material FoR. For example: follower forces, stiffness, mass, lumped masses…

    SHARPy Frames of Reference

    The material frame of reference is noted as \(B\). Essentially, the \(x\) component is tangent to the beam in the increasing node ordering, \(z\) looks up generally and \(y\) is oriented such that the FoR is right handed.

    In the practice (vertical surfaces, structural twist effects…) it is more complicated than this. The only sure thing about \(B\) is that its \(x\) direction is tangent to the beam in the increasing node number direction. However, with just this, we have an infinite number of potential reference frames, with \(y\) and \(z\) being normal to \(x\) but rotating around it. The solution is to indicate a for_delta, or frame of reference delta vector (\(\Delta\)).

    Frame of Reference Delta Vector

    Now we can define unequivocally the material frame of reference. With \(x_B\) and \(\Delta\) defining a plane, \(y_b\) is chosen such that the \(z\) component is oriented upwards with respect to the lifting surface.

    From this definition comes the only constraint to \(\Delta\): it cannot be parallel to \(x_B\).

  • frame_of_reference_delta [num_elem, num_node_elem, 3]: rotation vector to FoR \(B\).

    contains the \(\Delta\) vector in body-attached (\(A\)) frame of reference.

    As a rule of thumb:

    \[\begin{split}\Delta = \begin{cases} [-1, 0, 0], \quad \text{if right wing} \\ [1, 0, 0], \quad \text{if left wing} \\ [0, 1, 0], \quad \text{if fuselage} \\ [-1, 0, 0], \quad \text{if vertical fin} \\ \end{cases}\end{split}\]

    These rules of thumb only work if the nodes increase towards the tip of the surfaces (and the tail in the case of the fuselage).

  • structural_twist [num_elem, num_node_elem]: Element twist.

    Technically not necessary, as the same effect can be achieved with FoR_delta.

  • boundary_conditions [num_node]: boundary conditions.

    An array of integers (np.zeros((num_node, ), dtype=int)) and contains all 0 except for

    • One node NEEDS to have a 1 , this is the reference node. Usually, the first node has 1 and is located in [0, 0, 0]. This makes things much easier.
    • If the node is a tip of a beam (is not attached to 2 elements, but just 1), it needs to have a -1.
  • beam_number [num_elem]: beam index.

    Is another array of integers. Usually you don’t need to modify its value. Leave it at 0.

  • app_forces [num_elem, 6]: applied forces and moments.

    Contains the applied forces app_forces[:, 0:3] and moments app_forces[:, 3:6] in a given node.

    Important points: the forces are given in Material FoR (check above). That means that in a symmetrical model, a thrust force oriented upstream would have the shape [0, T, 0, 0, 0, 0] in the right wing, while the left would be [0, -T, 0, 0, 0, 0]. Likewise, a torsional moment for twisting the wing leading edge up would be [0, 0, 0, M, 0, 0] for the right, and [0, 0, 0, -M, 0, 0] for the left. But careful, because an out-of-plane bending moment (wing tip up) has the same sign (think about it).

  • lumped_mass [:]: lumped masses.

    Is an array with as many masses as needed (in kg this time). Their order is important, as more information is required to implement them in a model.

  • lumped_mass_nodes [:]: Lumped mass nodes.

    Is an array of integers. It contains the index of the nodes related to the masses given in lumped_mass in order.

  • lumped_mass_inertia [:, 3, 3]: Lumped mass inertia.

    Is an array of 3x3 inertial tensors. The relationship is set by the ordering as well.

  • lumped_mass_position [:, 3]: Lumped mass position.

    Is the relative position of the lumped mass with respect to the node (given in lumped_masss_nodes ) coordinates. ATTENTION: the lumped mass is solidly attached to the node, and thus, its position is given in Material FoR.

Aerodynamics file

All the aerodynamic data is contained in case.aero.h5.

It is important to know that the input for aero is usually based on elements (and inside the elements, their nodes). This causes sometimes an overlap in information, as some nodes are shared by two adjacent elements (like in the connectivities graph in the previous section). The easier way of dealing with this is to make sure the data is consistent, so that the properties of the last node of the first element are the same than the first node of the second element.

Item by item:

  • airfoils: Airfoil group.

    In the aero.h5 file, there is a Group called airfoils. The airfoils are stored in this group (which acts as a folder) as a two-column matrix with \(x/c\) and \(y/c\) in each column. They are named '0', '1' , and so on.

  • chords [num_elem, num_node_elem]: Chord

    Is an array with the chords of every airfoil given in an element/node basis.

  • twist [num_elem, num_node_elem]: Twist.

    Has the twist angle in radians. It is implemented as a rotation around the local \(x\) axis.

  • sweep [num_elem, num_node_elem]: Sweep.

    Same here, just a rotation around \(z\).

  • airfoil_distribution_input [num_elem, num_node_elem]: Airfoil distribution.

    Contains the indices of the airfoils that you put previously in airfoils.

  • surface_distribution_input [num_elem]: Surface integer array.

    It contains the index of the surface the element belongs to. Surfaces need to be continuous, so please note that if your beam numbering is not continuous, you need to make a surface per continuous section.

  • surface_m [num_surfaces]: Chordwise panelling.

    Is an integer array with the number of chordwise panels for every surface.

  • m_distribution [string]: Discretisation method.

    Is a string with the chordwise panel distribution. In almost all cases, leave it at uniform.

  • aero_node_input [num_node]: Aerodynamic node definition.

    Is a boolean (True or False) array that indicates if that node has a lifting surface attached to it.

  • elastic_axis [num_elem, num_node_elem]: elastic axis.

    Indicates the elastic axis location with respect to the leading edge as a fraction of the chord of that rib. Note that the elastic axis is already determined, as the beam is fixed now, so this settings controls the location of the lifting surface wrt the beam.

  • control_surface [num_elem, num_node_elem]: Control surface.

    Is an integer array containing -1 if that section has no control surface associated to it, and 0, 1, 2 ... if the section belongs to the control surface 0, 1, 2 ... respectively.

  • control_surface_type [num_control_surface]: Control Surface type.

    Contains 0 if the control surface deflection is static, and 1 is it is dynamic.

  • control_surface_chord [num_control_surface]: Control surface chord.

    Is an INTEGER array with the number of panels belonging to the control surface. For example, if M = 4 and you want your control surface to be \(0.25c\), you need to put 1.

  • control_surface_hinge_coord [num_control_surface]: Control surface hinge coordinate.

    Only necessary for lifting surfaces that are deflected as a whole, like some horizontal tails in some aircraft. Leave it at 0 if you are not modelling this.

  • airfoil_efficiency [num_elem, num_node_elem, 2, 3]: Airfoil efficiency.

    This is an optional setting that introduces a user-defined efficiency and constant terms to the mapping between the aerodynamic forces calculated at the lattice grid and the structural nodes. The formatting of the 4-dimensional array is simple. The first two dimensions correspond to the element index and the local node index. The third index is whether the term is the multiplier to the force 0 or a constant term 1. The final term refers to, in the local, body-attached B frame, the factors and constant terms for: fy, fz, mx. For more information on how these factors are included in the mapping terms see sharpy.aero.utils.mapping.aero2struct_force_mapping().

SHARPy Solvers

The available SHARPy solvers are listed below. Attending to SHARPy’s modular structure, they can be run independently so the order in which you desire to run them is important.

The starting point is the PreSharpy loader. It contains the simulation configuration and which solvers are to be run and in the order that should happen.

Aero Solvers

DynamicUVLM
class sharpy.solvers.dynamicuvlm.DynamicUVLM[source]

Dynamic Aerodynamic Time Domain Simulation

Provides an aerodynamic only simulation in time by time stepping the solution. The type of aerodynamic solver is parsed as a setting.

To Do:
Clean timestep information for memory efficiency

Warning

Under development. Issues encountered when using the linear UVLM as the aerodynamic solver with integration order = 1.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Write status to screen True
structural_solver str Structural solver to use in the coupled simulation None
structural_solver_settings dict Dictionary of settings for the structural solver None
aero_solver str Aerodynamic solver to use in the coupled simulation None
aero_solver_settings dict Dictionary of settings for the aerodynamic solver None
n_time_steps int Number of time steps for the simulation None
dt float Time step None
include_unsteady_force_contribution bool If on, added mass contribution is added to the forces. This depends on the time derivative of the bound circulation. Check filter_gamma_dot in the aero solver False
postprocessors list(str) List of the postprocessors to run at the end of every time step []
postprocessors_settings dict Dictionary with the applicable settings for every psotprocessor. Every postprocessor needs its entry, even if empty {}
NoAero
class sharpy.solvers.noaero.NoAero[source]

Solver to be used with DynamicCoupled when aerodynamics are not of interest

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
       
initialise(data, custom_settings=None)[source]

To be called just once per simulation.

PrescribedUvlm
class sharpy.solvers.prescribeduvlm.PrescribedUvlm[source]

This class runs a prescribed rigid body motion simulation of a rigid aerodynamic body.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Write status to screen True
structural_solver str Structural solver to use in the coupled simulation None
structural_solver_settings dict Dictionary of settings for the structural solver None
aero_solver str Aerodynamic solver to use in the coupled simulation None
aero_solver_settings dict Dictionary of settings for the aerodynamic solver None
n_time_steps int Number of time steps for the simulation None
dt float Time step None
postprocessors list(str) List of the postprocessors to run at the end of every time step []
postprocessors_settings dict Dictionary with the applicable settings for every psotprocessor. Every postprocessor needs its entry, even if empty {}
SHWUvlm
class sharpy.solvers.shwuvlm.SHWUvlm[source]

Steady vortex method assuming helicoidal wake shape

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Output run-time information True
num_cores int Number of cores to used in parallelisation 0
convection_scheme int Convection scheme for the wake (only 2 tested for this solver) 2
dt float time step used to discretise the wake 0.1
iterative_solver bool   False
iterative_tol float   0.0001
iterative_precond bool   False
velocity_field_generator str Name of the velocity field generator SteadyVelocityField
velocity_field_input dict Dictionary of inputs needed by the velocity field generator {}
gamma_dot_filtering int Parameter used to filter gamma dot (only odd numbers bigger than one allowed) 0
rho float Density 1.225
rot_vel float Rotation velocity in rad/s 0.0
rot_axis list(float) Axis of rotation of the wake [1.0, 0.0, 0.0]
rot_center list(float) Center of rotation of the wake [0.0, 0.0, 0.0]
StaticUvlm
class sharpy.solvers.staticuvlm.StaticUvlm[source]

StaticUvlm solver class, inherited from BaseSolver

Aerodynamic solver that runs a UVLM routine to solve the steady or unsteady aerodynamic problem. The aerodynamic problem is posed in the form of an Aerogrid object.

Parameters:
  • data (PreSharpy) – object with problem data
  • custom_settings (dict) – custom settings that override the settings in the solver .txt file. None by default
settings

Name-value pair of settings employed by solver. See Notes for valid combinations

Type:dict
settings_types

Acceptable data types for entries in settings

Type:dict
settings_default

Default values for the available settings

Type:dict
data

object containing the information of the problem

Type:PreSharpy
velocity_generator

object containing the flow conditions information

Type:object

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print info to screen True
horseshoe bool Horseshoe wake modelling for steady simulations. False
num_cores int Number of cores to use in the VLM lib 0
n_rollup int Number of rollup iterations for free wake. Use at least n_rollup > 1.1*m_star 1
rollup_dt float Controls when the AIC matrix is refreshed during the wake rollup 0.1
rollup_aic_refresh int   1
rollup_tolerance float Convergence criterium for rollup wake 0.0001
iterative_solver bool Not in use False
iterative_tol float Not in use 0.0001
iterative_precond bool Not in use False
velocity_field_generator str Name of the velocity field generator to be used in the simulation SteadyVelocityField
velocity_field_input dict Dictionary of settings for the velocity field generator {}
rho float Air density 1.225
next_step()[source]

Updates de aerogrid based on the info of the step, and increases the self.ts counter

StepLinearUVLM
class sharpy.solvers.steplinearuvlm.StepLinearUVLM[source]

Time domain aerodynamic solver that uses a linear UVLM formulation to be used with the solvers.DynamicCoupled solver.

To use this solver, the solver_id = StepLinearUVLM must be given as the name for the aero_solver is the case of an aeroelastic solver, where the setting below would be parsed through aero_solver_settings.

Notes

The integr_order variable refers to the finite differencing scheme used to calculate the bound circulation derivative with respect to time \(\dot{\mathbf{\Gamma}}\). A first order scheme is used when integr_order == 1

\[\dot{\mathbf{\Gamma}}^{n+1} = \frac{\mathbf{\Gamma}^{n+1}-\mathbf{\Gamma}^n}{\Delta t}\]

If integr_order == 2 a higher order scheme is used (but it isn’t exactly second order accurate [1]).

\[\dot{\mathbf{\Gamma}}^{n+1} = \frac{3\mathbf{\Gamma}^{n+1}-4\mathbf{\Gamma}^n + \mathbf{\Gamma}^{n-1}} {2\Delta t}\]

If track_body is True, the UVLM is projected onto a frame U that is:

  • Coincident with G at the linearisation timestep.
  • Thence, rotates by the same quantity as the FoR A.

It is similar to a stability axes and is recommended any time rigid body dynamics are included.

See also

sharpy.sharpy.linear.assembler.linearuvlm.LinearUVLM

References

[1] Maraniello, S., & Palacios, R.. State-Space Realizations and Internal Balancing in Potential-Flow Aerodynamics with Arbitrary Kinematics. AIAA Journal, 57(6), 1–14. 2019. https://doi.org/10.2514/1.J058153

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
dt float Time step 0.1
integr_order int Integration order of the circulation derivative. Either 1 or 2. 2
ScalingDict dict Dictionary of scaling factors to achieve normalised UVLM realisation. {}
remove_predictor bool Remove the predictor term from the UVLM equations True
use_sparse bool Assemble UVLM plant matrix in sparse format True
density float Air density 1.225
track_body bool UVLM inputs and outputs projected to coincide with lattice at linearisation True
track_body_number int Frame of reference number to follow. If -1 track A frame. -1

The settings that ScalingDict accepts are the following:

Name Type Description Default
length float Reference length to be used for UVLM scaling 1.0
speed float Reference speed to be used for UVLM scaling 1.0
density float Reference density to be used for UVLM scaling 1.0
initialise(data, custom_settings=None)[source]

Initialises the Linear UVLM aerodynamic solver and the chosen velocity generator.

Settings are parsed into the standard SHARPy settings format for solvers. It then checks whether there is any previous information about the linearised system (in order for a solution to be restarted without overwriting the linearisation).

If a linearised system does not exist, a linear UVLM system is created linearising about the current time step.

The reference values for the input and output are transformed into column vectors \(\mathbf{u}\) and \(\mathbf{y}\), respectively.

The information pertaining to the linear system is stored in a dictionary self.data.aero.linear within the main data variable.

Parameters:
  • data (PreSharpy) – class containing the problem information
  • custom_settings (dict) – custom settings dictionary
pack_input_vector()[source]

Transform a SHARPy AeroTimestep instance into a column vector containing the input to the linear UVLM system.

\[[\zeta,\, \dot{\zeta}, u_{ext}] \longrightarrow \mathbf{u}\]

If the track_body option is on, the function projects all the input into a frame that:

  1. is equal to the FoR G at time 0 (linearisation point)
  2. rotates as the body frame specified in the track_body_number
Returns:Input vector
Return type:np.ndarray
static pack_state_vector(aero_tstep, aero_tstep_m1, dt, integr_order)[source]

Transform SHARPy Aerotimestep format into column vector containing the state information.

The state vector is of a different form depending on the order of integration chosen. If a second order scheme is chosen, the state includes the bound circulation at the previous timestep, hence the timestep information for the previous timestep shall be parsed.

The transformation is of the form:

  • If integr_order==1:

    \[\mathbf{x}_n = [\mathbf{\Gamma}^T_n,\, \mathbf{\Gamma_w}_n^T,\, \Delta t \,\mathbf{\dot{\Gamma}}_n^T]^T\]
  • Else, if integr_order==2:

    \[\mathbf{x}_n = [\mathbf{\Gamma}_n^T,\, \mathbf{\Gamma_w}_n^T,\, \Delta t \,\mathbf{\dot{\Gamma}}_n^T,\, \mathbf{\Gamma}_{n-1}^T]^T\]

For the second order integration scheme, if the previous timestep information is not parsed, a first order stencil is employed to estimate the bound circulation at the previous timestep:

\[\mathbf{\Gamma}^{n-1} = \mathbf{\Gamma}^n - \Delta t \mathbf{\dot{\Gamma}}^n\]
Parameters:
Returns:

State vector

Return type:

np.ndarray

run(aero_tstep, structure_tstep, convect_wake=False, dt=None, t=None, unsteady_contribution=False)[source]

Solve the linear aerodynamic UVLM model at the current time step n. The step increment is solved as:

\[\begin{split}\mathbf{x}^n &= \mathbf{A\,x}^{n-1} + \mathbf{B\,u}^n \\ \mathbf{y}^n &= \mathbf{C\,x}^n + \mathbf{D\,u}^n\end{split}\]

A change of state is possible in order to solve the system without the predictor term. In which case the system is solved by:

\[\begin{split}\mathbf{h}^n &= \mathbf{A\,h}^{n-1} + \mathbf{B\,u}^{n-1} \\ \mathbf{y}^n &= \mathbf{C\,h}^n + \mathbf{D\,u}^n\end{split}\]

Variations are taken with respect to initial reference state. The state and input vectors for the linear UVLM system are of the form:

If integr_order==1:
\[\mathbf{x}_n = [\delta\mathbf{\Gamma}^T_n,\, \delta\mathbf{\Gamma_w}_n^T,\, \Delta t \,\delta\mathbf{\dot{\Gamma}}_n^T]^T\]
Else, if integr_order==2:
\[\mathbf{x}_n = [\delta\mathbf{\Gamma}_n^T,\, \delta\mathbf{\Gamma_w}_n^T,\, \Delta t \,\delta\mathbf{\dot{\Gamma}}_n^T,\, \delta\mathbf{\Gamma}_{n-1}^T]^T\]
And the input vector:
\[\mathbf{u}_n = [\delta\mathbf{\zeta}_n^T,\, \delta\dot{\mathbf{\zeta}}_n^T,\,\delta\mathbf{u_{ext}}^T_n]^T\]

where the subscript n refers to the time step.

The linear UVLM system is then solved as detailed in sharpy.linear.src.linuvlm.Dynamic.solve_step(). The output is a column vector containing the aerodynamic forces at the panel vertices.

To Do: option for impulsive start?

Parameters:
  • aero_tstep (AeroTimeStepInfo) – object containing the aerodynamic data at the current time step
  • structure_tstep (StructTimeStepInfo) – object containing the structural data at the current time step
  • convect_wake (bool) – for backward compatibility only. The linear UVLM assumes a frozen wake geometry
  • dt (float) – time increment
  • t (float) – current time
  • unsteady_contribution (bool) – (backward compatibily). Unsteady aerodynamic effects are always included
Returns:

updated self.data class with the new forces and circulation terms of the system

Return type:

PreSharpy

unpack_ss_vectors(y_n, x_n, u_n, aero_tstep)[source]

Transform column vectors used in the state space formulation into SHARPy format

The column vectors are transformed into lists with one entry per aerodynamic surface. Each entry contains a matrix with the quantities at each grid vertex.

\[\mathbf{y}_n \longrightarrow \mathbf{f}_{aero}\]
\[\mathbf{x}_n \longrightarrow \mathbf{\Gamma}_n,\, \mathbf{\Gamma_w}_n,\, \mathbf{\dot{\Gamma}}_n\]

If the track_body option is on, the output forces are projected from the linearization frame, to the G frame. Note that the linearisation frame is:

  1. equal to the FoR G at time 0 (linearisation point)
  2. rotates as the body frame specified in the track_body_number
Parameters:
  • y_n (np.ndarray) – Column output vector of linear UVLM system
  • x_n (np.ndarray) – Column state vector of linear UVLM system
  • u_n (np.ndarray) – Column input vector of linear UVLM system
  • aero_tstep (AeroTimeStepInfo) – aerodynamic timestep information class instance
Returns:

Tuple containing:

forces (list):

Aerodynamic forces in a list with n_surf entries. Each entry is a (6, M+1, N+1) matrix, where the first 3 indices correspond to the components in x, y and z. The latter 3 are zero.

gamma (list):

Bound circulation list with n_surf entries. Circulation is stored in an (M+1, N+1) matrix, corresponding to the panel vertices.

gamma_dot (list):

Bound circulation derivative list with n_surf entries. Circulation derivative is stored in an (M+1, N+1) matrix, corresponding to the panel vertices.

gamma_star (list):

Wake (free) circulation list with n_surf entries. Wake circulation is stored in an (M_star+1, N+1) matrix, corresponding to the panel vertices of the wake.

Return type:

tuple

StepUvlm
class sharpy.solvers.stepuvlm.StepUvlm[source]

StepUVLM is the main solver to use for unsteady aerodynamics.

The desired flow field is injected into the simulation by means of a generator. For a list of available velocity field generators see the documentation page on generators which can be found under SHARPy Source Code.

Typical generators could be:

amongst others.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
print_info bool Print info to screen True  
num_cores int Number of cores to use in the VLM lib 0  
n_time_steps int Number of time steps to be run 100  
convection_scheme int 0: fixed wake, 2: convected with background flow;``3``: full force-free wake 3 0, 2, 3
dt float Time step 0.1  
iterative_solver bool Not in use False  
iterative_tol float Not in use 0.0001  
iterative_precond bool Not in use False  
velocity_field_generator str Name of the velocity field generator to be used in the simulation SteadyVelocityField  
velocity_field_input dict Dictionary of settings for the velocity field generator {}  
gamma_dot_filtering int Filtering parameter for the Welch filter for the Gamma_dot estimation. Used when unsteady_force_contribution is on. 0  
rho float Air density 1.225  
initialise(data, custom_settings=None)[source]

To be called just once per simulation.

run(aero_tstep=None, structure_tstep=None, convect_wake=True, dt=None, t=None, unsteady_contribution=False)[source]

Runs a step of the aerodynamics as implemented in UVLM.

Coupled Solvers

DynamicCoupled
class sharpy.solvers.dynamiccoupled.DynamicCoupled[source]

The DynamicCoupled solver couples the aerodynamic and structural solvers of choice to march forward in time the aeroelastic system’s solution.

Using the DynamicCoupled solver requires that an instance of the StaticCoupled solver is called in the SHARPy solution flow when defining the problem case.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Write status to screen True
structural_solver str Structural solver to use in the coupled simulation None
structural_solver_settings dict Dictionary of settings for the structural solver None
aero_solver str Aerodynamic solver to use in the coupled simulation None
aero_solver_settings dict Dictionary of settings for the aerodynamic solver None
n_time_steps int Number of time steps for the simulation None
dt float Time step None
fsi_substeps int Max iterations in the FSI loop 70
fsi_tolerance float Convergence threshold for the FSI loop 1e-05
structural_substeps int Number of extra structural time steps per aero time step. 0 is a fully coupled simulation. 0
relaxation_factor float Relaxation parameter in the FSI iteration. 0 is no relaxation and -> 1 is very relaxed 0.2
final_relaxation_factor float Relaxation factor reached in relaxation_steps with dynamic_relaxation on 0.0
minimum_steps int Number of minimum FSI iterations before convergence 3
relaxation_steps int Length of the relaxation factor ramp between relaxation_factor and final_relaxation_factor with dynamic_relaxation on 100
dynamic_relaxation bool Controls if relaxation factor is modified during the FSI iteration process False
postprocessors list(str) List of the postprocessors to run at the end of every time step []
postprocessors_settings dict Dictionary with the applicable settings for every psotprocessor. Every postprocessor needs its entry, even if empty {}
controller_id dict Dictionary of id of every controller (key) and its type (value) {}
controller_settings dict Dictionary with settings (value) of every controller id (key) {}
cleanup_previous_solution bool Controls if previous timestep_info arrays are reset before running the solver False
include_unsteady_force_contribution bool If on, added mass contribution is added to the forces. This depends on the time derivative of the bound circulation. Check filter_gamma_dot in the aero solver False
steps_without_unsteady_force int Number of initial timesteps that don’t include unsteady forces contributions. This avoids oscillations due to no perfectly trimmed initial conditions 0
pseudosteps_ramp_unsteady_force int Length of the ramp with which unsteady force contribution is introduced every time step during the FSI iteration process 0
convergence(k, tstep, previous_tstep)[source]

Check convergence in the FSI loop.

Convergence is determined as:

\[\epsilon_q^k = \frac{|| q^k - q^{k - 1} ||}{q^0}\]
\[\epsilon_\dot{q}^k = \frac{|| \dot{q}^k - \dot{q}^{k - 1} ||}{\dot{q}^0}\]

FSI converged if \(\epsilon_q^k < \mathrm{FSI\ tolerance}\) and \(\epsilon_\dot{q}^k < \mathrm{FSI\ tolerance}\)

get_g()[source]

Getter for g, the gravity value

get_rho()[source]

Getter for rho, the density value

initialise(data, custom_settings=None)[source]

Controls the initialisation process of the solver, including processing the settings and initialising the aero and structural solvers, postprocessors and controllers.

static interpolate_timesteps(step0, step1, out_step, coeff)[source]

Performs a linear interpolation between step0 and step1 based on coeff in [0, 1]. 0 means info in out_step == step0 and 1 out_step == step1.

Quantities interpolated: * steady_applied_forces * unsteady_applied_forces * velocity input in Lagrange constraints

process_controller_output(controlled_state)[source]

This function modified the solver properties and parameters as requested from the controller.

This keeps the main loop much cleaner, while allowing for flexibility

Please, if you add options in here, always code the possibility of that specific option not being there without the code complaining to the user.

If it possible, use the same Key for the new setting as for the setting in the solver. For example, if you want to modify the structural_substeps variable in settings, use that Key in the info dictionary.

As a convention: a value of None returns the value to the initial one specified in settings, while the key not being in the dict is ignored, so if any change was made before, it will stay there.

run()[source]

Run the time stepping procedure with controllers and postprocessors included.

set_g(new_g)[source]

Setter for g, the gravity value

set_rho(new_rho)[source]

Setter for rho, the density value

LinDynamicSim
class sharpy.solvers.lindynamicsim.LinDynamicSim[source]

Time-domain solution of Linear Time Invariant Systems

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Output directory ./output/
write_dat list(str) List of vectors to write: x, y, u and/or t []
reference_velocity float Velocity to scale the structural equations when using a non-dimensional system 1.0
n_tsteps int Number of time steps to run 10
physical_time float Time to run 2.0
dt float Time increment for the solution of systems without a specified dt 0.001
postprocessors list(str)   []
postprocessors_settings dict   {}
RigidDynamicPrescribedStep
class sharpy.solvers.rigiddynamicprescribedstep.RigidDynamicPrescribedStep[source]

@modified Alfonso del Carre

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
dt float Time step of simulation 0.01
num_steps int Number of timesteps to be run 500
StaticCoupled
class sharpy.solvers.staticcoupled.StaticCoupled[source]

This class is the main FSI driver for static simulations. It requires a structural_solver and a aero_solver to be defined.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Write status to screen True
structural_solver str Structural solver to use in the coupled simulation None
structural_solver_settings dict Dictionary of settings for the structural solver None
aero_solver str Aerodynamic solver to use in the coupled simulation None
aero_solver_settings dict Dictionary of settings for the aerodynamic solver None
max_iter int Max iterations in the FSI loop 100
n_load_steps int Length of ramp for forces and gravity during FSI iteration 0
tolerance float Convergence threshold for the FSI loop 1e-05
relaxation_factor float Relaxation parameter in the FSI iteration. 0 is no relaxation and -> 1 is very relaxed 0.0
StaticCoupledRBM
class sharpy.solvers.staticcoupledrbm.StaticCoupledRBM[source]

Steady coupled solver including rigid body motions

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Output run-time information True
structural_solver str Name of the structural solver used in the computation None
structural_solver_settings dict Dictionary os settings needed by the structural solver None
aero_solver str Name of the aerodynamic solver used in the computation None
aero_solver_settings dict Dictionary os settings needed by the aerodynamic solver None
max_iter int Maximum numeber of FSI iterations 100
n_load_steps int Number of steps to ramp up the application of loads 1
tolerance float FSI tolerance 1e-05
relaxation_factor float Relaxation factor 0.0

Flight dynamics Solvers

StaticTrim
class sharpy.solvers.statictrim.StaticTrim[source]

The StaticTrim solver determines the longitudinal state of trim (equilibrium) for an aeroelastic system in static conditions. It wraps around the desired solver to yield the state of trim of the system, in most cases the StaticCoupled solver.

It calculates the required angle of attack, elevator deflection and thrust required to achieve longitudinal equilibrium. The output angles are shown in degrees.

The results from the trimming iteration can be saved to a text file by using the save_info option.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print info to screen True
solver str Solver to run in trim routine  
solver_settings dict Solver settings dictionary {}
max_iter int Maximum number of iterations of trim routine 100
fz_tolerance float Tolerance in vertical force 0.01
fx_tolerance float Tolerance in horizontal force 0.01
m_tolerance float Tolerance in pitching moment 0.01
tail_cs_index int Index of control surfaces that move to achieve trim 0
thrust_nodes list(int) Nodes at which thrust is applied [0]
initial_alpha float Initial angle of attack 0.0
initial_deflection float Initial control surface deflection 0.0
initial_thrust float Initial thrust setting 0.0
initial_angle_eps float Initial change of control surface deflection 0.05
initial_thrust_eps float Initial thrust setting change 2.0
relaxation_factor float Relaxation factor 0.2
save_info bool Save trim results to text file False
folder str Output location for trim results ./output/
trim_algorithm()[source]

Trim algorithm method

The trim condition is found iteratively.

Returns:array of trim values for angle of attack, control surface deflection and thrust.
Return type:np.array
Trim
class sharpy.solvers.trim.Trim[source]

Trim routine with support for lateral dynamics. It usually struggles much more than the StaticTrim (only longitudinal) solver.

We advise to start with StaticTrim even if you configuration is not totally symmetric.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print info to screen True
solver str Solver to run in trim routine  
solver_settings dict Solver settings dictionary {}
max_iter int Maximum number of iterations of trim routine 100
tolerance float Threshold for convergence of trim 0.0001
initial_alpha float Initial angle of attack 0.0
initial_beta float Initial sideslip angle 0.0
initial_roll float Initial roll angle 0
cs_indices list(int) Indices of control surfaces to be trimmed []
initial_cs_deflection list(float) Initial deflection of the control surfaces in order. []
thrust_nodes list(int) Nodes at which thrust is applied [0]
initial_thrust list(float) Initial thrust setting [1.0]
thrust_direction list(float) Thrust direction setting [0.0, 1.0, 0.0]
special_case dict Extra settings for specific cases such as differential thrust control {}
refine_solution bool If True and the optimiser routine allows for it, the optimiser will try to improve the solution with hybrid methods False

Linear Solvers

LinearAssembler
class sharpy.solvers.linearassembler.LinearAssembler[source]

Warning

Under development - please advise of new features and bugs!

Creates a workspace containing the different linear elements of the state-space.

The user specifies which elements to build sequentially via the linear_system setting.

The most common uses will be:

  • Aerodynamic: sharpy.linear.assembler.LinearUVLM solver
  • Structural: sharpy.linear.assembler.LinearBeam solver
  • Aeroelastic: sharpy.linear.assembler.LinearAeroelastic solver

The solver enables to load a user specific assembly of a state-space by means of the LinearCustom block.

See sharpy.sharpy.linear.assembler.LinearAssembler for a detailed description of each of the state-space assemblies.

Upon assembly of the linear system, the data structure data.linear will be created. The Linear contains the state-space as an attribute. This state space will be the one employed by postprocessors.

Important: running the linear routines requires information on the tangent mass, stiffness and gyroscopic structural matrices therefore the solver solvers.modal.Modal must have been run prior to linearisation. In addition, if the problem includes rigid body velocities, at least one timestep of solvers.DynamicCoupled must have run such that the rigid body velocity is included.

Example:

The typical flow setting used prior to using this solver for an aeroelastic simulation with rigid body dynamics will be similar to:

>>> flow = ['BeamLoader',
>>>        'AerogridLoader',
>>>        'StaticTrim',
>>>        'DynamicCoupled',  # a single time step will suffice
>>>        'Modal',
>>>        'LinearAssembler']

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
linear_system str Name of chosen state space assembly type None
linear_system_settings dict Settings for the desired state space assembler {}
linearisation_tstep int Chosen linearisation time step number from available time steps -1

Loader Solvers

PreSharpy
class sharpy.presharpy.presharpy.PreSharpy(in_settings=None)[source]

The PreSharpy solver is the main loader solver of SHARPy. It takes the admin-like settings for the simulation, including the case name, case route and the list of solvers to run and in which order to run them. This order of solvers is referred to, throughout SHARPy, as the flow setting.

This is a mandatory solver for all simulations at the start so it is never included in the flow setting.

The settings for this solver are parsed through in the configuration file under the header SHARPy. I.e, when you are defining the config file for a simulation, the settings for PreSharpy are included as:

import configobj
filename = '<case_route>/<case_name>.sharpy'
config = configobj.ConfigObj()
config.filename = filename
config['SHARPy'] = {'case': '<your SHARPy case name>',  # an example setting
                    # Rest of your settings for the PreSHARPy class
                    }

The following are the settings that the PreSharpy class takes:

Name Type Description Default
flow list(str) List of the desired solvers’ solver_id to run in sequential order. None
case str Case name default_case_name
route str Route to case files None
write_screen bool Display output on terminal screen. True
write_log bool Write log file False
log_folder str Log folder destination directory  
AerogridLoader
class sharpy.solvers.aerogridloader.AerogridLoader[source]

AerogridLoader class, inherited from BaseSolver

Generates aerodynamic grid based on the input data

Parameters:data (PreSharpy) – ProblemData class structure
settings

Name-value pair of the settings employed by the aerodynamic solver

Type:dict
settings_types

Acceptable types for the values in settings

Type:dict
settings_default

Name-value pair of default values for the aerodynamic settings

Type:dict
data

class structure

Type:ProblemData
aero_file_name

name of the .aero.h5 HDF5 file

Type:str
aero

empty attribute

aero_data_dict

key-value pairs of aerodynamic data

Type:dict

Notes

The control_surface_deflection setting allows the user to use a time specific control surface deflection, should the problem include them. This setting takes a list of strings, each for the required control surface generator.

The control_surface_deflection_generator_settings setting is a list of dictionaries, one for each control surface. The dictionaries specify the settings for the generator DynamicControlSurface. If the relevant control surface is simply static, an empty string should be parsed. See the documentation for DynamicControlSurface generators for accepted key-value pairs as settings.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
unsteady bool Unsteady effects False
aligned_grid bool Align grid True
freestream_dir list(float) Free stream flow direction [1.0, 0.0, 0.0]
mstar int Number of chordwise wake panels 10
control_surface_deflection list(str) List of control surface generators for each control surface []
control_surface_deflection_generator_settings list(dict) List of dictionaries with the settings for each generator []
BeamLoader
class sharpy.solvers.beamloader.BeamLoader[source]

BeamLoader class solver inherited from BaseSolver

Loads the structural beam solver with the specified user settings.

Parameters:data (ProblemData) – class containing the problem information
settings

contains the specific settings for the solver

Type:dict
settings_types

Key value pairs of the accepted types for the settings values

Type:dict
settings_default

Dictionary containing the default solver settings, should none be provided.

Type:dict
data

class containing the data for the problem

Type:ProblemData
fem_file_name

name of the .fem.h5 HDF5 file

Type:str
dyn_file_name

name of the .dyn.h5 HDF5 file

Type:str
fem_data_dict

key-value pairs of FEM data

Type:dict
dyn_data_dict

key-value pairs of data for dynamic problems

Type:dict
structure

Empty attribute

Type:None

Notes

For further reference on Quaternions see: https://en.wikipedia.org/wiki/Quaternion

See also

class sharpy.utils.solver_interface.BaseSolver
class sharpy.structure.models.beam.Beam

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
unsteady bool If True it will be a dynamic problem. The default is usually good for all simulations True
orientation list(float) Initial attitude of the structure given as the quaternion that parametrises the rotation from G to A frames of reference. [1.0, 0, 0, 0]

Structural Solvers

NonLinearDynamic
class sharpy.solvers.nonlineardynamic.NonLinearDynamic[source]

Structural solver used for the dynamic simulation of free-flying structures.

This solver provides an interface to the structural library (xbeam) and updates the structural parameters for every time step of the simulation.

This solver is called as part of a standalone structural simulation.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print output to screen True
max_iterations int Sets maximum number of iterations 100
num_load_steps int   1
delta_curved float   0.01
min_delta float Structural solver tolerance 1e-05
newmark_damp float Sets the Newmark damping coefficient 0.0001
gravity_on bool Flag to include gravitational forces False
gravity float Gravitational acceleration 9.81
relaxation_factor float   0.3
dt float Time step increment 0.01
num_steps int   500
prescribed_motion bool   None
gravity_dir list(float)   [0, 0, 1]
NonLinearDynamicCoupledStep
class sharpy.solvers.nonlineardynamiccoupledstep.NonLinearDynamicCoupledStep[source]

Structural solver used for the dynamic simulation of free-flying structures.

This solver provides an interface to the structural library (xbeam) and updates the structural parameters for every k-th step in the FSI iteration.

This solver can be called as part of a standalone structural simulation or as the structural solver of a coupled aeroelastic simulation.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print output to screen True
max_iterations int Sets maximum number of iterations 100
num_load_steps int   1
delta_curved float   0.01
min_delta float Structural solver tolerance 1e-05
newmark_damp float Sets the Newmark damping coefficient 0.0001
gravity_on bool Flag to include gravitational forces False
gravity float Gravitational acceleration 9.81
relaxation_factor float   0.3
dt float Time step increment 0.01
num_steps int   500
balancing bool   False
initial_velocity_direction list(float) Initial velocity of the reference node given in the inertial FOR [-1.0, 0.0, 0.0]
initial_velocity float Initial velocity magnitude of the reference node 0
NonLinearDynamicMultibody
class sharpy.solvers.nonlineardynamicmultibody.NonLinearDynamicMultibody[source]

Nonlinear dynamic multibody

Nonlinear dynamic step solver for multibody structures.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print output to screen True
max_iterations int Sets maximum number of iterations 100
num_load_steps int   1
delta_curved float   0.01
min_delta float Structural solver tolerance 1e-05
newmark_damp float Sets the Newmark damping coefficient 0.0001
gravity_on bool Flag to include gravitational forces False
gravity float Gravitational acceleration 9.81
relaxation_factor float   0.3
dt float Time step increment 0.01
num_steps int   500
NonLinearDynamicPrescribedStep
class sharpy.solvers.nonlineardynamicprescribedstep.NonLinearDynamicPrescribedStep[source]

Structural solver used for the dynamic simulation of clamped structures or those subject to a prescribed motion.

This solver provides an interface to the structural library (xbeam) and updates the structural parameters for every k-th step in the FSI iteration.

This solver can be called as part of a standalone structural simulation or as the structural solver of a coupled aeroelastic simulation.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print output to screen True
max_iterations int Sets maximum number of iterations 100
num_load_steps int   1
delta_curved float   0.01
min_delta float Structural solver tolerance 1e-05
newmark_damp float Sets the Newmark damping coefficient 0.0001
gravity_on bool Flag to include gravitational forces False
gravity float Gravitational acceleration 9.81
relaxation_factor float   0.3
dt float Time step increment 0.01
num_steps int   500
NonLinearStatic
class sharpy.solvers.nonlinearstatic.NonLinearStatic[source]

Structural solver used for the static simulation of free-flying structures.

This solver provides an interface to the structural library (xbeam) and updates the structural parameters for every k-th step of the FSI iteration.

This solver can be called as part of a standalone structural simulation or as the structural solver of a coupled static aeroelastic simulation.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print output to screen True
max_iterations int Sets maximum number of iterations 100
num_load_steps int   1
delta_curved float   0.01
min_delta float Structural solver tolerance 1e-05
newmark_damp float Sets the Newmark damping coefficient 0.0001
gravity_on bool Flag to include gravitational forces False
gravity float Gravitational acceleration 9.81
relaxation_factor float   0.3
dt float Time step increment 0.01
num_steps int   500
initial_position list(float)   <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fdf3860>
NonLinearStaticMultibody
class sharpy.solvers.nonlinearstaticmultibody.NonLinearStaticMultibody[source]

Nonlinear static multibody

Nonlinear static solver for multibody structures.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print output to screen True
max_iterations int Sets maximum number of iterations 100
num_load_steps int   1
delta_curved float   0.01
min_delta float Structural solver tolerance 1e-05
newmark_damp float Sets the Newmark damping coefficient 0.0001
gravity_on bool Flag to include gravitational forces False
gravity float Gravitational acceleration 9.81
relaxation_factor float   0.3
dt float Time step increment 0.01
num_steps int   500

Post-Processing

AeroForcesCalculator

class sharpy.postproc.aeroforcescalculator.AeroForcesCalculator[source]

Calculates the total aerodynamic forces on the frame of reference A.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Output folder location ./output
write_text_file bool Write txt file with results False
text_file_name str Text file name  
screen_output bool Show results on screen True
unsteady bool Include unsteady contributions False
coefficients bool Calculate aerodynamic coefficients False
q_ref float Reference dynamic pressure 1
S_ref float Reference area 1

AerogridPlot

class sharpy.postproc.aerogridplot.AerogridPlot[source]

Aerodynamic Grid Plotter

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Output folder ./output
include_rbm bool   True
include_forward_motion bool   False
include_applied_forces bool   True
include_unsteady_applied_forces bool   False
minus_m_star int   0
name_prefix str Prefix to add to file name  
u_inf float   0.0
dt float   0.0
include_velocities bool   False
num_cores int   1

AsymptoticStability

class sharpy.postproc.asymptoticstability.AsymptoticStability[source]

Calculates the asymptotic stability properties of the linearised aeroelastic system by computing the corresponding eigenvalues.

To use an iterative eigenvalue solver, the setting iterative_eigvals should be set to on. This will be beneficial when deailing with very large systems. However, the direct method is preferred and more efficient when the system is of a relatively small size (typically around 5000 states).

Warning

The setting modes_to_plot to plot the eigenvectors in Paraview is currently under development.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Output folder ./output
print_info bool Print information and table of eigenvalues False
reference_velocity float Reference velocity at which to compute eigenvalues for scaled systems 1.0
frequency_cutoff float Truncate higher frequency modes. If zero none are truncated 0
export_eigenvalues bool Save eigenvalues and eigenvectors to file. False
display_root_locus bool Show plot with eigenvalues on Argand diagram False
velocity_analysis list(float) List containing min, max and number of velocities to analyse the system []
iterative_eigvals bool Calculate the first num_evals using an iterative solver. False
num_evals int Number of eigenvalues to retain. 200
modes_to_plot list(int) List of mode numbers to simulate and plot []
postprocessors list(str) To be used with modes_to_plot. Under development. []
postprocessors_settings dict To be used with modes_to_plot. Under development. {}
display_root_locus()[source]

Displays root locus diagrams.

Returns the fig and ax handles for further editing.

Returns:ax:
Return type:fig
export_eigenvalues(num_evals)[source]

Saves a num_evals number of eigenvalues and eigenvectors to file. The files are saved in the output directoy and include:

  • eigenvectors.dat: (num_dof, num_evals) array of eigenvectors
  • eigenvalues_r.dat: (num_evals, 1) array of the real part of the eigenvalues
  • eigenvalues_i.dat: (num_evals, 1) array of the imaginary part of the eigenvalues.

The units of the eigenvalues are rad/s

References

Loading and saving complex arrays: https://stackoverflow.com/questions/6494102/how-to-save-and-load-an-array-of-complex-numbers-using-numpy-savetxt/6522396

Parameters:num_evals – Number of eigenvalues to save
mode_time_domain(fact, fact_rbm, mode_num, cycles=2)[source]

Returns a single, scaled mode shape in time domain.

Parameters:
  • fact – Structural deformation scaling
  • fact_rbm – Rigid body motion scaling
  • mode_num – Number of mode to plot
  • cycles – Number of periods/cycles to plot
Returns:

Time domain array and scaled eigenvector in time.

Return type:

tuple

plot_modes()[source]

Warning

Under development

Plot the aeroelastic mode shapes for the first n_modes_to_plot

print_eigenvalues()[source]

Prints the eigenvalues to a table with the corresponding natural frequency, period and damping ratios

run()[source]

Computes the eigenvalues and eigenvectors

Returns:Eigenvalues sorted and frequency truncated eigenvectors (np.ndarray): Corresponding mode shapes
Return type:eigenvalues (np.ndarray)
static sort_eigenvalues(eigenvalues, eigenvectors, frequency_cutoff=0)[source]

Sort continuous-time eigenvalues by order of magnitude.

The conjugate of complex eigenvalues is removed, then if specified, high frequency modes are truncated. Finally, the eigenvalues are sorted by largest to smallest real part.

Parameters:
  • eigenvalues (np.ndarray) – Continuous-time eigenvalues
  • eigenvectors (np.ndarray) – Corresponding right eigenvectors
  • frequency_cutoff (float) – Cutoff frequency for truncation [rad/s]

Returns:

BeamLoads

class sharpy.postproc.beamloads.BeamLoads[source]

Writes to file the total loads acting on the beam elements

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
csv_output bool Write csv file with results False
output_file_name str Output file name beam_loads
folder str Output folder path ./output

BeamPlot

class sharpy.postproc.beamplot.BeamPlot[source]

Plots beam to Paraview format

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Output folder path ./output
include_rbm bool Include frame of reference rigid body motion True
include_FoR bool Include frame of reference variables False
include_applied_forces bool Write beam applied forces True
include_applied_moments bool Write beam applied moments True
name_prefix str Name prefix for files  
output_rbm bool Write csv file with rigid body motion data True

FrequencyResponse

class sharpy.postproc.frequencyresponse.FrequencyResponse[source]

Frequency Response Calculator

Computes the frequency response of a linear system. If a reduced order model has been created, a comparison is made between the two responses.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
folder str Output folder ./output  
print_info bool Write output to screen False  
compute_fom bool Compute frequency response of full order model (use caution if large) False  
load_fom str Folder to locate full order model frequency response data    
frequency_unit str Units of frequency, “w” for rad/s, “k” reduced k w, k
frequency_bounds list(float) Lower and upper frequency bounds in the corresponding unit [0.001, 1]  
num_freqs int Number of frequencies to evaluate 50  
quick_plot bool Produce array of .png plots showing response. Requires matplotlib False  
run()[source]

Get the frequency response of the linear state-space Returns:

PickleData

class sharpy.postproc.pickledata.PickleData[source]

This postprocessor writes the SHARPy data structure in a pickle file, such that classes and methods from SHARPy are retained for restarted solutions or further post-processing.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Folder to output pickle file ./output

SaveData

class sharpy.postproc.savedata.SaveData[source]

The SaveData postprocessor writes the SHARPy variables into hdf5 files. The linear state space files may be saved to .mat if desired instead.

It has options to save the following classes:

  • Aerogrid including sharpy.sharpy.utils.datastructures.AeroTimeStepInfo
  • Beam including sharpy.sharpy.utils.datastructures.StructTimeStepInfo
  • sharpy.solvers.linearassembler.Linear including classes in sharpy.linear.assembler

Notes

This method saves simply the data. If you would like to preserve the SHARPy methods of the relevant classes see also sharpy.solvers.pickledata.PickleData.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
folder str Folder to save data ./output  
save_aero bool Save aerodynamic classes. True  
save_struct bool Save structural classes. True  
save_linear bool Save linear state space system. False  
save_linear_uvlm bool Save linear UVLM state space system. Use with caution when dealing with large systems. False  
skip_attr list(str) List of attributes to skip when writing file ['fortran', 'airfoils', 'airfoil_db', 'settings_types', 'ct_dynamic_forces_list', 'ct_gamma_dot_list', 'ct_gamma_list', 'ct_gamma_star_list', 'ct_normals_list', 'ct_u_ext_list', 'ct_u_ext_star_list', 'ct_zeta_dot_list', 'ct_zeta_list', 'ct_zeta_star_list', 'dynamic_input']  
compress_float bool Compress float False  
format str Save linear state space to hdf5 .h5 or Matlab .mat format. h5 h5, mat

StabilityDerivatives

class sharpy.postproc.stabilityderivatives.StabilityDerivatives[source]

Outputs the stability derivatives of a free-flying aircraft

Warning

Under Development

To Do:
  • Coefficient of stability derivatives
  • Option to output in NED frame

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Display info to screen True
folder str Output directory ./output/
u_inf float Free stream reference velocity 1.0
S_ref float Reference planform area 1.0
b_ref float Reference span 1.0
c_ref float Reference chord 1.0
uvlm_steady_state_transfer_function()[source]

Stability derivatives calculated using the transfer function of the UVLM projected onto the structural degrees of freedom at zero frequency (steady state).

Returns:
matrix containing the steady state values of the transfer function between the force output
(columns) and the velocity / control surface inputs (rows).
Return type:np.array

StallCheck

class sharpy.postproc.stallcheck.StallCheck[source]

Outputs the incidence angle of every panel of the surface.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Print info to screen True
airfoil_stall_angles dict Dictionary of stall angles for each airfoil {}
output_degrees bool Output incidence angles in degrees vs radians False

WriteVariablesTime

class sharpy.postproc.writevariablestime.WriteVariablesTime[source]

Write variables with time

WriteVariablesTime is a class inherited from BaseSolver

It is a postprocessor that outputs the value of variables with time onto a text file.

settings_types

Acceptable data types of the input data

Type:dict
settings_default

Default values for input data should the user not provide them

Type:dict
See the list of arguments
dir

directory to output the information

Type:str

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
folder str Output folder directory ./output/
delimiter str Delimiter to be used in the output file `` ``
FoR_variables list(str) Variables of StructTimeStepInfo associated to the frame of reference to be writen ['']
FoR_number list(int) Number of the A frame of reference to output (for multibody configurations) <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa285f8>
structure_variables list(str) Variables of StructTimeStepInfo associated to the frame of reference to be writen ['']
structure_nodes list(int) Number of the nodes to be writen <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa28668>
aero_panels_variables list(str) Variables of AeroTimeStepInfo associated to panels to be writen ['']
aero_panels_isurf list(int) Number of the panels’ surface to be output <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa286a0>
aero_panels_im list(int) Chordwise index of the panels to be output <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa286d8>
aero_panels_in list(int) Spanwise index of the panels to be output <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa28710>
aero_nodes_variables list(str) Variables of AeroTimeStepInfo associated to nodes to be writen ['']
aero_nodes_isurf list(int) Number of the nodes’ surface to be output <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa28748>
aero_nodes_im list(int) Chordwise index of the nodes to be output <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa28780>
aero_nodes_in list(int) Spanwise index of the nodes to be output <sphinx.ext.autodoc.importer._MockObject object at 0x7fa06fa287b8>
cleanup_old_solution bool Remove the existing files false

SHARPy Source Code

The core SHARPy documentation is found herein.

Note

The docs are still a work in progress and therefore, most functions/classes with which there is not much user interaction are not fully documented. We would appreciate any help by means of you contributing to our growing documentation!

If you feel that a function/class is not well documented and, hence, you cannot use it, feel free to raise an issue so that we can improve it.

Aerodynamic Packages

Models
Aerogrid

Aerogrid contains all the necessary routines to generate an aerodynamic grid based on the input dictionaries.

Aerogrid
class sharpy.aero.models.aerogrid.Aerogrid[source]

Aerogrid is the main object containing information of the grid of panels

It is created by the solver sharpy.solvers.aerogridloader.AerogridLoader

static compute_gamma_dot(dt, tstep, previous_tsteps)[source]

Computes the temporal derivative of circulation (gamma) using finite differences.

It will use a first order approximation for the first evaluation (when len(previous_tsteps) == 1), and then second order ones.

\[\left.\frac{d\Gamma}{dt}\right|^n \approx \lim_{\Delta t \rightarrow 0}\frac{\Gamma^n-\Gamma^{n-1}}{\Delta t}\]

For the second time step and onwards, the following second order approximation is used:

\[\left.\frac{d\Gamma}{dt}\right|^n \approx \lim_{\Delta t \rightarrow 0}\frac{3\Gamma^n -4\Gamma^{n-1}+\Gamma^{n-2}}{2\Delta t}\]
Parameters:
  • dt (float) – delta time for the finite differences
  • tstep (AeroTimeStepInfo) – tstep at time n (current)
  • previous_tsteps (list(AeroTimeStepInfo)) – previous tstep structure in order: [n-N,..., n-2, n-1]
Returns:

first derivative of circulation with respect to time

Return type:

float

See also

class sharpy.utils.datastructures.AeroTimeStepInfo
generate_strip

Returns a strip of panels in A frame of reference, it has to be then rotated to simulate angles of attack, etc

Utilities
Force Mapping Utilities
aero2struct_force_mapping

Maps the aerodynamic forces at the lattice to the structural nodes

The aerodynamic forces from the UVLM are always in the inertial G frame of reference and have to be transformed to the body or local B frame of reference in which the structural forces are defined.

Since the structural nodes and aerodynamic panels are coincident in a spanwise direction, the aerodynamic forces that correspond to a structural node are the summation of the M+1 forces defined at the lattice at that spanwise location.

\[\begin{split}\mathbf{f}_{struct}^B &= \sum\limits_{i=0}^{m+1}C^{BG}\mathbf{f}_{i,aero}^G \\ \mathbf{m}_{struct}^B &= \sum\limits_{i=0}^{m+1}C^{BG}(\mathbf{m}_{i,aero}^G + \tilde{\boldsymbol{\zeta}}^G\mathbf{f}_{i, aero}^G)\end{split}\]

where \(\tilde{\boldsymbol{\zeta}}^G\) is the skew-symmetric matrix of the vector between the lattice grid vertex and the structural node.

It is possible to introduce efficiency and constant terms in the mapping of forces that are user-defined. For more info see efficiency_local_aero2struct_forces().

The efficiency and constant terms are introduced by means of the array airfoil_efficiency in the aero.h5 input file. If this variable has been defined, the function used to map the forces will be efficiency_local_aero2struct_forces(). Else, the standard formulation local_aero2struct_forces() will be used.

param aero_forces:
 Aerodynamic forces from the UVLM in inertial frame of reference
type aero_forces:
 list
param struct2aero_mapping:
 Structural to aerodynamic node mapping
type struct2aero_mapping:
 dict
param zeta:Aerodynamic grid coordinates
type zeta:list
param pos_def:Vector of structural node displacements
type pos_def:np.ndarray
param psi_def:Vector of structural node rotations (CRVs)
type psi_def:np.ndarray
param master:Unused
param conn:Connectivities matrix
type conn:np.ndarray
param cag:Transformation matrix between inertial and body-attached reference A
type cag:np.ndarray
param aero_dict:
 Dictionary containing the grid’s information.
type aero_dict:dict
returns:structural forces in an n_node x 6 vector
rtype:np.ndarray
efficiency_local_aero2struct_forces

Maps the local aerodynamic forces at a given vertex to its corresponding structural node, introducing user-defined efficiency and constant value factors.

\[\begin{split}\mathbf{f}_{struct}^B &= \varepsilon^f_0 C^{BG}\mathbf{f}_{i,aero}^G + \varepsilon^f_1\\ \mathbf{m}_{struct}^B &= \varepsilon^m_0 (C^{BG}(\mathbf{m}_{i,aero}^G + \tilde{\boldsymbol{\zeta}}^G\mathbf{f}_{i, aero}^G)) + \varepsilon^m_1\end{split}\]
param local_aero_forces:
 aerodynamic forces and moments at a grid vertex
type local_aero_forces:
 np.ndarray
param chi_g:vector between grid vertex and structural node in inertial frame
type chi_g:np.ndarray
param cbg:transformation matrix between inertial and body frames of reference
type cbg:np.ndarray
param force_efficiency:
 force efficiency matrix for all structural elements. Its size is n_elem x n_node_elem x 2 x 3
type force_efficiency:
 np.ndarray
param moment_efficiency:
 moment efficiency matrix for all structural elements. Its size is n_elem x n_node_elem x 2 x 3
type moment_efficiency:
 np.ndarray
param i_elem:element index
type i_elem:int
param i_local_node:
 local node index within element
type i_local_node:
 int
returns:corresponding aerodynamic force at the structural node from the force and moment at a grid vertex
rtype:np.ndarray
local_aero2struct_forces

Maps the local aerodynamic forces at a given vertex to its corresponding structural node.

\[\begin{split}\mathbf{f}_{struct}^B &= C^{BG}\mathbf{f}_{i,aero}^G\\ \mathbf{m}_{struct}^B &= C^{BG}(\mathbf{m}_{i,aero}^G + \tilde{\boldsymbol{\zeta}}^G\mathbf{f}_{i, aero}^G)\end{split}\]
param local_aero_forces:
 aerodynamic forces and moments at a grid vertex
type local_aero_forces:
 np.ndarray
param chi_g:vector between grid vertex and structural node in inertial frame
type chi_g:np.ndarray
param cbg:transformation matrix between inertial and body frames of reference
type cbg:np.ndarray
param force_efficiency:
 Unused. See efficiency_local_aero2struct_forces().
type force_efficiency:
 np.ndarray
param moment_efficiency:
 Unused. See efficiency_local_aero2struct_forces().
type moment_efficiency:
 np.ndarray
param i_elem:
type i_elem:int
returns:corresponding aerodynamic force at the structural node from the force and moment at a grid vertex
rtype:np.ndarray

Controllers

ControlSurfacePidController
class sharpy.controllers.controlsurfacepidcontroller.ControlSurfacePidController[source]

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
time_history_input_file str Route and file name of the time history of desired state None
P float Proportional gain of the controller None
I float Integral gain of the controller 0.0
D float Differential gain of the controller 0.0
input_type str Quantity used to define the reference state. Supported: pitch None
dt float Time step of the simulation None
controlled_surfaces list(int) Control surface indices to be actuated by this controller None
controlled_surfaces_coeff list(float) Control surface deflection coefficients. For example, for antisymmetric deflections => [1, -1]. [1.0]
write_controller_log bool Write a time history of input, required input, and control True
controller_log_route str Directory where the log will be stored ./output/
control(data, controlled_state)[source]

Main routine of the controller. Input is data (the self.data in the solver), and currrent_state which is a dictionary with [‘structural’, ‘aero’] time steps for the current iteration.

Parameters:
  • data – problem data containing all the information.
  • controlled_statedict with two vars: structural and aero containing the timestep_info that will be returned with the control variables.
Returns:

A dict with structural and aero time steps and control input included.

TakeOffTrajectoryController
class sharpy.controllers.takeofftrajectorycontroller.TakeOffTrajectoryController[source]

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
trajectory_input_file str Route and file name of the trajectory file given as a csv with columns: time, x, y, z None
dt float Time step of the simulation None
trajectory_method str Trajectory controller method. For now, “lagrange” is the supported option lagrange
controlled_constraint str Name of the controlled constraint in the multibody context Usually, it is something like constraint_00. None
controller_log_route str Directory where the log will be stored ./output/
write_controller_log bool Controls if the log from the controller is written or not. True
free_trajectory_structural_solver str If different than and empty string, the structural solver will be changed after the end of the trajectory has been reached  
free_trajectory_structural_substeps int Controls the structural solver structural substeps once the end of the trajectory has been reached 0
initial_ramp_length_structural_substeps int Controls the number of timesteps that are used to increase the structural substeps from 0 10
control(data, controlled_state)[source]

Main routine of the controller. Input is data (the self.data in the solver), and currrent_state which is a dictionary with [‘structural’, ‘aero’] time steps for the current iteration.

Parameters:
  • data – problem data containing all the information.
  • controlled_statedict with two vars: structural and aero containing the timestep_info that will be returned with the control variables.
Returns:

A dict with structural and aero time steps and control input included.

process_trajectory(dxdt=True)[source]

See https://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.interpolate.UnivariateSpline.html

Generators

Velocity field generators prescribe the flow conditions for your problem. For instance, you can have an aircraft at a prescribed fixed location in a velocity field towards the aircraft. Alternatively, you can have a free moving aircraft in a static velocity field.

Dynamic Control Surface generators enable the user to prescribe a certain control surface deflection in time.

BumpVelocityField
class sharpy.generators.bumpvelocityfield.BumpVelocityField[source]

Bump Velocity Field Generator

BumpVelocityField is a class inherited from BaseGenerator

The BumpVelocityField class generates a bump-shaped gust profile velocity field, and the profile has the characteristics specified by the user.

To call this generator, the generator_id = BumpVelocityField shall be used. This is parsed as the value for the velocity_field_generator key in the desired aerodynamic solver’s settings.

The resultant velocity, $w_g$, is calculated as follows:

\[w_g = \frac{w_0}{4}\left( 1 + \cos(\frac{(x - x_0)}{H_x} \right)\left( 1 + \cos(\frac{(y - y_0)}{H_y} \right)\]

Notes

For now, only simulations where the inertial FoR is fixed are supported.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
gust_intensity float Intensity of the gust None
x0 float x location of the centre of the bump 0.0
y0 float y location of the centre of the bump 0.0
hx float Gust gradient in the x direction 1.0
hy float Gust gradient in the y direction 1.0
relative_motion bool When true the gust will move at the prescribed velocity False
u_inf float Free stream velocity None
u_inf_direction list(float) Free stream velocity direction <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070a653c8>
DynamicControlSurface
class sharpy.generators.dynamiccontrolsurface.DynamicControlSurface[source]

Dynamic Control Surface deflection Generator

DynamicControlSurface class inherited from BaseGenerator

The object generates a deflection in radians based on the time series given as a vector in the input data

To call this generator, the generator_id = DynamicControlSurface shall be used. This is parsed as the value for the control_surface_deflection_generator key in the aerogridloader solver’s settings.

Parameters:in_dict (dict) –

Input data in the form of dictionary. See acceptable entries below.

Name Type Description Default
dt float Timestep for the simulation None
deflection_file str Relative path to the file with the deflection information. None
settings_types

Acceptable data types of the input data

Type:dict
settings_default

Default values for input data should the user not provide them

Type:dict
deflection

Array of deflection of the control surface

Type:np.array
deflection_dot

Array of the time derivative of the cs deflection. Calculated using 1st order finite differences.

Type:np.array

See also

class sharpy.utils.generator_interface.BaseGenerator
GridBox
class sharpy.generators.gridbox.GridBox[source]

Generatex a grid within a box to be used to generate the flow field during the postprocessing

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
coords_0 list(float) First bounding box corner [0.0, 0.0, 0.0]
coords_1 list(float) Second bounding box corner [10.0, 0.0, 10.0]
spacing list(float) Spacing parameters of the bbox [1.0, 1.0, 1.0]
moving bool If True, the box moves with the body frame of reference. It does not rotate with it, though False
Gust Velocity Field Generators

These generators are used to create a gust velocity field. GustVelocityField is the main class that should be parsed as the velocity_field_input to the desired aerodynamic solver.

The remaining classes are the specific gust profiles and parsed as gust_shape.

Examples:

The typical input to the aerodynamic solver settings would therefore read similar to:

>>> aero_settings = {'<some_aero_settings>': '<some_aero_settings>',
>>>                  'velocity_field_generator': 'GustVelocityField',
>>>                  'velocity_field_input': {'u_inf': 1,
>>>                                           'gust_shape': '<desired_gust>',
>>>                                           'gust_parameters': '<gust_settings>'}}
DARPA
class sharpy.generators.gustvelocityfield.DARPA[source]

Discrete, non-uniform span model

\[U_z = \frac{u_{de}}{2}\left[1-\cos\left(\frac{2\pi x}{S}\right)\right]\cos\left(\frac{\pi y}{b}\right)\]

This gust can be used by using the setting gust_shape = 'DARPA' in GustVelocityField.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
gust_length float Length of gust 0.0
gust_intensity float Intensity of the gust 0.0
span float Wing span 0.0
GustVelocityField
class sharpy.generators.gustvelocityfield.GustVelocityField[source]

Gust Velocity Field Generator

GustVelocityField is a class inherited from BaseGenerator

The GustVelocityField class generates a gust profile velocity field, and the profile has the characteristics specified by the user.

To call this generator, the generator_id = GustVelocityField shall be used. This is parsed as the value for the velocity_field_generator key in the desired aerodynamic solver’s settings.

Notation: \(u_{de}\) is the gust intensity, \(S\) is the gust length and \(b\) is the wing span. \(x\) and \(y\) refer to the chordwise and spanwise distance penetrated into the gust, respectively.

Several gust profiles are available. Your chosen gust profile should be parsed to gust_shape and the corresponding settings as a dictionary to gust_parameters.

This generator takes the following settings

Name Type Description Default
u_inf float Free stream velocity None
u_inf_direction list(float) Free stream velocity relative component [1.0, 0.0, 0.0]
offset float Spatial offset of the gust with respect to origin 0.0
relative_motion bool If true, the gust is convected with u_inf False
gust_shape str Gust profile shape None
gust_parameters dict Dictionary of parameters specific of the gust_shape selected {}
continuous_sin
class sharpy.generators.gustvelocityfield.continuous_sin[source]

Continuous sinusoidal gust model

\[U_z = \frac{u_{de}}{2}\sin\left(\frac{2\pi x}{S}\right)\]

This gust can be used by using the setting gust_shape = 'continuous_sin' in GustVelocityField.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
gust_length float Length of gust 0.0
gust_intensity float Intensity of the gust 0.0
lateral_one_minus_cos
class sharpy.generators.gustvelocityfield.lateral_one_minus_cos[source]

This gust can be used by using the setting gust_shape = 'lateral 1-cos' in GustVelocityField.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
gust_length float Length of gust 0.0
gust_intensity float Intensity of the gust 0.0
one_minus_cos
class sharpy.generators.gustvelocityfield.one_minus_cos[source]

One minus cos gust (single bump)

\[U_z = \frac{u_{de}}{2}\left[1-\cos\left(\frac{2\pi x}{S}\right)\right]\]

This gust can be used by using the setting gust_shape = '1-cos' in GustVelocityField.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
gust_length float Length of gust, \(S\). 0.0
gust_intensity float Intensity of the gust \(u_{de}\). 0.0
span_sine
class sharpy.generators.gustvelocityfield.span_sine[source]

This gust can be used by using the setting gust_shape = 'span sine' in GustVelocityField.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
gust_intensity float Intensity of the gust 0.0
span float Wing span 0.0
periods_per_span int Number of times that the sine is repeated in the span of the wing 1
perturbation_dir list(float) Direction in which the perturbation will be applied in A FoR <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070aa7ac8>
span_dir list(float) Direction of the span of the wing <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070aa7400>
span_with_gust float Extension of the span to which the gust will be applied 0.0
time_varying
class sharpy.generators.gustvelocityfield.time_varying[source]

The inflow velocity changes with time but it is uniform in space. It is read from a 4 column file:

\[time[s] \Delta U_x \Delta U_y \Delta U_z\]

This gust can be used by using the setting gust_shape = 'time varying' in :class:.`GustVelocityField`.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
file str File with the information  
time_varying_global
class sharpy.generators.gustvelocityfield.time_varying_global[source]

Similar to the previous one but the velocity changes instanteneously in the whole flow field. It is not fed into the solid.

This gust can be used by using the setting gust_shape = 'time varying global' in GustVelocityField.

The GustVelocityField generator takes the following settings as a dictionary assignedto gust_parameters.

Name Type Description Default
file str File with the information (only for time varying)  
ShearVelocityField
class sharpy.generators.shearvelocityfield.ShearVelocityField[source]

Shear Velocity Field Generator

ShearVelocityField class inherited from BaseGenerator

The object creates a steady velocity field with shear

\[\hat{u} = \hat{u}\_\infty \left( \frac{h - h\_\mathrm{corr}}{h\_\mathrm{ref}} \right)^{\mathrm{shear}\_\mathrm{exp}}\]
\[h = \zeta \cdot \mathrm{shear}\_\mathrm{direction}\]

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
u_inf float Free stream velocity magnitude None
u_inf_direction list(float) x, y and z relative components of the free stream velocity <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070a65908>
shear_direction list(float) x, y and z relative components of the direction along which shear applies <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070a65198>
shear_exp float Exponent of the shear law 0.0
h_ref float Reference height at which u_inf is defined 1.0
h_corr float Height to correct shear law 0.0
SteadyVelocityField
class sharpy.generators.steadyvelocityfield.SteadyVelocityField[source]

Steady Velocity Field Generator

SteadyVelocityField class inherited from BaseGenerator

The object creates a steady velocity field with the velocity and flow direction specified by the user.

To call this generator, the generator_id = SteadyVelocityField shall be used. This is parsed as the value for the velocity_field_generator key in the desired aerodynamic solver’s settings.

Parameters:in_dict (dict) –

Input data in the form of dictionary. See acceptable entries below:

Name Type Description Default
u_inf float Free stream velocity magnitude 0
u_inf_direction list(float) x, y and z relative components of the free stream velocity [1.0, 0.0, 0.0]
settings_types

Acceptable data types of the input data

Type:dict
settings_default

Default values for input data should the user not provide them

Type:dict
u_inf

Free stream velocity selection

Type:float
u_inf_direction

x, y and z relative contributions to the free stream velocity

Type:list(float)

See also

class sharpy.utils.generator_interface.BaseGenerator
TrajectoryGenerator
class sharpy.generators.trajectorygenerator.TrajectoryGenerator[source]

TrajectoryGenerator is used to generate nodal positions or velocities for trajectory constraints such as the ones included in the multibody solver.

It is usually called from a Controller module.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
angle_end float Trajectory angle wrt horizontal at release 0.0
veloc_end float Release velocity at release None
shape str Shape of the z vs x function. quadratic or linear are supported quadratic
acceleration str Acceleration law, possible values are linear or constant linear
dt float Time step of the simulation None
coords_end list(float) Coordinates of the final ramp point None
plot bool Plot the ramp shape. Requires matplotlib installed False
print_info bool Print information on runtime False
time_offset float Time interval before the start of the ramp acceleration 0.0
offset list(float) Coordinates of the starting point of the simulation <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070aa70f0>
return_velocity bool If True, nodal velocities are given, if False, coordinates are the output False
TurbVelocityField
class sharpy.generators.turbvelocityfield.TurbVelocityField[source]

Turbulent Velocity Field Generator

TurbVelocitityField is a class inherited from BaseGenerator

The TurbVelocitityField class generates a velocity field based on the input from an [XDMF](http://www.xdmf.org) file. It supports time-dependant fields as well as frozen turbulence.

To call this generator, the generator_id = TurbVelocityField shall be used. This is parsed as the value for the velocity_field_generator key in the desired aerodynamic solver’s settings.

Supported files:
  • field_id.xdmf: Steady or Unsteady XDMF file

This generator also performs time interpolation between two different time steps. For now, only linear interpolation is possible.

Space interpolation is done through scipy.interpolate trilinear interpolation. However, turbulent fields are read directly from the binary file and not copied into memory. This is performed using np.memmap. The overhead of this procedure is ~18% for the interpolation stage, however, initially reading the binary velocity field (which will be much more common with time-domain simulations) is faster by a factor of 1e4. Also, memory savings are quite substantial: from 6Gb for a typical field to a handful of megabytes for the whole program.

Parameters:in_dict (dict) – Input data in the form of dictionary. See acceptable entries below:

Attributes:

See also

class sharpy.utils.generator_interface.BaseGenerator

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Output solver-specific information in runtime. True
turbulent_field str XDMF file path of the velocity field None
offset list(float) Spatial offset in the 3 dimensions <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070b1e748>
centre_y bool Flat for changing the domain to [-y_max/2, y_max/2] True
periodicity str Axes in which periodicity is enforced xy
frozen bool If True, the turbulent field will not be updated in time True
store_field bool If True, the xdmf snapshots are stored in memory. Only two at a time for the linear interpolation False
read_btl(in_file)[source]

Legacy function, not using the custom format based on HDF5 anymore.

read_grid(i_grid, i_cache=0)[source]

This function returns an interpolator list of size 3 made of scipy.interpolate.RegularGridInterpolator objects.

read_xdmf(in_file)[source]

Reads the xml file <case_name>.xdmf. Writes the self.grid_data data structure with all the information necessary.

Note: this function does not load any turbulence data (such as ux000, …), it only reads the header information contained in the xdmf file.

TurbVelocityFieldBts
class sharpy.generators.turbvelocityfieldbts.TurbVelocityFieldBts[source]

Turbulent Velocity Field Generator from TurbSim bts files

TurbVelocitityFieldBts is a class inherited from BaseGenerator

The TurbVelocitityFieldBts class generates a velocity field based on the input from a bts file generated by TurbSim. https://nwtc.nrel.gov/TurbSim

To call this generator, the generator_id = TurbVelocityField shall be used. This is parsed as the value for the velocity_field_generator key in the desired aerodynamic solver’s settings.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
print_info bool Output solver-specific information in runtime True
turbulent_field str BTS file path of the velocity file None
new_orientation str New order of the axes xyz
u_fed list(float) Velocity at which the turbulence field is fed into the solid <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070a65278>
u_out list(float) Velocity to set for points outside the interpolating box <sphinx.ext.autodoc.importer._MockObject object at 0x7fa070a656a0>
case_with_tower bool Does the SHARPy case will include the tower in the simulation? False

Linear SHARPy

The code included herein enables the assembly of linearised state-space systems based on the previous solution of a nonlinear problem that will be used as linearisation reference.

The code is structured in the following way:

  • Assembler: different state-spaces to assemble, from only structural/aerodynamic to fully coupled aeroelastic
  • Src: source code required for the linearisation and utilities for the manipulation of state-space elements

References:

Maraniello, S. , Palacios, R.. State-Space Realizations and Internal Balancing in Potential-Flow Aerodynamics with Arbitrary Kinematics. AIAA Journal, Vol. 57, No.6, June 2019
Assembler
Control surface deflector for linear systems

Control surface deflector for linear systems

LinControlSurfaceDeflector
class sharpy.linear.assembler.lincontrolsurfacedeflector.LinControlSurfaceDeflector[source]

Subsystem that deflects control surfaces for use with linear state space systems

The current version supports only deflections. Future work will include standalone state-space systems to model physical actuators.

assemble()[source]

Warning

Under-development

Will assemble the state-space for an actuator model Returns:

generate(linuvlm=None, tsaero0=None, tsstruct0=None, aero=None, structure=None)[source]

Generates a matrix mapping a linear control surface deflection onto the aerodynamic grid.

The parsing of arguments is temporary since this state space element will include a full actuator model.

The parsing of arguments is optional if the class has been previously initialised.

Parameters:
  • linuvlm
  • tsaero0
  • tsstruct0
  • aero
  • structure

Returns:

der_R_arbitrary_axis_times_v

Linearised rotation vector of the vector v by angle theta about an arbitrary axis u.

The rotation of a vector \(\mathbf{v}\) about the axis \(\mathbf{u}\) by an angle \(\boldsymbol{\theta}\) can be expressed as

\[\mathbf{w} = \mathbf{R}(\mathbf{u}, \theta) \mathbf{v},\]

where \(\mathbf{R}\) is a \(\mathbb{R}^{3\times 3}\) matrix.

This expression can be linearised for it to be included in the linear solver as

\[\delta\mathbf{w} = \frac{\partial}{\partial\theta}\left(\mathbf{R}(\mathbf{u}, \theta_0)\right)\delta\theta\]

The matrix \(\mathbf{R}\) is

\[\begin{split}\mathbf{R} = \begin{bmatrix}\cos \theta +u_{x}^{2}\left(1-\cos \theta \right) & u_{x}u_{y}\left(1-\cos \theta \right)-u_{z}\sin \theta & u_{x}u_{z}\left(1-\cos \theta \right)+u_{y}\sin \theta \\ u_{y}u_{x}\left(1-\cos \theta \right)+u_{z}\sin \theta & \cos \theta +u_{y}^{2}\left(1-\cos \theta \right)& u_{y}u_{z}\left(1-\cos \theta \right)-u_{x}\sin \theta \\ u_{z}u_{x}\left(1-\cos \theta \right)-u_{y}\sin \theta & u_{z}u_{y}\left(1-\cos \theta \right)+u_{x}\sin \theta & \cos \theta +u_{z}^{2}\left(1-\cos \theta \right)\end{bmatrix},\end{split}\]

and its linearised expression becomes

\[\begin{split}\frac{\partial}{\partial\theta}\left(\mathbf{R}(\mathbf{u}, \theta_0)\right) = \begin{bmatrix} -\sin \theta +u_{x}^{2}\sin \theta \mathbf{v}_1 + u_{x}u_{y}\sin \theta-u_{z} \cos \theta \mathbf{v}_2 + u_{x}u_{z}\sin \theta +u_{y}\cos \theta \mathbf{v}_3 \\ u_{y}u_{x}\sin \theta+u_{z}\cos \theta\mathbf{v}_1 -\sin \theta +u_{y}^{2}\sin \theta\mathbf{v}_2 + u_{y}u_{z}\sin \theta-u_{x}\cos \theta\mathbf{v}_3 \\ u_{z}u_{x}\sin \theta-u_{y}\cos \theta\mathbf{v}_1 + u_{z}u_{y}\sin \theta+u_{x}\cos \theta\mathbf{v}_2 -\sin \theta +u_{z}^{2}\sin\theta\mathbf{v}_3\end{bmatrix}_{\theta=\theta_0}\end{split}\]

and is of dimension \(\mathbb{R}^{3\times 1}\).

param u:Arbitrary rotation axis
type u:numpy.ndarray
param theta:Rotation angle (radians)
type theta:float
param v:Vector to rotate
type v:numpy.ndarray
returns:Linearised rotation vector of dimensions \(\mathbb{R}^{3\times 1}\).
rtype:numpy.ndarray
LinearAeroelastic
class sharpy.linear.assembler.linearaeroelastic.LinearAeroelastic[source]

Assemble a linearised aeroelastic system

The aeroelastic system can be seen as the coupling between a linearised aerodynamic system (System 1) and a linearised beam system (System 2).

The coupled system retains inputs and outputs from both systems such that

\[\mathbf{u} = [\mathbf{u}_1;\, \mathbf{u}_2]\]

and the outputs are also ordered in a similar fashion

\[\mathbf{y} = [\mathbf{y}_1;\, \mathbf{y}_2]\]

Reference the individual systems for the particular ordering of the respective input and output variables.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
aero_settings dict Linear UVLM settings None
beam_settings dict Linear Beam settings None
uvlm_filename str Path to .data.h5 file containing UVLM/ROM state space to load  
track_body bool UVLM inputs and outputs projected to coincide with lattice at linearisation True
use_euler bool Parametrise orientations in terms of Euler angles False
assemble()[source]

Assembly of the linearised aeroelastic system.

The UVLM state-space system has already been assembled. Prior to assembling the beam’s first order state-space, the damping and stiffness matrices have to be modified to include the damping and stiffenning terms that arise from the linearisation of the aeordynamic forces with respect to the A frame of reference. See sharpy.linear.src.lin_aeroela.get_gebm2uvlm_gains() for details on the linearisation.

Then the beam is assembled as per the given settings in normalised time if the aerodynamic system has been scaled. The discrete time systems of the UVLM and the beam must have the same time step.

The UVLM inputs and outputs are then projected onto the structural degrees of freedom (obviously with the exception of external gusts and control surfaces). Hence, the gains \(\mathbf{K}_{sa}\) and \(\mathbf{K}_{as}\) are added to the output and input of the UVLM system, respectively. These gains perform the following relation:

\[\begin{split}\begin{bmatrix}\zeta \\ \zeta' \\ u_g \\ \delta \end{bmatrix} = \mathbf{K}_{as} \begin{bmatrix} \eta \\ \eta' \\ u_g \\ \delta \end{bmatrix} =\end{split}\]
\[\mathbf{N}_{nodes} = \mathbf{K}_{sa} \mathbf{f}_{vertices}\]

If the beam is expressed in modal form, the UVLM is further projected onto the beam’s modes to have the following input/output structure:

Returns:

get_gebm2uvlm_gains(data)[source]

Provides:

  • the gain matrices required to connect the linearised GEBM and UVLM
inputs/outputs
  • the stiffening and damping factors to be added to the linearised GEBM equations in order to account for non-zero aerodynamic loads at the linearisation point.

The function produces the gain matrices:

  • Kdisp: gains from GEBM to UVLM grid displacements

  • Kvel_disp: influence of GEBM dofs displacements to UVLM grid velocities.

  • Kvel_vel: influence of GEBM dofs displacements to UVLM grid displacements.

  • Kforces (UVLM->GEBM) dimensions are the transpose than the

    Kdisp and Kvel* matrices. Hence, when allocation this term, ii and jj indices will unintuitively refer to columns and rows,

    respectively.

And the stiffening/damping terms accounting for non-zero aerodynamic forces at the linearisation point:

  • Kss: stiffness factor (flexible dof -> flexible dof) accounting for non-zero forces at the linearisation point.
  • Csr: damping factor (rigid dof -> flexible dof)
  • Crs: damping factor (flexible dof -> rigid dof)
  • Crr: damping factor (rigid dof -> rigid dof)

Stiffening and damping related terms due to the non-zero aerodynamic forces at the linearisation point:

\[\mathbf{F}_{A,n} = C^{AG}(\mathbf{\chi})\sum_j \mathbf{f}_{G,j} \rightarrow \delta\mathbf{F}_{A,n} = C^{AG}_0 \sum_j \delta\mathbf{f}_{G,j} + \frac{\partial}{\partial\chi}(C^{AG}\sum_j \mathbf{f}_{G,j}^0)\delta\chi\]

The term multiplied by the variation in the quaternion, \(\delta\chi\), couples the forces with the rigid body equations and becomes part of \(\mathbf{C}_{sr}\).

Similarly, the linearisation of the moments results in expression that contribute to the stiffness and damping matrices.

\[\mathbf{M}_{B,n} = \sum_j \tilde{X}_B C^{BA}(\Psi)C^{AG}(\chi)\mathbf{f}_{G,j}\]
\[\delta\mathbf{M}_{B,n} = \sum_j \tilde{X}_B\left(C_0^{BG}\delta\mathbf{f}_{G,j} + \frac{\partial}{\partial\Psi}(C^{BA}\delta\mathbf{f}^0_{A,j})\delta\Psi + \frac{\partial}{\partial\chi}(C^{BA}_0 C^{AG} \mathbf{f}_{G,j})\delta\chi\right)\]

The linearised equations of motion for the geometrically exact beam model take the input term \(\delta \mathbf{Q}_n = \{\delta\mathbf{F}_{A,n},\, T_0^T\delta\mathbf{M}_{B,n}\}\), which means that the moments should be provided as \(T^T(\Psi)\mathbf{M}_B\) instead of \(\mathbf{M}_A = C^{AB}\mathbf{M}_B\), where \(T(\Psi)\) is the tangential operator.

\[\delta(T^T\mathbf{M}_B) = T^T_0\delta\mathbf{M}_B + \frac{\partial}{\partial\Psi}(T^T\delta\mathbf{M}_B^0)\delta\Psi\]

is the linearised expression for the moments, where the first term would correspond to the input terms to the beam equations and the second arises due to the non-zero aerodynamic moment at the linearisation point and must be subtracted (since it comes from the forces) to form part of \(\mathbf{K}_{ss}\). In addition, the \(\delta\mathbf{M}_B\) term depends on both \(\delta\Psi\) and \(\delta\chi\), therefore those terms would also contribute to \(\mathbf{K}_{ss}\) and \(\mathbf{C}_{sr}\), respectively.

The contribution from the total forces and moments will be accounted for in \(\mathbf{C}_{rr}\) and \(\mathbf{C}_{rs}\).

\[\delta\mathbf{F}_{tot,A} = \sum_n\left(C^{GA}_0 \sum_j \delta\mathbf{f}_{G,j} + \frac{\partial}{\partial\chi}(C^{AG}\sum_j \mathbf{f}_{G,j}^0)\delta\chi\right)\]

Therefore, after running this method, the beam matrices will be updated as:

>>> K_beam[:flex_dof, :flex_dof] += Kss
>>> C_beam[:flex_dof, -rigid_dof:] += Csr
>>> C_beam[-rigid_dof:, :flex_dof] += Crs
>>> C_beam[-rigid_dof:, -rigid_dof:] += Crr

Track body option

The track_body setting restricts the UVLM grid to linear translation motions and therefore should be used to ensure that the forces are computed using the reference linearisation frame.

The UVLM and beam are linearised about a reference equilibrium condition. The UVLM is defined in the inertial reference frame while the beam employs the body attached frame and therefore a projection from one frame onto another is required during the coupling process.

However, the inputs to the UVLM (i.e. the lattice grid coordinates) are obtained from the beam deformation which is expressed in A frame and therefore the grid coordinates need to be projected onto the inertial frame G. As the beam rotates, the projection onto the G frame of the lattice grid coordinates will result in a grid that is not coincident with that at the linearisation reference and therefore the grid coordinates must be projected onto the original frame, which will be referred to as U. The transformation between the inertial frame G and the U frame is a function of the rotation of the A frame and the original position:

\[C^{UG}(\chi) = C^{GA}(\chi_0)C^{AG}(\chi)\]

Therefore, the grid coordinates obtained in A frame and projected onto the G frame can be transformed to the U frame using

\[\zeta_U = C^{UG}(\chi) \zeta_G\]

which allows the grid lattice coordinates to be projected onto the original linearisation frame.

In a similar fashion, the output lattice vertex forces of the UVLM are defined in the original linearisation frame U and need to be transformed onto the inertial frame G prior to projecting them onto the A frame to use them as the input forces to the beam system.

\[\boldsymbol{f}_G = C^{GU}(\chi)\boldsymbol{f}_U\]

The linearisation of the above relations lead to the following expressions that have to be added to the coupling matrices:

  • Kdisp_vel terms:

    \[\delta\boldsymbol{\zeta}_U= C^{GA}_0 \frac{\partial}{\partial \boldsymbol{\chi}} \left(C^{AG}\boldsymbol{\zeta}_{G,0}\right)\delta\boldsymbol{\chi} + \delta\boldsymbol{\zeta}_G\]
  • Kvel_vel terms:

    \[\delta\dot{\boldsymbol{\zeta}}_U= C^{GA}_0 \frac{\partial}{\partial \boldsymbol{\chi}} \left(C^{AG}\dot{\boldsymbol{\zeta}}_{G,0}\right)\delta\boldsymbol{\chi} + \delta\dot{\boldsymbol{\zeta}}_G\]

The transformation of the forces and moments introduces terms that are functions of the orientation and are included as stiffening and damping terms in the beam’s matrices:

  • Csr damping terms relating to translation forces:

    \[C_{sr}^{tra} -= \frac{\partial}{\partial\boldsymbol{\chi}} \left(C^{GA} C^{AG}_0 \boldsymbol{f}_{G,0}\right)\delta\boldsymbol{\chi}\]
  • Csr damping terms related to moments:

    \[C_{sr}^{rot} -= T^\top\widetilde{\mathbf{X}}_B C^{BG} \frac{\partial}{\partial\boldsymbol{\chi}} \left(C^{GA} C^{AG}_0 \boldsymbol{f}_{G,0}\right)\delta\boldsymbol{\chi}\]

The track_body setting.

When track_body is enabled, the UVLM grid is no longer coincident with the inertial reference frame throughout the simulation but rather it is able to rotate as the A frame rotates. This is to simulate a free flying vehicle, where, for instance, the orientation does not affect the aerodynamics. The UVLM defined in this frame of reference, named U, satisfies the following convention:

  • The U frame is coincident with the G frame at the time of linearisation.
  • The U frame rotates as the A frame rotates.

Transformations related to the U frame of reference:

  • The angle between the U frame and the A frame is always constant and equal to \(\boldsymbol{\Theta}_0\).

  • The angle between the A frame and the G frame is \(\boldsymbol{\Theta}=\boldsymbol{\Theta}_0 + \delta\boldsymbol{\Theta}\)

  • The projection of a vector expressed in the G frame onto the U frame is expressed by:

    \[\boldsymbol{v}^U = C^{GA}_0 C^{AG} \boldsymbol{v}^G\]
  • The reverse, a projection of a vector expressed in the U frame onto the G frame, is expressed by

    \[\boldsymbol{v}^U = C^{GA} C^{AG}_0 \boldsymbol{v}^U\]

The effect this has on the aeroelastic coupling between the UVLM and the structural dynamics is that the orientation and change of orientation of the vehicle has no effect on the aerodynamics. The aerodynamics are solely affected by the contribution of the 6-rigid body velocities (as well as the flexible DOFs velocities).

update(u_infty)[source]

Updates the aeroelastic scaled system with the new reference velocity.

Only the beam equations need updating since the only dependency in the forward flight velocity resides there.

Parameters:u_infty (float) – New reference velocity
Returns:Updated aeroelastic state-space system
Return type:sharpy.linear.src.libss.ss
Linear State Beam Element Class

Linear State Beam Element Class

LinearBeam
class sharpy.linear.assembler.linearbeam.LinearBeam[source]

State space member

Define class for linear state-space realisation of GEBM flexible-body equations from SHARPy timestep_info class and with the nonlinear structural information.

State-space models can be defined in continuous or discrete time (dt required). Modal projection, either on the damped or undamped modal shapes, is also avaiable.

Notes on the settings:

  1. modal_projection={True,False}: determines whether to project the states

    onto modal coordinates. Projection over damped or undamped modal shapes can be obtained selecting:

    • proj_modes = {'damped','undamped'}

    while

    • inout_coords={'modes','nodal'}

    determines whether the modal state-space inputs/outputs are modal coords or nodal degrees-of-freedom. If modes is selected, the Kin and Kout gain matrices are generated to transform nodal to modal dofs

  2. dlti={True,False}: if true, generates discrete-time system.

    The continuous to discrete transformation method is determined by:

    discr_method={ 'newmark',  # Newmark-beta
                        'zoh',              # Zero-order hold
                        'bilinear'} # Bilinear (Tustin) transformation
    

    DLTIs can be obtained directly using the Newmark-\(\beta\) method

    discr_method='newmark' newmark_damp=xx with xx<<1.0

    for full-states descriptions (modal_projection=False) and modal projection over the undamped structural modes (modal_projection=True and proj_modes). The Zero-order holder and bilinear methods, instead, work in all descriptions, but require the continuous state-space equations.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
modal_projection bool Use modal projection True  
inout_coords str Beam state space input/output coordinates nodes nodes, modes
num_modes int Number of modes to retain 10  
discrete_time bool Assemble beam in discrete time True  
dt float Discrete time system integration time step 0.001  
proj_modes str Use undamped or damped modes undamped damped, undamped
discr_method str Discrete time assembly system method: newmark newmark, zoh, bilinear
newmark_damp float Newmark damping value. For systems assembled using newmark 0.0001  
use_euler bool Use euler angles for rigid body parametrisation False  
print_info bool Display information on screen True  
gravity bool Linearise gravitational forces False  
remove_dofs list(str) Remove desired degrees of freedom [] eta, V, W, orient
remove_sym_modes bool Remove symmetric modes if wing is clamped False  
assemble(t_ref=None)[source]

Assemble the beam state-space system.

Parameters:t_ref (float) – Scaling factor to non-dimensionalise the beam’s time step.

Returns:

remove_symmetric_modes()[source]

Removes symmetric modes when the wing is clamped at the midpoint.

It will force the wing tip displacements in z to be postive for all modes.

Updates the mode shapes matrix, the natural frequencies and the number of modes.

unpack_ss_vector(x_n, u_n, struct_tstep)[source]

Warning

Under development. Missing:
  • Accelerations
  • Double check the cartesian rotation vector
  • Tangential operator for the moments

Takes the state \(x = [\eta, \dot{\eta}]\) and input vectors \(u = N\) of a linearised beam and returns a SHARPy timestep instance, including the reference values.

Parameters:
  • x_n (np.ndarray) – Structural beam state vector in nodal space
  • y_n (np.ndarray) – Beam input vector (nodal forces)
  • struct_tstep (utils.datastructures.StructTimeStepInfo) – Reference timestep used for linearisation
Returns:

new timestep with linearised values added to the reference value

Return type:

utils.datastructures.StructTimeStepInfo

LinearGustGenerator
class sharpy.linear.assembler.lineargustassembler.LinearGustGenerator[source]

Reduces the entire gust field input to a user-defined set of more comprehensive inputs

Linear UVLM State Space System

Linear UVLM State Space System

LinearUVLM
class sharpy.linear.assembler.linearuvlm.LinearUVLM[source]

Linear UVLM System Assembler

Produces state-space model of the form

\[\begin{split}\mathbf{x}_{n+1} &= \mathbf{A}\,\mathbf{x}_n + \mathbf{B} \mathbf{u}_{n+1} \\ \mathbf{y}_n &= \mathbf{C}\,\mathbf{x}_n + \mathbf{D} \mathbf{u}_n\end{split}\]

where the state, inputs and outputs are:

\[\mathbf{x}_n = \{ \delta \mathbf{\Gamma}_n,\, \delta \mathbf{\Gamma_{w_n}},\, \Delta t\,\delta\mathbf{\Gamma}'_n,\, \delta\mathbf{\Gamma}_{n-1} \}\]
\[\mathbf{u}_n = \{ \delta\mathbf{\zeta}_n,\, \delta\mathbf{\zeta}'_n,\, \delta\mathbf{u}_{ext,n} \}\]
\[\mathbf{y} = \{\delta\mathbf{f}\}\]

with \(\mathbf{\Gamma}\in\mathbb{R}^{MN}\) being the vector of vortex circulations, \(\mathbf{\zeta}\in\mathbb{R}^{3(M+1)(N+1)}\) the vector of vortex lattice coordinates and \(\mathbf{f}\in\mathbb{R}^{3(M+1)(N+1)}\) the vector of aerodynamic forces and moments. Note that \((\bullet)'\) denotes a derivative with respect to time.

Note that the input is atypically defined at time n+1. If the setting remove_predictor = True the predictor term u_{n+1} is eliminated through the change of state[1]:

\[\begin{split}\mathbf{h}_n &= \mathbf{x}_n - \mathbf{B}\,\mathbf{u}_n \\\end{split}\]

such that:

\[\begin{split}\mathbf{h}_{n+1} &= \mathbf{A}\,\mathbf{h}_n + \mathbf{A\,B}\,\mathbf{u}_n \\ \mathbf{y}_n &= \mathbf{C\,h}_n + (\mathbf{C\,B}+\mathbf{D})\,\mathbf{u}_n\end{split}\]

which only modifies the equivalent \(\mathbf{B}\) and \(\mathbf{D}\) matrices.

The integr_order setting refers to the finite differencing scheme used to calculate the bound circulation derivative with respect to time \(\dot{\mathbf{\Gamma}}\). A first order scheme is used when integr_order == 1

\[\dot{\mathbf{\Gamma}}^{n+1} = \frac{\mathbf{\Gamma}^{n+1}-\mathbf{\Gamma}^n}{\Delta t}\]

If integr_order == 2 a higher order scheme is used (but it isn’t exactly second order accurate [1]).

\[\dot{\mathbf{\Gamma}}^{n+1} = \frac{3\mathbf{\Gamma}^{n+1}-4\mathbf{\Gamma}^n + \mathbf{\Gamma}^{n-1}} {2\Delta t}\]

References

[1] Franklin, GF and Powell, JD. Digital Control of Dynamic Systems, Addison-Wesley Publishing Company, 1980

[2] Maraniello, S., & Palacios, R.. State-Space Realizations and Internal Balancing in Potential-Flow Aerodynamics with Arbitrary Kinematics. AIAA Journal, 57(6), 1–14. 2019. https://doi.org/10.2514/1.J058153

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
dt float Time step 0.1  
integr_order int Integration order of the circulation derivative. 2 1, 2
ScalingDict dict Dictionary of scaling factors to achieve normalised UVLM realisation. {}  
remove_predictor bool Remove the predictor term from the UVLM equations True  
use_sparse bool Assemble UVLM plant matrix in sparse format True  
density float Air density 1.225  
remove_inputs list(str) List of inputs to remove. u_gust to remove external velocity input. [] u_gust
gust_assembler str Selected linear gust assembler.   leading_edge
rom_method list(str) List of model reduction methods to reduce UVLM. []  
rom_method_settings dict Dictionary with settings for the desired ROM methods, where the name of the ROM method is the key to the dictionary {}  

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
length float Reference length to be used for UVLM scaling 1.0  
speed float Reference speed to be used for UVLM scaling 1.0  
density float Reference density to be used for UVLM scaling 1.0  
assemble(track_body=False)[source]

Assembles the linearised UVLM system, removes the desired inputs and adds linearised control surfaces (if present).

With all possible inputs present, these are ordered as

\[\mathbf{u} = [\boldsymbol{\zeta},\,\dot{\boldsymbol{\zeta}},\,\mathbf{w},\,\delta]\]

Control surface inputs are ordered last as:

\[[\delta_1, \delta_2, \dots, \dot{\delta}_1, \dot{\delta_2}]\]
remove_inputs(remove_list=<class 'list'>)[source]

Remove certain inputs from the input vector

To do:
  • Support for block UVLM
Parameters:remove_list (list) – Inputs to remove
unpack_input_vector(u_n)[source]

Unpacks the input vector into the corresponding grid coordinates, velocities and external velocities.

Parameters:u_n (np.ndarray) – UVLM input vector. May contain control surface deflections and external velocities.
Returns:Tuple containing zeta, zeta_dot and u_ext, accounting for the effect of control surfaces.
Return type:tuple
unpack_ss_vector(data, x_n, aero_tstep, track_body=False)[source]

Transform column vectors used in the state space formulation into SHARPy format

The column vectors are transformed into lists with one entry per aerodynamic surface. Each entry contains a matrix with the quantities at each grid vertex.

\[\mathbf{y}_n \longrightarrow \mathbf{f}_{aero}\]
\[\mathbf{x}_n \longrightarrow \mathbf{\Gamma}_n,\, \mathbf{\Gamma_w}_n,\, \mathbf{\dot{\Gamma}}_n\]

If the track_body option is on, the output forces are projected from the linearization frame, to the G frame. Note that the linearisation frame is:

  1. equal to the FoR G at time 0 (linearisation point)
  2. rotates as the body frame specified in the track_body_number
Parameters:
  • y_n (np.ndarray) – Column output vector of linear UVLM system
  • x_n (np.ndarray) – Column state vector of linear UVLM system
  • u_n (np.ndarray) – Column input vector of linear UVLM system
  • aero_tstep (AeroTimeStepInfo) – aerodynamic timestep information class instance
Returns:

Tuple containing:

forces (list):

Aerodynamic forces in a list with n_surf entries. Each entry is a (6, M+1, N+1) matrix, where the first 3 indices correspond to the components in x, y and z. The latter 3 are zero.

gamma (list):

Bound circulation list with n_surf entries. Circulation is stored in an (M+1, N+1) matrix, corresponding to the panel vertices.

gamma_dot (list):

Bound circulation derivative list with n_surf entries. Circulation derivative is stored in an (M+1, N+1) matrix, corresponding to the panel vertices.

gamma_star (list):

Wake (free) circulation list with n_surf entries. Wake circulation is stored in an (M_star+1, N+1) matrix, corresponding to the panel vertices of the wake.

Return type:

tuple

Linearised System Source Code
Assembly of linearised UVLM system
  1. Maraniello, 25 May 2018
Includes:
  • Boundary conditions methods:
    • AICs: allocate aero influence coefficient matrices of multi-surfaces configurations
    • nc_dqcdzeta_Sin_to_Sout: derivative matrix of nc*dQ/dzeta where Q is the induced velocity at the bound collocation points of one surface to another.
    • nc_dqcdzeta_coll: assembles nc_dqcdzeta_coll_Sin_to_Sout matrices in multi-surfaces configurations
    • uc_dncdzeta: assemble derivative matrix dnc/dzeta*Uc at bound collocation points
AICs

Given a list of bound (Surfs) and wake (Surfs_star) instances of surface.AeroGridSurface, returns the list of AIC matrices in the format:

  • AIC_list[ii][jj] contains the AIC from the bound surface Surfs[jj] to

Surfs[ii]. - AIC_star_list[ii][jj] contains the AIC from the wake surface Surfs[jj] to Surfs[ii].

dfqsdgamma_vrel0

Assemble derivative of quasi-steady force w.r.t. gamma with fixed relative velocity - the changes in induced velocities due to gamma are not accounted for. The routine exploits the get_joukovski_qs method insude the AeroGridSurface class

dfqsduinput

Assemble derivative of quasi-steady force w.r.t. external input velocity.

dfqsdvind_gamma

Assemble derivative of quasi-steady force w.r.t. induced velocities changes due to gamma. Note: the routine is memory consuming but avoids unnecessary computations.

dfqsdvind_zeta

Assemble derivative of quasi-steady force w.r.t. induced velocities changes due to zeta.

dfqsdzeta_omega

Assemble derivative of quasi-steady force w.r.t. to zeta The contribution implemented is related with the omega x zeta term call: Der_list = dfqsdzeta_omega(Surfs,Surfs_star)

dfqsdzeta_vrel0

Assemble derivative of quasi-steady force w.r.t. zeta with fixed relative velocity - the changes in induced velocities due to zeta over the surface inducing the velocity are not accounted for. The routine exploits the available relative velocities at the mid-segment points

dfunstdgamma_dot

Computes derivative of unsteady aerodynamic force with respect to changes in circulation.

Note: the function also checks that the first derivative of the circulation at the linearisation point is null. If not, a further contribution to the added mass, depending on the changes in panel area and normal, arises and needs to be implemented.

dvinddzeta

Produces derivatives of induced velocity by Surf_in w.r.t. the zetac point. Derivatives are divided into those associated to the movement of zetac, and to the movement of the Surf_in vertices (DerVert).

If Surf_in is bound (IsBound==True), the circulation over the TE due to the wake is not included in the input.

If Surf_in is a wake (IsBound==False), derivatives w.r.t. collocation points are computed ad the TE contribution on DerVert. In this case, the chordwise paneling Min_bound of the associated input is required so as to calculate Kzeta and correctly allocate the derivative matrix.

The output derivatives are: - Dercoll: 3 x 3 matrix - Dervert: 3 x 3*Kzeta (if Surf_in is a wake, Kzeta is that of the bound)

Warning: zetac must be contiguously stored!

dvinddzeta_cpp

Used by autodoc_mock_imports.

eval_panel_cpp

Used by autodoc_mock_imports.

nc_domegazetadzeta

Produces a list of derivative matrix d(omaga x zeta)/dzeta, where omega is the rotation speed of the A FoR, ASSUMING constant panel norm.

Each list is such that: - the ii-th element is associated to the ii-th bound surface collocation point, and will contain a sub-list such that:

  • the j-th element of the sub-list is the dAIC_dzeta matrices w.r.t. the

zeta d.o.f. of the j-th bound surface.

Hence, DAIC*[ii][jj] will have size K_ii x Kzeta_jj

call: ncDOmegaZetavert = nc_domegazetadzeta(Surfs,Surfs_star)

nc_dqcdzeta

Produces a list of derivative matrix

\[\frac{\partial(\mathcal{A}\boldsymbol{\Gamma}_0)}{\partial\boldsymbol{\zeta}}\]

where \(\mathcal{A}\) is the aerodynamic influence coefficient matrix at the bound surfaces collocation point, assuming constant panel norm.

Each list is such that:

  • the ii-th element is associated to the ii-th bound surface collocation point, and will contain a sub-list such that:

    • the j-th element of the sub-list is the dAIC_dzeta matrices w.r.t. the zeta d.o.f. of the j-th bound surface.

Hence, DAIC*[ii][jj] will have size K_ii x Kzeta_jj

If Merge is True, the derivatives due to collocation points movement are added to Dvert to minimise storage space.

To do:

  • Dcoll is highly sparse, exploit?
nc_dqcdzeta_Sin_to_Sout
Computes derivative matrix of
nc*dQ/dzeta

where Q is the induced velocity induced by bound surface Surf_in onto bound surface Surf_out. The panel normals of Surf_out are constant.

The input/output are: - Der_coll of size (Kout,3*Kzeta_out): derivative due to the movement of collocation point on Surf_out. - Der_vert of size:

  • (Kout,3*Kzeta_in) if Surf_in_bound is True
  • (Kout,3*Kzeta_bound_in) if Surf_in_bound is False; Kzeta_bound_in is

the number of vertices in the bound surface of whom Surf_out is the wake.

Note that: - if Surf_in_bound is False, only the TE movement contributes to Der_vert. - if Surf_in_bound is False, the allocation of Der_coll could be speed-up by scanning only the wake segments along the chordwise direction, as on the others the net circulation is null.

test_wake_prop_term

Test allocation of single term of wake propagation matrix

uc_dncdzeta

Build derivative of

\[\boldsymbol{u}_c\frac{\partial\boldsymbol{n}_c}{\partial\boldsymbol{zeta}}\]

where \(\boldsymbol{u}_c\) is the total velocity at the collocation points.

param Surf:the input can also be a list of surface.AerogridSurface
type Surf:surface.AerogridSurface

References

wake_prop

Assembly of wake propagation matrices, in sparse or dense matrices format

Note: wake propagation matrices are very sparse. Nonetheless, allocation in dense format (from numpy.zeros) or sparse does not have important differences in terms of cpu time and memory used as numpy.zeros does not allocate memory until this is accessed.

Mapping methods for bound surface panels
  1. Maraniello, 19 May 2018
AeroGridMap
class sharpy.linear.src.gridmapping.AeroGridMap(M: number of chord-wise, N: number of span-wise)[source]

Produces mapping between panels, segment and vertices of a surface. Grid elements are identified through the indices (m,n), where:

  • m: chordwise index
  • n: spanwise index

The same indexing is applied to panel, vertices and segments.

Elements: - panels=(M,N) - vertices=(M+1,N+1) - segments: these are divided in segments developing along the chordwise and spanwise directions.

  • chordwise: (M,N+1)
  • spanwise: (M+1,N)

Mapping structures: - Mpv: for each panel (mp,np) returns the chord/span-wise indices of its vertices, (mv,nv). This has size (M,N,4,2) - Mps: maps each panel (mp,np) to the ii-th segment. This has size (M,N,4,2)

# - Mps_extr: for each panel (m,n) returns the indices of the extrema of each side # of the panel.

Note: - mapping matrices are stored as np.int16 or np.int32 arrays

from_panel_to_segments(m: chordwise index, n: spanwise index)[source]

For each panel (m,n) it provides the ms,ns indices of each segment.

from_panel_to_vertices(m: chordwise index, n: spanwise index)[source]

From panel of indices (m,n) to indices of vertices

from_vertex_to_panel(m: chordwise index, n: spanwise index)[source]

Returns the panel for which the vertex is locally numbered as 0,1,2,3. Returns a (4,2) array such that its elements are:

[vv_local,(m,n) of panel]

where vv_local is the local verteix number.

Important: indices -1 are possible is the vertex does not have local index 0,1,2 or 3 with respect to any panel.

map_panels_to_segments()[source]

Mapping from panel of segments. self.Mpv is a (M,N,4,2) array such that:

[m, n, local_segment_number,
chordwise/spanwise index of segment,]
map_panels_to_vertices()[source]

Mapping from panel of vertices. self.Mpv is a (M,N,4,2) array such that its element are:

[m, n, local_vertex_number, spanwise/chordwise indices of vertex]
map_panels_to_vertices_1D_scalar()[source]

Mapping: - FROM: the index of a scalar quantity defined at panel collocation point and stored in 1D array. - TO: index of a scalar quantity defined at vertices and stored in 1D

The Mpv1d_scalar has size (K,4) where:
[1d index of panel, index of vertex 0,1,2 or 3]
map_vertices_to_panels()[source]

Maps from vertices to panels. Produces a (M+1,N+1,4,2) array, associating vertices to panels. Its elements are:

[m vertex,
n vertex,
vertex local index,
chordwise/spanwise panel indices]
map_vertices_to_panels_1D_scalar()[source]

Mapping: - FROM: the index of a scalar quantity defined at vertices and stored in 1D array. - TO: index of a scalar quantity defined at panels and stored in 1D

The Mpv1d_scalar has size (Kzeta,4) where:
[1d index of vertex, index of vertex 0,1,2 or 3 w.r.t. panel]
Defines interpolation methods (geometrically-exact) and matrices (linearisation)

Defines interpolation methods (geometrically-exact) and matrices (linearisation) S. Maraniello, 20 May 2018

get_Wnv_vector

Provide projection matrix from nodal velocities to normal velocity at collocation points

get_Wvc_scalar

Produce scalar interpolation matrix Wvc for state-space realisation.

Important: this will not work for coordinates extrapolation, as it would require information about the panel size. It works for other forces/scalar quantities extrapolation. It assumes the quantity at the collocation point is determined proportionally to the weight associated to each vertex and obtained through get_panel_wcv.

get_panel_wcv

Produces a compact array with weights for bilinear interpolation, where aN,aM in [0,1] are distances in the chordwise and spanwise directions such that:

  • (aM,aN)=(0,0) –> quantity at vertex 0
  • (aM,aN)=(1,0) –> quantity at vertex 1
  • (aM,aN)=(1,1) –> quantity at vertex 2
  • (aM,aN)=(0,1) –> quantity at vertex 3
Induced Velocity Derivatives

Calculate derivatives of induced velocity.

Methods:

  • eval_seg_exp and eval_seg_exp_loop: profide ders in format

    [Q_{x,y,z},ZetaPoint_{x,y,z}]

    and use fully-expanded analytical formula.

  • eval_panel_exp: iterates through whole panel

  • eval_seg_comp and eval_seg_comp_loop: profide ders in format

    [Q_{x,y,z},ZetaPoint_{x,y,z}]

    and use compact analytical formula.

Dvcross_by_skew3d

Used by autodoc_mock_imports.

eval_panel_comp

Used by autodoc_mock_imports.

eval_panel_cpp

Used by autodoc_mock_imports.

eval_panel_exp

Used by autodoc_mock_imports.

eval_panel_fast

Used by autodoc_mock_imports.

eval_panel_fast_coll

Used by autodoc_mock_imports.

eval_seg_comp_loop

Used by autodoc_mock_imports.

eval_seg_exp

Used by autodoc_mock_imports.

eval_seg_exp_loop

Used by autodoc_mock_imports.

Induced Velocity Derivatives with respect to Panel Normal

Calculate derivative of

\[\boldsymbol{u}_c\frac{\partial\boldsymbol{n}_c}{\partial\boldsymbol{zeta}}\]

with respect to local panel coordinates.

eval

Returns a 4 x 3 array, containing the derivative of Wnc*Uc w.r.t the panel vertices coordinates.

Fitting Tools Library

@author: Salvatore Maraniello

@date: 15 Jan 2018

fitfrd

Wrapper for fitfrd (mag=0) and fitfrdmag (mag=1) functions in continuous and discrete time (if ds in input). Input:

kv,yv: frequency array and frequency response N: order for rational function approximation mag=1,0: Flag for determining method to use dt (optional): sampling time for DLTI systems
get_rfa_res

Returns magnitude of the residual Yfit-Yv of a RFA approximation at each point kv. The coefficients of the approximations are: - cnum=xv[:Nnum] - cdem=xv[Nnum:] where cnum and cden are as per the ‘rfa’ function.

get_rfa_res_norm

Define residual scalar norm of Pade approximation of coefficients cnum=xv[:Nnum] and cden[Nnum:] (see get_rfa_res and rfa function) and time-step ds (if discrete time).

poly_fit

Find best II order fitting polynomial from frequency response Yv over the frequency range kv for both continuous (ds=None) and discrete (ds>0) LTI systems.

Input: - kv: frequency points - Yv: frequency response - dyv,ddyv: frequency responses of I and II order derivatives - method=’leastsq’,’dev’: algorithm for minimisation - Bup (only ‘dev’ method): bounds for bv coefficients as per scipy.optimize.differential_evolution. This is a length 3 array.

Important: - this function attributes equal weight to each data-point!

rfa

Evaluates over the frequency range kv.the rational function approximation: [cnum[-1] + cnum[-2] z + … + cnum[0] z**Nnum ]/…

[cden[-1] + cden[-2] z + … + cden[0] z**Nden]

where the numerator and denominator polynomial orders, Nnum and Nden, are the length of the cnum and cden arrays and:

  • z=exp(1.j*kv*ds), with ds sampling time if ds is given (discrete-time

system) - z=1.*kv, if ds is None (continuous time system)

rfa_fit_dev

Find best fitting RFA approximation from frequency response Yv over the frequency range kv for both continuous (ds=None) and discrete (ds>0) LTI systems.

The RFA approximation is found through a 2-stage strategy:
a. an evolutionary algoryhtm is run to determine the optimal fitting coefficients b. the search is refined through a least squares algorithm.
and is stopped as soon as:
1. the maximum absolute error in frequency response of the RFA falls below TolAbs 2. the maximum number of iterations is reached.

Input: - kv: frequency range for approximation - Yv: frequency response vector over kv - TolAbs: maximum admissible absolute difference in frequency response between RFA and original system. - Nnum,Ndem: number of coefficients for Pade approximation. - ds: sampling time for DLTI systems - NtrialMax: maximum number of repetition of global and least square optimisations - Cfbouds: maximum absolute values of coeffieicnts (only for evolutionary algorithm) - OutFull: if False, only outputs optimal coefficients of RFA. Otherwise,

outputs cost and RFA coefficients of each trial.

Output: - cnopt: optimal coefficients (numerator) - cdopt: optimal coefficients (denominator)

Important: - this function has the same objective as fitfrd in matwrapper module. While generally slower, the global optimisation approach allows to verify the results from fitfrd.

rfa_mimo

Given the frequency response of a MIMO DLTI system, this function returns the A,B,C,D matrices associated to the rational function approximation of the original system.

Input: - Yfull: frequency response (as per libss.freqresp) of full size system over the frequencies kv. - kv: array of frequencies over which the RFA approximation is evaluated. - tolAbs: absolute tolerance for the rfa fitting - Nnum: number of numerator coefficients for RFA - Nden: number of denominator coefficients for RFA - NtrialMax: maximum number of attempts - method=[‘intependent’]. Method used to produce the system:

  • intependent: each input-output combination is treated separately. The

resulting system is a collection of independent SISO DLTIs

rfader

Evaluates over the frequency range kv.the derivative of order m of the rational function approximation: [cnum[-1] + cnum[-2] z + … + cnum[0] z**Nnum ]/…

[cden[-1] + cden[-2] z + … + cden[0] z**Nden]

where the numerator and denominator polynomial orders, Nnum and Nden, are the length of the cnum and cden arrays and:

  • z=exp(1.j*kv*ds), with ds sampling time if ds is given (discrete-time

system) - z=1.*kv, if ds is None (continuous time system)

Collect tools to manipulate sparse and/or mixed dense/sparse matrices.

Collect tools to manipulate sparse and/or mixed dense/sparse matrices.

author: S. Maraniello date: Dec 2018

Comment: manipulating large linear system may require using both dense and sparse matrices. While numpy/scipy automatically handle most operations between mixed dense/sparse arrays, some (e.g. dot product) require more attention. This library collects methods to handle these situations.

Classes: scipy.sparse matrices are wrapped so as to ensure compatibility with numpy arrays upon conversion to dense. - csc_matrix: this is a wrapper of scipy.csc_matrix. - SupportedTypes: types supported for operations - WarningTypes: due to some bugs in scipy (v.1.1.0), sum (+) operations between np.ndarray and scipy.sparse matrices can result in numpy.matrixlib.defmatrix.matrix types. This list contains such undesired types that can result from dense/sparse operations and raises a warning if required. (b) convert these types into numpy.ndarrays.

Methods: - dot: handles matrix dot products across different types. - solve: solves linear systems Ax=b with A and b dense, sparse or mixed. - dense: convert matrix to numpy array

Warning: - only sparse types into SupportedTypes are supported!

To Do: - move these methods into an algebra module?

block_dot

dot product between block matrices.

Inputs: A, B: are nested lists of dense/sparse matrices of compatible shape for block matrices product. Empty blocks can be defined with None. (see numpy.block)

block_sum

dot product between block matrices.

Inputs: A, B: are nested lists of dense/sparse matrices of compatible shape for block matrices product. Empty blocks can be defined with None. (see numpy.block)

csc_matrix
class sharpy.linear.src.libsparse.csc_matrix(arg1, shape=None, dtype=None, copy=False)[source]

Wrapper of scipy.csc_matrix that ensures best compatibility with numpy.ndarray. The following methods have been overwritten to ensure that numpy.ndarray are returned instead of numpy.matrixlib.defmatrix.matrix.

  • todense
  • _add_dense

Warning: this format is memory inefficient to allocate new sparse matrices. Consider using: - scipy.sparse.lil_matrix, which supports slicing, or - scipy.sparse.coo_matrix, though slicing is not supported :(

todense()[source]

As per scipy.spmatrix.todense but returns a numpy.ndarray.

dense

If required, converts sparse array to dense.

dot
Method to compute
C = A*B ,

where * is the matrix product, with dense/sparse/mixed matrices.

The format (sparse or dense) of C is specified through ‘type_out’. If type_out==None, the output format is sparse if both A and B are sparse, dense otherwise.

The following formats are supported: - numpy.ndarray - scipy.csc_matrix

eye_as

Produces an identity matrix as per M, in shape and type

solve
Wrapper of
numpy.linalg.solve and scipy.sparse.linalg.spsolve

for solution of the linear system A x = b. - if A is a dense numpy array np.linalg.solve is called for solution. Note that if B is sparse, this requires convertion to dense. In this case, solution through LU factorisation of A should be considered to exploit the sparsity of B. - if A is sparse, scipy.sparse.linalg.spsolve is used.

zeros_as

Produces an identity matrix as per M, in shape and type

Linear Time Invariant systems

Linear Time Invariant systems author: S. Maraniello date: 15 Sep 2017 (still basement…)

Library of methods to build/manipulate state-space models. The module supports the sparse arrays types defined in libsparse.

The module includes:

Classes: - ss: provides a class to build DLTI/LTI systems with full and/or sparse

matrices and wraps many of the methods in these library. Methods include: - freqresp: wraps the freqresp function - addGain: adds gains in input/output. This is not a wrapper of addGain, as the system matrices are overwritten

Methods for state-space manipulation: - couple: feedback coupling. Does not support sparsity - freqresp: calculate frequency response. Supports sparsity. - series: series connection between systems - parallel: parallel connection between systems - SSconv: convert state-space model with predictions and delays - addGain: add gains to state-space model. - join2: merge two state-space models into one. - join: merge a list of state-space models into one. - sum state-space models and/or gains - scale_SS: scale state-space model - simulate: simulates discrete time solution - Hnorm_from_freq_resp: compute H norm of a frequency response - adjust_phase: remove discontinuities from a frequency response

Special Models: - SSderivative: produces DLTI of a numerical derivative scheme - SSintegr: produces DLTI of an integration scheme - build_SS_poly: build state-space model with polynomial terms.

Filtering: - butter

Utilities: - get_freq_from_eigs: clculate frequency corresponding to eigenvalues

Comments: - the module supports sparse matrices hence relies on libsparse.

to do:
  • remove unnecessary coupling routines
  • couple function can handle sparse matrices but only outputs dense matrices
    • verify if typical coupled systems are sparse
    • update routine
    • add method to automatically determine whether to use sparse or dense?
Hnorm_from_freq_resp

Given a frequency response over a domain kv, this funcion computes the H norms through numerical integration.

Note that if kv[-1]<np.pi/dt, the method assumed gv=0 for each frequency kv[-1]<k<np.pi/dt.

Warning: only use for SISO systems! For MIMO definitions are different

SSconv

Convert a DLTI system with prediction and delay of the form:

\[\begin{split}\mathbf{x}_{n+1} &= \mathbf{A\,x}_n + \mathbf{B_0\,u}_n + \mathbf{B_1\,u}_{n+1} + \mathbf{B_{m1}\,u}_{n-1} \\ \mathbf{y}_n &= \mathbf{C\,x}_n + \mathbf{D\,u}_n\end{split}\]

into the state-space form:

\[\begin{split}\mathbf{h}_{n+1} &= \mathbf{A_h\,h}_n + \mathbf{B_h\,u}_n \\ \mathbf{y}_n &= \mathbf{C_h\,h}_n + \mathbf{D_h\,u}_n\end{split}\]

If \(\mathbf{B_{m1}}\) is None, the original state is retrieved through

\[\mathbf{x}_n = \mathbf{h}_n + \mathbf{B_1\,u}_n\]

and only the \(\mathbf{B}\) and \(\mathbf{D}\) matrices are modified.

If \(\mathbf{B_{m1}}\) is not None, the SS is augmented with the new state

\[\mathbf{g}_{n} = \mathbf{u}_{n-1}\]

or, equivalently, with the equation

\[\mathbf{g}_{n+1} = \mathbf{u}_n\]

leading to the new form

\[\begin{split}\mathbf{H}_{n+1} &= \mathbf{A_A\,H}_{n} + \mathbf{B_B\,u}_n \\ \mathbf{y}_n &= \mathbf{C_C\,H}_{n} + \mathbf{D_D\,u}_n\end{split}\]

where \(\mathbf{H} = (\mathbf{x},\,\mathbf{g})\).

param A:dynamics matrix
type A:np.ndarray
param B0:input matrix for input at current time step n. Set to None if this is zero.
type B0:np.ndarray
param B1:input matrix for input at time step n+1 (predictor term)
type B1:np.ndarray
param C:output matrix
type C:np.ndarray
param D:direct matrix
type D:np.ndarray
param Bm1:input matrix for input at time step n-1 (delay term)
type Bm1:np.ndarray
returns:tuple packed with the state-space matrices \(\mathbf{A},\,\mathbf{B},\,\mathbf{C}\) and \(\mathbf{D}\).
rtype:tuple

References

Franklin, GF and Powell, JD. Digital Control of Dynamic Systems, Addison-Wesley Publishing Company, 1980

Warning

functions untested for delays (Bm1 != 0)

SSderivative

Given a time-step ds, and an single input time history u, this SS model returns the output y=[u,du/ds], where du/dt is computed with second order accuracy.

SSintegr

Builds a state-space model of an integrator.

  • method: Numerical scheme. Available options are:
    • 1tay: 1st order Taylor (fwd)
      I[ii+1,:]=I[ii,:] + ds*F[ii,:]
    • trap: I[ii+1,:]=I[ii,:] + 0.5*dx*(F[ii,:]+F[ii+1,:])

    Note: other option can be constructured if information on derivative of F is available (for e.g.)

addGain

Convert input u or output y of a SS DLTI system through gain matrix K. We have the following transformations: - where=’in’: the input dof of the state-space are changed

u_new -> Kmat*u -> SS -> y => u_new -> SSnew -> y
  • where=’out’: the output dof of the state-space are changed

    u -> SS -> y -> Kmat*u -> ynew => u -> SSnew -> ynew

  • where=’parallel’: the input dofs are changed, but not the output

    {u_1 -> SS -> y_1

    { u_2 -> y_2= Kmat*u_2 => u_new=(u_1,u_2) -> SSnew -> y=y_1+y_2
    {y = y_1+y_2

Warning: function not tested for Kmat stored in sparse format

adjust_phase

Modify the phase y of a frequency response to remove discontinuities.

build_SS_poly

Builds a discrete-time state-space representation of a polynomial system whose frequency response has from:

Ypoly[oo,ii](k) = -A2[oo,ii] D2(k) - A1[oo,ii] D1(k) - A0[oo,ii]

where C1,D2 are discrete-time models of first and second derivatives, ds is the time-step and the coefficient matrices are such that:

A{nn}=Acf[oo,ii,nn]
butter

build MIMO butterworth filter of order ord and cut-off freq over Nyquist freq ratio Wn. The filter will have N input and N output and N*ord states.

Note: the state-space form of the digital filter does not depend on the sampling time, but only on the Wn ratio. As a result, this function only returns the A,B,C,D matrices of the filter state-space form.

compare_ss

Assert matrices of state-space models are identical

couple

Couples 2 dlti systems ss01 and ss02 through the gains K12 and K21, where K12 transforms the output of ss02 into an input of ss01.

Other inputs: - out_sparse: if True, the output system is stored as sparse (not recommended)

freqresp

In-house frequency response function supporting dense/sparse types

Inputs: - SS: instance of ss class, or scipy.signal.StateSpace* - wv: frequency range - dlti: True if discrete-time system is considered.

Outputs: - Yfreq[outputs,inputs,len(wv)]: frequency response over wv

Warnings: - This function may not be very efficient for dense matrices (as A is not reduced to upper Hessenberg form), but can exploit sparsity in the state-space matrices.

get_freq_from_eigs

Compute natural freq corresponding to eigenvalues, eigs, of a continuous or discrete-time (dlti=True) systems.

Note: if dlti=True, the frequency is normalised by (1./dt), where dt is the DLTI time-step - i.e. the frequency in Hertz is obtained by multiplying fn by (1./dt).

join

Given a list of state-space models belonging to the ss class, creates a joined system whose output is the sum of the state-space outputs. If wv is not None, this is a list of weights, such that the output is:

y = sum( wv[ii] y_ii )

Ref: equation (4.22) of Benner, P., Gugercin, S. & Willcox, K., 2015. A Survey of Projection-Based Model Reduction Methods for Parametric Dynamical Systems. SIAM Review, 57(4), pp.483–531.

Warning: - system matrices must be numpy arrays - the function does not perform any check!

join2

Join two state-spaces or gain matrices such that, given:

\[\begin{split}\mathbf{u}_1 \longrightarrow &\mathbf{SS}_1 \longrightarrow \mathbf{y}_1 \\ \mathbf{u}_2 \longrightarrow &\mathbf{SS}_2 \longrightarrow \mathbf{y}_2\end{split}\]

we obtain:

\[\mathbf{u} \longrightarrow \mathbf{SS}_{TOT} \longrightarrow \mathbf{y}\]

with \(\mathbf{u}=(\mathbf{u}_1,\mathbf{u}_2)^T\) and \(\mathbf{y}=(\mathbf{y}_1,\mathbf{y}_2)^T\).

The output \(\mathbf{SS}_{TOT}\) is either a gain matrix or a state-space system according to the input \(\mathbf{SS}_1\) and \(\mathbf{SS}_2\)

param SS1:State space 1 or gain 1
type SS1:scsig.StateSpace or np.ndarray
param SS2:State space 2 or gain 2
type SS2:scsig.StateSpace or np.ndarray
returns:combined state space or gain matrix
rtype:scsig.StateSpace or np.ndarray
parallel

Returns the sum (or parallel connection of two systems). Given two state-space models with the same output, but different input:

u1 –> SS01 –> y u2 –> SS02 –> y
project

Given 2 transformation matrices, (WT,V) of shapes (Nk,self.states) and (self.states,Nk) respectively, this routine returns a projection of the state space ss_here according to:

Anew = WT A V Bnew = WT B Cnew = C V Dnew = D

The projected model has the same number of inputs/outputs as the original one, but Nk states.

random_ss

Define random system from number of states (Nx), inputs (Nu) and output (Ny).

scale_SS

Given a state-space system, scales the equations such that the original input and output, \(u\) and \(y\), are substituted by \(u_{AD}=\frac{u}{u_{ref}}\) and \(y_{AD}=\frac{y}{y_{ref}}\).

If the original system has form:

\[\begin{split}\mathbf{x}^{n+1} &= \mathbf{A\,x}^n + \mathbf{B\,u}^n \\ \mathbf{y}^{n} &= \mathbf{C\,x}^{n} + \mathbf{D\,u}^n\end{split}\]

the transformation is such that:

\[\begin{split}\mathbf{x}^{n+1} &= \mathbf{A\,x}^n + \mathbf{B}\,\frac{u_{ref}}{x_{ref}}\mathbf{u_{AD}}^n \\ \mathbf{y_{AD}}^{n+1} &= \frac{1}{y_{ref}}(\mathbf{C}\,x_{ref}\,\mathbf{x}^{n+1} + \mathbf{D}\,u_{ref}\,\mathbf{u_{AD}}^n)\end{split}\]

By default, the state-space model is manipulated by reference (byref=True)

param SSin:original state-space formulation
type SSin:scsig.dlti
param input_scal:
 input scaling factor \(u_{ref}\). It can be a float or an array, in which case the each element of the input vector will be scaled by a different factor.
type input_scal:
 float or np.ndarray
param output_scal:
 output scaling factor \(y_{ref}\). It can be a float or an array, in which case the each element of the output vector will be scaled by a different factor.
type output_scal:
 float or np.ndarray
param state_scal:
 state scaling factor \(x_{ref}\). It can be a float or an array, in which case the each element of the state vector will be scaled by a different factor.
type state_scal:
 float or np.ndarray
param byref:state space manipulation order
type byref:bool
returns:scaled state space formulation
rtype:scsig.dlti
series

Connects two state-space blocks in series. If these are instances of DLTI state-space systems, they need to have the same type and time-step. If the input systems are sparse, they are converted to dense.

The connection is such that:

\[u \rightarrow \mathsf{SS01} \rightarrow \mathsf{SS02} \rightarrow y \Longrightarrow u \rightarrow \mathsf{SStot} \rightarrow y\]
param SS01:State Space 1 instance. Can be DLTI/CLTI, dense or sparse.
type SS01:libss.ss
param SS02:State Space 2 instance. Can be DLTI/CLTI, dense or sparse.
type SS02:libss.ss
Returns
libss.ss: Combined state space system in series in dense format.
simulate

Routine to simulate response to generic input. @warning: this routine is for testing and may lack of robustness. Use

scipy.signal instead.
ss
class sharpy.linear.src.libss.ss(A, B, C, D, dt=None)[source]

Wrap state-space models allocation into a single class and support both full and sparse matrices. The class emulates

scipy.signal.ltisys.StateSpaceContinuous scipy.signal.ltisys.StateSpaceDiscrete

but supports sparse matrices and other functionalities.

Methods: - get_mats: return matrices as tuple - check_types: check matrices types are supported - freqresp: calculate frequency response over range. - addGain: project inputs/outputs - scale: allows scaling a system

addGain(K, where)[source]

Projects input u or output y the state-space system through the gain matrix K. The input ‘where’ determines whether inputs or outputs are projected as:

  • where=’in’: inputs are projected such that:
    u_new -> u=K*u_new -> SS -> y => u_new -> SSnew -> y
  • where=’out’: outputs are projected such that:
    u -> SS -> y -> y_new=K*y => u -> SSnew -> ynew

Warning: this is not a wrapper of the addGain method in this module, as the state-space matrices are directly overwritten.

freqresp(wv)[source]

Calculate frequency response over frequencies wv

Note: this wraps frequency response function.

inputs

Number of inputs \(m\) to the system.

max_eig()[source]

Returns most unstable eigenvalue

outputs

Number of outputs \(p\) of the system.

project(WT, V)[source]

Given 2 transformation matrices, (WT,V) of shapes (Nk,self.states) and (self.states,Nk) respectively, this routine projects the state space model states according to:

Anew = WT A V Bnew = WT B Cnew = C V Dnew = D

The projected model has the same number of inputs/outputs as the original one, but Nk states.

scale(input_scal=1.0, output_scal=1.0, state_scal=1.0)[source]

Given a state-space system, scales the equations such that the original state, input and output, (x, u and y), are substituted by

xad=x/state_scal uad=u/input_scal yad=y/output_scal
The entries input_scal/output_scal/state_scal can be:
  • floats: in this case all input/output are scaled by the same value
  • lists/arrays of length Nin/Nout: in this case each dof will be scaled

by a different factor

If the original system has form:
xnew=A*x+B*u y=C*x+D*u
the transformation is such that:
xnew=A*x+(B*uref/xref)*uad yad=1/yref( C*xref*x+D*uref*uad )
states

Number of states \(n\) of the system.

truncate(N)[source]

Retains only the first N states.

ss_block
class sharpy.linear.src.libss.ss_block(A, B, C, D, S_states, S_inputs, S_outputs, dt=None)[source]

State-space model in block form. This class has the same purpose as “ss”, but the A, B, C, D are allocated in the form of nested lists. The format is similar to the one used in numpy.block but:

  1. Block matrices can contain both dense and sparse matrices
  2. Empty blocks are defined through None type

Methods: - remove_block: drop one of the blocks from the s-s model - addGain: project inputs/outputs - project: project state

addGain(K, where)[source]

Projects input u or output y the state-space system through the gain block matrix K. The input ‘where’ determines whether inputs or outputs are projected as:

  • where=’in’: inputs are projected such that:
    u_new -> u=K*u_new -> SS -> y => u_new -> SSnew -> y
  • where=’out’: outputs are projected such that:
    u -> SS -> y -> y_new=K*y => u -> SSnew -> ynew

Input: K must be a list of list of matrices. The size of K must be compatible with either B or C for block matrix product.

get_sizes(M)[source]

Get the size of each block in M.

project(WT, V, by_arrays=True, overwrite=False)[source]

Given 2 transformation matrices, (W,V) of shape (Nk,self.states), this routine projects the state space model states according to:

Anew = W^T A V Bnew = W^T B Cnew = C V Dnew = D

The projected model has the same number of inputs/outputs as the original one, but Nk states.

Inputs: - WT = W^T - V = V - by_arrays: if True, W, V are either numpy.array or sparse matrices. If

False, they are block matrices.
  • overwrite: if True, overwrites the A, B, C matrices
remove_block(where, index)[source]

Remove a block from either inputs or outputs.

Inputs: - where = {‘in’, ‘out’}: determined whether to remove inputs or outputs - index: index of block to remove

ss_to_scipy

Converts to a scipy.signal linear time invariant system

param ss:SHARPy state space object
type ss:libss.ss
returns:scipy.signal.dlti
sum_ss

Given 2 systems or gain matrices (or a combination of the two) having the same amount of input/output, the function returns a gain or state space model summing the two. Namely, given:

u -> SS1 -> y1 u -> SS2 -> y2
we obtain:
u -> SStot -> y1+y2 if negative=False
Linear aeroelastic model based on coupled GEBM + UVLM

Linear aeroelastic model based on coupled GEBM + UVLM S. Maraniello, Jul 2018

LinAeroEla
class sharpy.linear.src.lin_aeroelastic.LinAeroEla(data, custom_settings_linear=None, uvlm_block=False)[source]
Future work:
  • settings are converted from string to type in __init__ method.
  • implement all settings of LinUVLM (e.g. support for sparse matrices)
When integrating in SHARPy:
  • define:
    • self.setting_types
    • self.setting_default
  • use settings.to_custom_types(self.in_dict, self.settings_types, self.settings_default) for conversion to type.
Parameters:
  • data (sharpy.presharpy.PreSharpy) – main SHARPy data class
  • settings_linear (dict) – optional settings file if they are not included in the data structure
settings

solver settings for the linearised aeroelastic solution

Type:dict
lingebm

linearised geometrically exact beam model

Type:lingebm.FlexDynamic
num_dof_str

number of structural degrees of freedom

Type:int
num_dof_rig

number of rigid degrees of freedom

Type:int
num_dof_flex

number of flexible degrees of freedom (num_dof_flex+num_dof_rigid=num_dof_str)

Type:int
linuvl

linearised UVLM class

Type:linuvlm.Dynamic
tsaero

aerodynamic state timestep info

Type:sharpy.utils.datastructures.AeroTimeStepInfo
tsstr

structural state timestep info

Type:sharpy.utils.datastructures.StructTimeStepInfo
dt

time increment

Type:float
q

corresponding vector of displacements of dimensions [1, num_dof_str]

Type:np.array
dq

time derivative (\(\dot{\mathbf{q}}\)) of the corresponding vector of displacements with dimensions [1, num_dof_str]

Type:np.array
SS

state space formulation (discrete or continuous time), as selected by the user

Type:scipy.signal
assemble_ss(beam_num_modes=None)[source]

Assemble State Space formulation

get_gebm2uvlm_gains()[source]
Provides:
  • the gain matrices required to connect the linearised GEBM and UVLM
inputs/outputs
  • the stiffening and damping factors to be added to the linearised

GEBM equations in order to account for non-zero aerodynamic loads at the linearisation point.

The function produces the gain matrices:

  • Kdisp: gains from GEBM to UVLM grid displacements
  • Kvel_disp: influence of GEBM dofs displacements to UVLM grid velocities.
  • Kvel_vel: influence of GEBM dofs displacements to UVLM grid displacements.
  • Kforces (UVLM->GEBM) dimensions are the transpose than the

Kdisp and Kvel* matrices. Hence, when allocation this term, ii and jj indices will unintuitively refer to columns and rows, respectively.

And the stiffening/damping terms accounting for non-zero aerodynamic forces at the linearisation point:

  • Kss: stiffness factor (flexible dof -> flexible dof) accounting

for non-zero forces at the linearisation point. - Csr: damping factor (rigid dof -> flexible dof) - Crs: damping factor (flexible dof -> rigid dof) - Crr: damping factor (rigid dof -> rigid dof)

Stiffening and damping related terms due to the non-zero aerodynamic forces at the linearisation point:

\[\mathbf{F}_{A,n} = C^{AG}(\mathbf{\chi})\sum_j \mathbf{f}_{G,j} \rightarrow \delta\mathbf{F}_{A,n} = C^{AG}_0 \sum_j \delta\mathbf{f}_{G,j} + \frac{\partial}{\partial\chi}(C^{AG}\sum_j \mathbf{f}_{G,j}^0)\delta\chi\]

The term multiplied by the variation in the quaternion, \(\delta\chi\), couples the forces with the rigid body equations and becomes part of \(\mathbf{C}_{sr}\).

Similarly, the linearisation of the moments results in expression that contribute to the stiffness and damping matrices.

\[\mathbf{M}_{B,n} = \sum_j \tilde{X}_B C^{BA}(\Psi)C^{AG}(\chi)\mathbf{f}_{G,j}\]
\[\delta\mathbf{M}_{B,n} = \sum_j \tilde{X}_B\left(C_0^{BG}\delta\mathbf{f}_{G,j} + \frac{\partial}{\partial\Psi}(C^{BA}\delta\mathbf{f}^0_{A,j})\delta\Psi + \frac{\partial}{\partial\chi}(C^{BA}_0 C^{AG} \mathbf{f}_{G,j})\delta\chi\right)\]

The linearised equations of motion for the geometrically exact beam model take the input term \(\delta \mathbf{Q}_n = \{\delta\mathbf{F}_{A,n},\, T_0^T\delta\mathbf{M}_{B,n}\}\), which means that the moments should be provided as \(T^T(\Psi)\mathbf{M}_B\) instead of \(\mathbf{M}_A = C^{AB}\mathbf{M}_B\), where \(T(\Psi)\) is the tangential operator.

\[\delta(T^T\mathbf{M}_B) = T^T_0\delta\mathbf{M}_B + \frac{\partial}{\partial\Psi}(T^T\delta\mathbf{M}_B^0)\delta\Psi\]

is the linearised expression for the moments, where the first term would correspond to the input terms to the beam equations and the second arises due to the non-zero aerodynamic moment at the linearisation point and must be subtracted (since it comes from the forces) to form part of \(\mathbf{K}_{ss}\). In addition, the \(\delta\mathbf{M}_B\) term depends on both \(\delta\Psi\) and \(\delta\chi\), therefore those terms would also contribute to \(\mathbf{K}_{ss}\) and \(\mathbf{C}_{sr}\), respectively.

The contribution from the total forces and moments will be accounted for in \(\mathbf{C}_{rr}\) and \(\mathbf{C}_{rs}\).

\[\delta\mathbf{F}_{tot,A} = \sum_n\left(C^{GA}_0 \sum_j \delta\mathbf{f}_{G,j} + \frac{\partial}{\partial\chi}(C^{AG}\sum_j \mathbf{f}_{G,j}^0)\delta\chi\right)\]

Therefore, after running this method, the beam matrices should be updated as:

>>> K_beam[:flex_dof, :flex_dof] += Kss
>>> C_beam[:flex_dof, -rigid_dof:] += Csr
>>> C_beam[-rigid_dof:, :flex_dof] += Crs
>>> C_beam[-rigid_dof:, -rigid_dof:] += Crr

Track body option

The track_body setting restricts the UVLM grid to linear translation motions and therefore should be used to ensure that the forces are computed using the reference linearisation frame.

The UVLM and beam are linearised about a reference equilibrium condition. The UVLM is defined in the inertial reference frame while the beam employs the body attached frame and therefore a projection from one frame onto another is required during the coupling process.

However, the inputs to the UVLM (i.e. the lattice grid coordinates) are obtained from the beam deformation which is expressed in A frame and therefore the grid coordinates need to be projected onto the inertial frame G. As the beam rotates, the projection onto the G frame of the lattice grid coordinates will result in a grid that is not coincident with that at the linearisation reference and therefore the grid coordinates must be projected onto the original frame, which will be referred to as U. The transformation between the inertial frame G and the U frame is a function of the rotation of the A frame and the original position:

\[C^{UG}(\chi) = C^{GA}(\chi_0)C^{AG}(\chi)\]

Therefore, the grid coordinates obtained in A frame and projected onto the G frame can be transformed to the U frame using

\[\zeta_U = C^{UG}(\chi) \zeta_G\]

which allows the grid lattice coordinates to be projected onto the original linearisation frame.

In a similar fashion, the output lattice vertex forces of the UVLM are defined in the original linearisation frame U and need to be transformed onto the inertial frame G prior to projecting them onto the A frame to use them as the input forces to the beam system.

\[\boldsymbol{f}_G = C^{GU}(\chi)\boldsymbol{f}_U\]

The linearisation of the above relations lead to the following expressions that have to be added to the coupling matrices:

  • Kdisp_vel terms:

    \[\delta\boldsymbol{\zeta}_U= C^{GA}_0 \frac{\partial}{\partial \boldsymbol{\chi}} \left(C^{AG}\boldsymbol{\zeta}_{G,0}\right)\delta\boldsymbol{\chi} + \delta\boldsymbol{\zeta}_G\]
  • Kvel_vel terms:

    \[\delta\dot{\boldsymbol{\zeta}}_U= C^{GA}_0 \frac{\partial}{\partial \boldsymbol{\chi}} \left(C^{AG}\dot{\boldsymbol{\zeta}}_{G,0}\right)\delta\boldsymbol{\chi} + \delta\dot{\boldsymbol{\zeta}}_G\]

The transformation of the forces and moments introduces terms that are functions of the orientation and are included as stiffening and damping terms in the beam’s matrices:

  • Csr damping terms relating to translation forces:

    \[C_{sr}^{tra} -= \frac{\partial}{\partial\boldsymbol{\chi}} \left(C^{GA} C^{AG}_0 \boldsymbol{f}_{G,0}\right)\delta\boldsymbol{\chi}\]
  • Csr damping terms related to moments:

    \[C_{sr}^{rot} -= T^\top\widetilde{\mathbf{X}}_B C^{BG} \frac{\partial}{\partial\boldsymbol{\chi}} \left(C^{GA} C^{AG}_0 \boldsymbol{f}_{G,0}\right)\delta\boldsymbol{\chi}\]

The track_body setting.

When track_body is enabled, the UVLM grid is no longer coincident with the inertial reference frame throughout the simulation but rather it is able to rotate as the A frame rotates. This is to simulate a free flying vehicle, where, for instance, the orientation does not affect the aerodynamics. The UVLM defined in this frame of reference, named U, satisfies the following convention:

  • The U frame is coincident with the G frame at the time of linearisation.
  • The U frame rotates as the A frame rotates.

Transformations related to the U frame of reference:

  • The angle between the U frame and the A frame is always constant and equal to \(\boldsymbol{\Theta}_0\).

  • The angle between the A frame and the G frame is \(\boldsymbol{\Theta}=\boldsymbol{\Theta}_0 + \delta\boldsymbol{\Theta}\)

  • The projection of a vector expressed in the G frame onto the U frame is expressed by:

    \[\boldsymbol{v}^U = C^{GA}_0 C^{AG} \boldsymbol{v}^G\]
  • The reverse, a projection of a vector expressed in the U frame onto the G frame, is expressed by

    \[\boldsymbol{v}^U = C^{GA} C^{AG}_0 \boldsymbol{v}^U\]

The effect this has on the aeroelastic coupling between the UVLM and the structural dynamics is that the orientation and change of orientation of the vehicle has no effect on the aerodynamics. The aerodynamics are solely affected by the contribution of the 6-rigid body velocities (as well as the flexible DOFs velocities).

reshape_struct_input()[source]

Reshape structural input in a column vector

Utilities functions for linear analysis

Utilities functions for linear analysis

Info
class sharpy.linear.src.lin_utils.Info(zeta, zeta_dot, u_ext, ftot, mtot, q, qdot, SSaero=None, SSbeam=None, Kas=None, Kftot=None, Kmtot=None, Kmtot_disp=None, Asteady_inv=None)[source]

Summarise info about a data point

comp_tot_force

Compute total force with exact displacements

extract_from_data

Extract relevant info from data structure. If assemble is True, it will also generate a linear UVLM and the displacements/velocities gain matrices

solve_linear

Given 2 Info() classes associated to a reference linearisation point Ref and a perturbed state Pert, the method produces in output the prediction at the Pert state of a linearised model.

The solution is carried on using both the aero and beam input

Linear beam model class

Linear beam model class

S. Maraniello, Aug 2018 N. Goizueta

FlexDynamic
class sharpy.linear.src.lingebm.FlexDynamic(tsinfo, structure=None, custom_settings={})[source]

Define class for linear state-space realisation of GEBM flexible-body equations from SHARPy``timestep_info`` class and with the nonlinear structural information.

The linearised beam takes the following arguments:

Parameters:
  • tsinfo (sharpy.utils.datastructures.StructImeStepInfo) – Structural timestep containing the modal information
  • structure (sharpy.solvers.beamloader.Beam) – Beam class with the structural information
  • custom_settings (dict) – settings for the linearised beam

State-space models can be defined in continuous or discrete time (dt required). Modal projection, either on the damped or undamped modal shapes, is also avaiable. The rad/s array wv can be optionally passed for freq. response analysis

To produce the state-space equations:

  1. Set the settings:
    1. modal_projection={True,False}: determines whether to project the states

      onto modal coordinates. Projection over damped or undamped modal shapes can be obtained selecting:

      • proj_modes={'damped','undamped'}

      while

      • inout_coords={'modes','nodal'}

      determines whether the modal state-space inputs/outputs are modal coords or nodal degrees-of-freedom. If modes is selected, the Kin and Kout gain matrices are generated to transform nodal to modal dofs

    2. dlti={True,False}: if true, generates discrete-time system.

      The continuous to discrete transformation method is determined by:

      discr_method={ 'newmark',  # Newmark-beta
                          'zoh',              # Zero-order hold
                          'bilinear'} # Bilinear (Tustin) transformation
      

      DLTIs can be obtained directly using the Newmark-\(\beta\) method

      discr_method='newmark' newmark_damp=xx with xx<<1.0

      for full-states descriptions (modal_projection=False) and modal projection over the undamped structural modes (modal_projection=True and proj_modes). The Zero-order holder and bilinear methods, instead, work in all descriptions, but require the continuous state-space equations.

  2. Generate an instance of the beam

2. Run self.assemble(). The method accepts an additional parameter, Nmodes, which allows using a lower number of modes than specified in self.Nmodes

Examples

>>> beam_settings = {'modal_projection': True,
>>>             'inout_coords': 'modes',
>>>             'discrete_time': False,
>>>             'proj_modes': 'undamped',
>>>             'use_euler': True}
>>>
>>> beam = lingebm.FlexDynamic(tsstruct0, structure=data.structure, custom_settings=beam_settings)
>>>
>>> beam.assemble()

Notes

  • Modal projection will automatically select between damped/undamped modes shapes, based on the data available from tsinfo.
  • If the full system matrices are available, use the modal_sol methods to override mode-shapes and eigenvectors
assemble(Nmodes=None)[source]

Assemble state-space model

Several assembly options are available:

  1. Discrete-time, Newmark-\(\beta\):
    • Modal projection onto undamped modes. It uses the modal projection such that the generalised coordinates \(\eta\) are transformed into modal space by

      \[\mathbf{\eta} = \mathbf{\Phi\,q}\]

      where \(\mathbf{\Phi}\) are the first Nmodes right eigenvectors. Therefore, the equation of motion can be re-written such that the modes normalise the mass matrix to become the identity matrix.

      \[\mathbf{I_{Nmodes}}\mathbf{\ddot{q}} + \mathbf{\Lambda_{Nmodes}\,q} = 0\]

      The system is then assembled in Newmark-\(\beta\) form as detailed in newmark_ss()

    • Full size system assembly. No modifications are made to the mass, damping or stiffness matrices and the system is directly assembled by newmark_ss().

  2. Continuous time state-space

Parameters:Nmodes (int) – number of modes to retain
cont2disc(dt=None)[source]

Convert continuous-time SS model into

converge_modal(wv=None, tol=None, Yref=None, Print=False)[source]

Determine number of modes required to achieve a certain convergence of the modal solution in a prescribed frequency range wv. The H-infinity norm of the error w.r.t. Yref is used for assessing convergence.

Warning

if a reference freq. response, Yref, is not provided, the full- state continuous-time frequency response is used as reference. This requires the full-states matrices Mstr, Cstr, Kstr to be available.

euler_propagation_equations(tsstr)[source]

Introduce the linearised Euler propagation equations that relate the body fixed angular velocities to the Earth fixed Euler angles.

This method will remove the quaternion propagation equations created by SHARPy; the resulting system will have 9 rigid degrees of freedom.

Parameters:tsstr

Returns:

freqresp(wv=None, bode=True)[source]

Computes the frequency response of the current state-space model. If self.modal=True, the in/out are determined according to self.inout_coords

linearise_gravity_forces(tsstr=None)[source]

Linearises gravity forces and includes the resulting terms in the C and K matrices. The method takes the linearisation condition (optional argument), linearises and updates:

  • Stiffness matrix
  • Damping matrix
  • Modal damping matrix

The method works for both the quaternion and euler angle orientation parametrisation.

Parameters:tsstr (sharpy.utils.datastructures.StructTimeStepInfo) – Structural timestep at the linearisation point

Notes

The gravity forces are linearised to express them in terms of the beam formulation input variables:

  • Nodal forces: \(\delta \mathbf{f}_A\)
  • Nodal moments: \(\delta(T^T \mathbf{m}_B)\)
  • Total forces (rigid body equations): \(\delta \mathbf{F}_A\)
  • Total moments (rigid body equations): \(\delta \mathbf{M}_A\)

Gravity forces are naturally expressed in G (inertial) frame

\[\mathbf{f}_{G,0} = \mathbf{M\,g}\]

where the \(\mathbf{M}\) is the tangent mass matrix obtained at the linearisation reference.

To obtain the gravity forces expressed in A frame we make use of the projection matrices

\[\mathbf{f}_A = C^{AG}(\boldsymbol{\chi}) \mathbf{f}_{G,0}\]

that projects a vector in the inertial frame G onto the body attached frame A.

The projection of a vector can then be linearised as

\[\delta \mathbf{f}_A = C^{AG} \delta \mathbf{f}_{G,0} + \frac{\partial}{\partial \boldsymbol{\chi}}(C^{AG} \mathbf{f}_{G,0}) \delta\boldsymbol{\chi}.\]
  • Nodal forces:

    The linearisation of the gravity forces acting at each node is simply

    \[\delta \mathbf{f}_A = + \frac{\partial}{\partial \boldsymbol{\chi}}(C^{AG} \mathbf{f}_{G,0}) \delta\boldsymbol{\chi}\]

    where it is assumed that \(\delta\mathbf{f}_G = 0\).

  • Nodal moments:

    The gravity moments can be expressed in the local node frame of reference B by

    \[\mathbf{m}_B = \tilde{X}_{B,CG}C^{BA}(\Psi)C^{AG}(\boldsymbol{\chi})\mathbf{f}_{G,0}\]

    The linearisation is given by:

    \[\delta \mathbf{m}_B = \tilde{X}_{B,CG} \left(\frac{\partial}{\partial\Psi}(C^{BA}\mathbf{f}_{A,0})\delta\Psi + C^{BA}\frac{\partial}{\partial\boldsymbol{\chi}}(C^{AG}\mathbf{f}_{G,0})\delta\boldsymbol{\chi}\right)\]

    However, recall that the input moments are defined in tangential space \(\delta(T^\top\mathbf{m}_B)\) whose linearised expression is

    \[\delta(T^T(\Psi) \mathbf{m}_B) = T_0^T \delta \mathbf{m}_B + \frac{\partial}{\partial \Psi}(T^T \mathbf{m}_{B,0})\delta\Psi\]

    where the \(\delta \mathbf{m}_B\) term has been defined above.

  • Total forces:

    The total forces include the contribution from all flexible degrees of freedom as well as the gravity forces arising from the mass at the clamped node

    \[\mathbf{F}_A = \sum_n \mathbf{f}_A + \mathbf{f}_{A,clamped}\]

    which becomes

    \[\delta \mathbf{F}_A = \sum_n \delta \mathbf{f}_A + \frac{\partial}{\partial\boldsymbol{\chi}}\left(C^{AG}\mathbf{f}_{G,clamped}\right) \delta\boldsymbol{\chi}.\]
  • Total moments:

    The total moments, as opposed to the nodal moments, are expressed in A frame and again require the addition of the moments from the flexible structural nodes as well as the ones from the clamped node itself.

    \[\mathbf{M}_A = \sum_n \tilde{X}_{A,n}^{CG} C^{AG} \mathbf{f}_{n,G} + \tilde{X}_{A,clamped}C^{AG}\mathbf{f}_{G, clamped}\]

    where \(X_{A,n}^{CG} = R_{A,n} + C^{AB}(\Psi)X_{B,n}^{CG}\). Its linearised form is

    \[\delta X_{A,n}^{CG} = \delta R_{A,n} + \frac{\partial}{\partial \Psi}(C^{AB} X_{B,CG})\delta\Psi\]

    Therefore, the overall linearisation of the total moment is defined as

    \[\delta \mathbf{M}_A = \tilde{X}_{A,total}^{CG} \frac{\partial}{\partial \boldsymbol{\chi}}(C^{AG}\mathbf{F}_{G, total}) \delta \boldsymbol{\chi} -\sum_n \tilde{C}^{AG}\mathbf{f}_{G,0} \delta X_{A,n}^{CG}\]

    where \(X_{A, total}\) is the centre of gravity of the entire system expressed in A frame and \(\mathbf{F}_{G, total}\) are the gravity forces of the overall system in G frame, including the contributions from the clamped node.

The linearisation introduces damping and stiffening terms since the \(\delta\boldsymbol{\chi}\) and \(\delta\boldsymbol{\Psi}\) terms are found in the damping and stiffness matrices respectively.

Therefore, the beam matrices need updating to account for these terms:

  • Terms from the linearisation of the nodal moments will be assembled in the rows corresponding to moment equations and columns corresponding to the cartesian rotation vector

    \[K_{ss}^{m,\Psi} \leftarrow -T_0^T \tilde{X}_{B,CG} \frac{\partial}{\partial\Psi}(C^{BA}\mathbf{f}_{A,0}) -\frac{\partial}{\partial \Psi}(T^T \mathbf{m}_{B,0})\]
  • Terms from the linearisation of the translation forces with respect to the orientation are assembled in the damping matrix, the rows corresponding to translational forces and columns to orientation degrees of freedom

    \[C_{sr}^{f,\boldsymbol{\chi}} \leftarrow - \frac{\partial}{\partial \boldsymbol{\chi}}(C^{AG} \mathbf{f}_{G,0})\]
  • Terms from the linearisation of the moments with respect to the orientation are assembled in the damping matrix, with the rows correspondant to the moments and the columns to the orientation degrees of freedom

    \[C_{sr}^{m,\boldsymbol{\chi}} \leftarrow - T_0^T\tilde{X}_{B,CG}C^{BA}\frac{\partial}{\partial\boldsymbol{\chi}}(C^{AG}\mathbf{f}_{G,0})\]
  • Terms from the linearisation of the total forces with respect to the orientation correspond to the rigid body equations in the damping matrix, the rows to the translational forces and columns to the orientation

    \[C_{rr}^{F,\boldsymbol{\chi}} \leftarrow - \sum_n \frac{\partial}{\partial \boldsymbol{\chi}}(C^{AG} \mathbf{f}_{G,0})\]
  • Terms from the linearisation of the total moments with respect to the orientation correspond to the rigid body equations in the damping matrix, the rows to the moments and the columns to the orientation

    \[C_{rr}^{M,\boldsymbol{\chi}} \leftarrow - \sum_n\tilde{X}_{A,n}^{CG} \frac{\partial}{\partial \boldsymbol{\chi}}(C^{AG}\mathbf{f}_{G,0})\]
  • Terms from the linearisation of the total moments with respect to the nodal position \(R_A\) are included in the stiffness matrix, the rows corresponding to the moments in the rigid body equations and the columns to the nodal position

    \[K_{rs}^{M,R} \leftarrow + \sum_n \tilde{\mathbf{f}_{A,0}}\]
  • Terms from the linearisation of the total moments with respect to the cartesian rotation vector are included in the stiffness matrix, the rows corresponding to the moments in the rigid body equations and the columns to the cartesian rotation vector

    \[K_{rs}^{M, \Psi} \leftarrow + \sum_n \tilde{\mathbf{f}_{A,0}}\frac{\partial}{\partial \Psi}(C^{AB} X_{B,CG})\]
reshape_struct_input()[source]

Reshape structural input in a column vector

scale_system_normalised_time(time_ref)[source]

Scale the system with a normalised time step. The resulting time step is \(\Delta t = \Delta \bar{t}/t_{ref}\), where the over bar denotes dimensional time. The structural equations of motion are rescaled as:

\[\mathbf{M}\ddot{\boldsymbol{\eta}} + \mathbf{C} t_{ref} \dot{\boldsymbol{\eta}} + \mathbf{K} t_{ref}^2 \boldsymbol{\eta} = t_{ref}^2 \mathbf{N}\]

For aeroelastic applications, the reference time is usually defined using the semi-chord, \(b\), and the free stream velocity, \(U_\infty\).

\[t_{ref,ae} = \frac{b}{U_\infty}\]
Parameters:time_ref (float) – Normalisation factor such that \(t/\bar{t}\) is non-dimensional.
tune_newmark_damp(amplification_factor=0.999)[source]

Tune artifical damping to achieve a percent reduction of the lower frequency (lower damped) mode

update_modal()[source]

Re-projects the full-states continuous-time structural dynamics equations

\[\mathbf{M}\,\mathbf{\ddot{x}} +\mathbf{C}\,\mathbf{\dot{x}} + \mathbf{K\,x} = \mathbf{F}\]

onto modal space. The modes used to project are controlled through the self.proj_modes={damped or undamped} attribute.

Warning

This method overrides SHARPy timestep_info results and requires Mstr, Cstr, Kstr to be available.

update_truncated_modes(nmodes)[source]

Updates the system to the specified number of modes

Parameters:nmodes

Returns:

newmark_ss

Produces a discrete-time state-space model of the structural equations

\[\begin{split}\mathbf{\ddot{x}} &= \mathbf{M}^{-1}( -\mathbf{C}\,\mathbf{\dot{x}}-\mathbf{K}\,\mathbf{x}+\mathbf{F} ) \\ \mathbf{y} &= \mathbf{x}\end{split}\]

based on the Newmark-\(\beta\) integration scheme. The output state-space model has form:

\[\begin{split}\mathbf{X}_{n+1} &= \mathbf{A}\,\mathbf{X}_n + \mathbf{B}\,\mathbf{F}_n \\ \mathbf{Y} &= \mathbf{C}\,\mathbf{X} + \mathbf{D}\,\mathbf{F}\end{split}\]

with \(\mathbf{X} = [\mathbf{x}, \mathbf{\dot{x}}]^T\)

Note that as the state-space representation only requires the input force \(\mathbf{F}\) to be evaluated at time-step \(n\),the \(\mathbf{C}\) and \(\mathbf{D}\) matrices are, in general, fully populated.

The Newmark-\(\beta\) integration scheme is carried out following the modifications presented by Geradin [1] that render it unconditionally stable. The displacement and velocities are estimated as:

\[\begin{split}x_{n+1} &= x_n + \Delta t \dot{x}_n + \left(\frac{1}{2}-\theta_2\right)\Delta t^2 \ddot{x}_n + \theta_2\Delta t \ddot{x}_{n+1} \\ \dot{x}_{n+1} &= \dot{x}_n + (1-\theta_1)\Delta t \ddot{x}_n + \theta_1\Delta t \ddot{x}_{n+1}\end{split}\]

The stencil is unconditionally stable if the tuning parameters \(\theta_1\) and \(\theta_2\) are chosen as:

\[\begin{split}\theta_1 &= \frac{1}{2} + \alpha \\ \theta_2 &= \frac{1}{4} \left(\theta_1 + \frac{1}{2}\right)^2 \\ \theta_2 &= \frac{5}{80} + \frac{1}{4} (\theta_1 + \theta_1^2) \text{TBC SOURCE}\end{split}\]

where \(\alpha>0\) accounts for small positive algorithmic damping.

The following steps describe how to apply the Newmark-beta scheme to a state-space formulation. The original idea is based on [1].

The equation of a second order system dynamics reads:

\[M\mathbf{\ddot q} + C\mathbf{\dot q} + K\mathbf{q} = F\]

Applying that equation to the time steps \(n\) and \(n+1\), rearranging terms and multiplying by \(M^{-1}\):

\[\begin{split}\mathbf{\ddot q}_{n} = - M^{-1}C\mathbf{\dot q}_{n} - M^{-1}K\mathbf{q}_{n} + M^{-1}F_{n} \\ \mathbf{\ddot q}_{n+1} = - M^{-1}C\mathbf{\dot q}_{n+1} - M^{-1}K\mathbf{q}_{n+1} + M^{-1}F_{n+1}\end{split}\]

The relations of the Newmark-beta scheme are:

\[\begin{split}\mathbf{q}_{n+1} &= \mathbf{q}_n + \mathbf{\dot q}_n\Delta t + (\frac{1}{2}-\beta)\mathbf{\ddot q}_n \Delta t^2 + \beta \mathbf{\ddot q}_{n+1} \Delta t^2 + O(\Delta t^3) \\ \mathbf{\dot q}_{n+1} &= \mathbf{\dot q}_n + (1-\gamma)\mathbf{\ddot q}_n \Delta t + \gamma \mathbf{\ddot q}_{n+1} \Delta t + O(\Delta t^3)\end{split}\]

Substituting the former relation onto the later ones, rearranging terms, and writing it in state-space form:

\[\begin{split}\begin{bmatrix} I + M^{-1}K \Delta t^2\beta \quad \Delta t^2\beta M^{-1}C \\ (\gamma \Delta t M^{-1}K) \quad (I + \gamma \Delta t M^{-1}C) \end{bmatrix} \begin{Bmatrix} \mathbf{\dot q}_{n+1} \\ \mathbf{\ddot q}_{n+1} \end{Bmatrix} = \begin{bmatrix} (I - \Delta t^2(1/2-\beta)M^{-1}K \quad (\Delta t - \Delta t^2(1/2-\beta)M^{-1}C \\ (-(1-\gamma)\Delta t M^{-1}K \quad (I - (1-\gamma)\Delta tM^{-1}C \end{bmatrix} \begin{Bmatrix} \mathbf{q}_{n} \\ \mathbf{\dot q}_{n} \end{Bmatrix} + \begin{Bmatrix} (\Delta t^2(1/2-\beta) \\ (1-\gamma)\Delta t \end{Bmatrix} M^{-1}F_n+ \begin{Bmatrix} (\Delta t^2\beta) \\ (\gamma \Delta t) \end{Bmatrix}M^{-1}F_{n+1}\end{split}\]

To understand SHARPy code, it is convenient to apply the following change of notation:

\[\begin{split}\textrm{th1} = \gamma \\ \textrm{th2} = \beta \\ \textrm{a0} = \Delta t^2 (1/2 -\beta) \\ \textrm{b0} = \Delta t (1 -\gamma) \\ \textrm{a1} = \Delta t^2 \beta \\ \textrm{b1} = \Delta t \gamma \\\end{split}\]

Finally:

\[\begin{split}A_{ss1} \begin{Bmatrix} \mathbf{\dot q}_{n+1} \\ \mathbf{\ddot q}_{n+1} \end{Bmatrix} = A_{ss0} \begin{Bmatrix} \mathbf{\dot q}_{n} \\ \mathbf{\ddot q}_{n} \end{Bmatrix} + \begin{Bmatrix} (\Delta t^2(1/2-\beta) \\ (1-\gamma)\Delta t \end{Bmatrix} M^{-1}F_n+ \begin{Bmatrix} (\Delta t^2\beta) \\ (\gamma \Delta t) \end{Bmatrix}M^{-1}F_{n+1}\end{split}\]

To finally isolate the vector at \(n+1\), instead of inverting the \(A_{ss1}\) matrix, several systems are solved. Moreover, the output equation is simply \(y=x\).

param Minv:Inverse mass matrix \(\mathbf{M^{-1}}\)
type Minv:np.array
param C:Damping matrix \(\mathbf{C}\)
type C:np.array
param K:Stiffness matrix \(\mathbf{K}\)
type K:np.array
param dt:Timestep increment
type dt:float
param num_damp:Numerical damping. Default 1e-4
type num_damp:float
returns:the A, B, C, D matrices of the state space packed in a tuple with the predictor and delay term removed.
rtype:tuple

References

[1] - Geradin M., Rixen D. - Mechanical Vibrations: Theory and application to structural dynamics

sort_eigvals

sort by magnitude (frequency) and imaginary part if complex conj

Linearise UVLM solver

Linearise UVLM solver S. Maraniello, 7 Jun 2018

Dynamic
class sharpy.linear.src.linuvlm.Dynamic(tsdata, dt=None, dynamic_settings=None, integr_order=2, RemovePredictor=True, ScalingDict=None, UseSparse=True, for_vel=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Class for dynamic linearised UVLM solution. Linearisation around steady-state are only supported. The class is built upon Static, and inherits all the methods contained there.

Input:
  • tsdata: aero timestep data from SHARPy solution

  • dt: time-step

  • integr_order=2: integration order for UVLM unsteady aerodynamic force

  • RemovePredictor=True: if true, the state-space model is modified so as to accept in input perturbations, u, evaluated at time-step n rather than n+1.

  • ScalingDict=None: disctionary containing fundamental reference units:

    {'length':  reference_length,
    'speed':   reference_speed,
    'density': reference density}
    

    used to derive scaling quantities for the state-space model variables. The scaling factors are stored in self.ScalingFact.

    Note that while time, circulation, angular speeds) are scaled accordingly, FORCES ARE NOT. These scale by \(q_\infty b^2\), where \(b\) is the reference length and \(q_\infty\) is the dynamic pressure.

  • UseSparse=False: builds the A and B matrices in sparse form. C and D are dense anyway so the sparse format cannot be applied to them.

- nondimss

normalises a dimensional state-space model based on the scaling factors in self.ScalingFact.

- dimss

inverse of nondimss.

- assemble_ss

builds state-space model. See function for more details.

- assemble_ss_profiling

generate profiling report of the assembly and saves it into self.prof_out. To read the report:

import pstats
p = pstats.Stats(self.prof_out)
- solve_steady

solves for the steady state. Several methods available.

- solve_step

solves one time-step

- freqresp

ad-hoc method for fast frequency response (only implemented) for remove_predictor=False

Nx

Number of states

Type:int
Nu

Number of inputs

Type:int
Ny

Number of outputs

Type:int
K

Number of paneles \(K = MN\)

Type:int
K_star

Number of wake panels \(K^*=M^*N\)

Type:int
Kzeta

Number of panel vertices \(K_\zeta=(M+1)(N+1)\)

Type:int
Kzeta_star

Number of wake panel vertices \(K_{\zeta,w} = (M^*+1)(N+1)\)

Type:int

To do: Upgrade to linearise around unsteady snapshot (adjoint)

Nu

Number of inputs \(m\) to the system.

Nx

Number of states \(n\) of the system.

Ny

Number of outputs \(p\) of the system.

assemble_ss()[source]

Produces state-space model of the form

\[\begin{split}\mathbf{x}_{n+1} &= \mathbf{A}\,\mathbf{x}_n + \mathbf{B} \mathbf{u}_{n+1} \\ \mathbf{y}_n &= \mathbf{C}\,\mathbf{x}_n + \mathbf{D} \mathbf{u}_n\end{split}\]

where the state, inputs and outputs are:

\[\mathbf{x}_n = \{ \delta \mathbf{\Gamma}_n,\, \delta \mathbf{\Gamma_{w_n}},\, \Delta t\,\delta\mathbf{\Gamma}'_n,\, \delta\mathbf{\Gamma}_{n-1} \}\]
\[\mathbf{u}_n = \{ \delta\mathbf{\zeta}_n,\, \delta\mathbf{\zeta}'_n,\, \delta\mathbf{u}_{ext,n} \}\]
\[\mathbf{y} = \{\delta\mathbf{f}\}\]

with \(\mathbf{\Gamma}\in\mathbb{R}^{MN}\) being the vector of vortex circulations, \(\mathbf{\zeta}\in\mathbb{R}^{3(M+1)(N+1)}\) the vector of vortex lattice coordinates and \(\mathbf{f}\in\mathbb{R}^{3(M+1)(N+1)}\) the vector of aerodynamic forces and moments. Note that \((\bullet)'\) denotes a derivative with respect to time.

Note that the input is atypically defined at time n+1, therefore by default self.remove_predictor = True and the predictor term u_{n+1} is eliminated through the change of state[1]:

\[\begin{split}\mathbf{h}_n &= \mathbf{x}_n - \mathbf{B}\,\mathbf{u}_n \\\end{split}\]

such that:

\[\begin{split}\mathbf{h}_{n+1} &= \mathbf{A}\,\mathbf{h}_n + \mathbf{A\,B}\,\mathbf{u}_n \\ \mathbf{y}_n &= \mathbf{C\,h}_n + (\mathbf{C\,B}+\mathbf{D})\,\mathbf{u}_n\end{split}\]

which only modifies the equivalent \(\mathbf{B}\) and \(\mathbf{D}\) matrices.

References

[1] Franklin, GF and Powell, JD. Digital Control of Dynamic Systems, Addison-Wesley Publishing Company, 1980

To do: - remove all calls to scipy.linalg.block_diag

assemble_ss_profiling()[source]

Generate profiling report for assembly and save it in self.prof_out.

To read the report:
import pstats p=pstats.Stats(self.prof_out)
balfreq(DictBalFreq)[source]

Low-rank method for frequency limited balancing. The Observability ad controllability Gramians over the frequencies kv are solved in factorised form. Balancd modes are then obtained with a square-root method.

Details:

Observability and controllability Gramians are solved in factorised form through explicit integration. The number of integration points determines both the accuracy and the maximum size of the balanced model.

Stability over all (Nb) balanced states is achieved if:

  1. one of the Gramian is integrated through the full Nyquist range
  2. the integration points are enough.

Note, however, that even when stability is not achieved over the full balanced states, stability of the balanced truncated model with Ns<=Nb states is normally observed even when a low number of integration points is used. Two integration methods (trapezoidal rule on uniform grid and Gauss-Legendre quadrature) are provided.

Input:

  • DictBalFreq: dictionary specifying integration method with keys:

    • frequency: defines limit frequencies for balancing. The balanced model will be accurate in the range [0,F], where F is the value of this key. Note that F units must be consistent with the units specified in the self.ScalingFacts dictionary.
    • method_low: [‘gauss’,’trapz’] specifies whether to use gauss quadrature or trapezoidal rule in the low-frequency range [0,F]
    • options_low: options to use for integration in the low-frequencies. These depend on the integration scheme (See below).
    • method_high: method to use for integration in the range [F,F_N], where F_N is the Nyquist frequency. See ‘method_low’.
    • options_high: options to use for integration in the high-frequencies.
    • check_stability: if True, the balanced model is truncated to eliminate unstable modes - if any is found. Note that very accurate balanced model can still be obtained, even if high order modes are unstable. Note that this option is overridden if “”
    • get_frequency_response: if True, the function also returns the frequency response evaluated at the low-frequency range integration points. If True, this option also allows to automatically tune the balanced model.

Future options:

  • truncation_tolerance: if get_frequency_response is True, allows to truncate the balanced model so as to achieved a prescribed tolerance in the low-frequwncy range.
  • Ncpu: for parallel run

The following integration schemes are available:

  • trapz: performs integration over equally spaced points using trapezoidal rule. It accepts options dictionaries with keys:

    • points: number of integration points to use (including domain boundary)
  • gauss performs gauss-lobotto quadrature. The domain can be partitioned in Npart sub-domain in which the gauss-lobotto quadrature of order Ord can be applied. A total number of Npart*Ord points is required. It accepts options dictionaries of the form:

    • partitions: number of partitions
    • order: quadrature order.

Example:

The following dictionary

DictBalFreq={   'frequency': 1.2,
                'method_low': 'trapz',
                'options_low': {'points': 12},
                'method_high': 'gauss',
                'options_high': {'partitions': 2, 'order': 8},
                'check_stability': True }

balances the state-space model self.SS in the frequency range [0, 1.2] using

  1. 12 equally-spaced points integration of the Gramians in the low-frequency range [0,1.2] and
  2. a 2 Gauss-Lobotto 8-th order quadratures of the controllability Gramian in the high-frequency range.

A total number of 28 integration points will be required, which will result into a balanced model with number of states min{2*28* number_inputs, 2*28* number_outputs}

The model is finally truncated so as to retain only the first Ns stable modes.

balfreq_profiling()[source]

Generate profiling report for balfreq function and saves it into self.prof_out. The function also returns a pstats.Stats object.

To read the report:
import pstats
p=pstats.Stats(self.prof_out).sort_stats('cumtime')
p.print_stats(20)
freqresp(kv)[source]

Ad-hoc method for fast UVLM frequency response over the frequencies kv. The method, only requires inversion of a K x K matrix at each frequency as the equation for propagation of wake circulation are solved exactly. The algorithm implemented here can be used also upon projection of the state-space model.

Note: This method is very similar to the “minsize” solution option is the steady_solve.

get_Cw_cpx(zval)[source]

Produces a sparse matrix

\[\bar{\mathbf{C}}(z)\]

where

\[z = e^{k \Delta t}\]

such that the wake circulation frequency response at \(z\) is

\[\bar{\boldsymbol{\Gamma}}_w = \bar{\mathbf{C}}(z) \bar{\mathbf{\Gamma}}\]
nondimss()[source]

Scale state-space model based of self.ScalingFacts

solve_steady(usta, method='direct')[source]

Steady state solution from state-space model.

Warning: these methods are less efficient than the solver in Static class, Static.solve, and should be used only for verification purposes. The “minsize” method, however, guarantees the inversion of a K x K matrix only, similarly to what is done in Static.solve.

solve_step(x_n, u_n, u_n1=None, transform_state=False)[source]

Solve step.

If the predictor term has not been removed (remove_predictor = False) then the system is solved as:

\[\begin{split}\mathbf{x}^{n+1} &= \mathbf{A\,x}^n + \mathbf{B\,u}^n \\ \mathbf{y}^{n+1} &= \mathbf{C\,x}^{n+1} + \mathbf{D\,u}^n\end{split}\]

Else, if remove_predictor = True, the state is modified as

\[\mathbf{h}^n = \mathbf{x}^n - \mathbf{B\,u}^n\]

And the system solved by:

\[\begin{split}\mathbf{h}^{n+1} &= \mathbf{A\,h}^n + \mathbf{B_{mod}\,u}^{n} \\ \mathbf{y}^{n+1} &= \mathbf{C\,h}^{n+1} + \mathbf{D_{mod}\,u}^{n+1}\end{split}\]

Finally, the original state is recovered using the reverse transformation:

\[\mathbf{x}^{n+1} = \mathbf{h}^{n+1} + \mathbf{B\,u}^{n+1}\]

where the modifications to the \(\mathbf{B}_{mod}\) and \(\mathbf{D}_{mod}\) are detailed in Dynamic.assemble_ss().

Notes

Although the original equations include the term \(\mathbf{u}_{n+1}\), it is a reasonable approximation to take \(\mathbf{u}_{n+1}\approx\mathbf{u}_n\) given a sufficiently small time step, hence if the input at time n+1 is not parsed, it is estimated from \(u^n\).

Parameters:
  • x_n (np.array) – State vector at the current time step \(\mathbf{x}^n\)
  • u_n (np.array) – Input vector at time step \(\mathbf{u}^n\)
  • u_n1 (np.array) – Input vector at time step \(\mathbf{u}^{n+1}\)
  • transform_state (bool) – When the predictor term is removed, if true it will transform the state vector. If false it will be assumed that the state vector that is parsed is already transformed i.e. it is \(\mathbf{h}\).
Returns:

Updated state and output vector packed in a tuple \((\mathbf{x}^{n+1},\,\mathbf{y}^{n+1})\)

Return type:

Tuple

Notes

To speed-up the solution and use minimal memory:
  • solve for bound vorticity (and)
  • propagate the wake
  • compute the output separately.
unpack_state(xvec)[source]

Unpacks the state vector into physical constituents for full order models.

The state vector \(\mathbf{x}\) of the form

\[\mathbf{x}_n = \{ \delta \mathbf{\Gamma}_n,\, \delta \mathbf{\Gamma_{w_n}},\, \Delta t\,\delta\mathbf{\Gamma}'_n,\, \delta\mathbf{\Gamma}_{n-1} \}\]

Is unpacked into:

\[{\delta \mathbf{\Gamma}_n,\, \delta \mathbf{\Gamma_{w_n}},\, \,\delta\mathbf{\Gamma}'_n}\]
Parameters:xvec (np.ndarray) – State vector
Returns:Column vectors for bound circulation, wake circulation and circulation derivative packed in a tuple.
Return type:tuple
DynamicBlock
class sharpy.linear.src.linuvlm.DynamicBlock(tsdata, dt=None, dynamic_settings=None, integr_order=2, RemovePredictor=True, ScalingDict=None, UseSparse=True, for_vel=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Class for dynamic linearised UVLM solution. Linearisation around steady-state are only supported.

The class is a low-memory implementation of Dynamic, and inherits most of the methods contained there. State-space models are allocated in list-block form (as per numpy.block) to minimise memory usage. This class provides lower memory / computational time assembly, frequency response and frequency limited balancing.

Input:

  • tsdata: aero timestep data from SHARPy solution

  • dt: time-step

  • integr_order=2: integration order for UVLM unsteady aerodynamic force

  • RemovePredictor=True: if true, the state-space model is modified so as to accept in input perturbations, u, evaluated at time-step n rather than n+1.

  • ScalingDict=None: disctionary containing fundamental reference units

    >>> {'length':  reference_length,
         'speed':   reference_speed,
         'density': reference density}
    

    used to derive scaling quantities for the state-space model variables. The scaling factors are stores in self.ScalingFact.

    Note that while time, circulation, angular speeds) are scaled accordingly, FORCES ARE NOT. These scale by qinf*b**2, where b is the reference length and qinf is the dinamic pressure.

  • UseSparse=False: builds the A and B matrices in sparse form. C and D are dense, hence the sparce format is not used.

- nondimss

normalises a dimensional state-space model based on the scaling factors in self.ScalingFact.

- dimss

inverse of nondimss.

- assemble_ss

builds state-space model. See function for more details.

- assemble_ss_profiling

generate profiling report of the assembly and saves it into self.prof_out. To read the report:

>>> import pstats
    p=pstats.Stats(self.prof_out)
- freqresp

ad-hoc method for fast frequency response (only implemented) for remove_predictor=False

To do: upgrade to linearise around unsteady snapshot (adjoint)

assemble_ss()[source]

Produces block-form of state-space model

\[\begin{split}\mathbf{x}_{n+1} &= \mathbf{A}\,\mathbf{x}_n + \mathbf{B} \mathbf{u}_{n+1} \\ \mathbf{y}_n &= \mathbf{C}\,\mathbf{x}_n + \mathbf{D} \mathbf{u}_n\end{split}\]

where the state, inputs and outputs are:

\[\mathbf{x}_n = \{ \delta \mathbf{\Gamma}_n,\, \delta \mathbf{\Gamma_{w_n}},\, \Delta t\,\delta\mathbf{\Gamma}'_n,\, \delta\mathbf{\Gamma}_{n-1} \}\]
\[\mathbf{u}_n = \{ \delta\mathbf{\zeta}_n,\, \delta\mathbf{\zeta}'_n,\, \delta\mathbf{u}_{ext,n} \}\]
\[\mathbf{y} = \{\delta\mathbf{f}\}\]

with \(\mathbf{\Gamma}\) being the vector of vortex circulations, \(\mathbf{\zeta}\) the vector of vortex lattice coordinates and \(\mathbf{f}\) the vector of aerodynamic forces and moments. Note that \((\bullet)'\) denotes a derivative with respect to time.

Note that the input is atypically defined at time n+1, therefore by default self.remove_predictor = True and the predictor term u_{n+1} is eliminated through the change of state[1]:

\[\begin{split}\mathbf{h}_n &= \mathbf{x}_n - \mathbf{B}\,\mathbf{u}_n \\\end{split}\]

such that:

\[\begin{split}\mathbf{h}_{n+1} &= \mathbf{A}\,\mathbf{h}_n + \mathbf{A\,B}\,\mathbf{u}_n \\ \mathbf{y}_n &= \mathbf{C\,h}_n + (\mathbf{C\,B}+\mathbf{D})\,\mathbf{u}_n\end{split}\]

which only modifies the equivalent \(\mathbf{B}\) and \(\mathbf{D}\) matrices.

References

[1] Franklin, GF and Powell, JD. Digital Control of Dynamic Systems, Addison-Wesley Publishing Company, 1980

To do: - remove all calls to scipy.linalg.block_diag

balfreq(DictBalFreq)[source]

Low-rank method for frequency limited balancing. The Observability ad controllability Gramians over the frequencies kv are solved in factorised form. Balancd modes are then obtained with a square-root method.

Details: Observability and controllability Gramians are solved in factorised form through explicit integration. The number of integration points determines both the accuracy and the maximum size of the balanced model.

Stability over all (Nb) balanced states is achieved if:
  1. one of the Gramian is integrated through the full Nyquist range
  2. the integration points are enough.

Note, however, that even when stability is not achieved over the full balanced states, stability of the balanced truncated model with Ns<=Nb states is normally observed even when a low number of integration points is used. Two integration methods (trapezoidal rule on uniform grid and Gauss-Legendre quadrature) are provided.

Input:

  • DictBalFreq: dictionary specifying integration method with keys:

    • ‘frequency’: defines limit frequencies for balancing. The balanced

    model will be accurate in the range [0,F], where F is the value of this key. Note that F units must be consistent with the units specified in the self.ScalingFacts dictionary.

    • ‘method_low’: [‘gauss’,’trapz’] specifies whether to use gauss

    quadrature or trapezoidal rule in the low-frequency range [0,F]

    • ‘options_low’: options to use for integration in the low-frequencies.

    These depend on the integration scheme (See below).

    • ‘method_high’: method to use for integration in the range [F,F_N],

    where F_N is the Nyquist frequency. See ‘method_low’.

    • ‘options_high’: options to use for integration in the high-frequencies.
    • ‘check_stability’: if True, the balanced model is truncated to

    eliminate unstable modes - if any is found. Note that very accurate balanced model can still be obtained, even if high order modes are unstable. Note that this option is overridden if “”

    • ‘get_frequency_response’: if True, the function also returns the

    frequency response evaluated at the low-frequency range integration points. If True, this option also allows to automatically tune the balanced model.

Future options:

  • ‘truncation_tolerance’: if ‘get_frequency_response’ is True, allows

to truncatethe balanced model so as to achieved a prescribed tolerance in the low-frequwncy range.

  • Ncpu: for parallel run
The following integration schemes are available:
  • ‘trapz’: performs integration over equally spaced points using
trapezoidal rule. It accepts options dictionaries with keys:
  • ‘points’: number of integration points to use (including

domain boundary)

  • ‘gauss’ performs gauss-lobotto quadrature. The domain can be

partitioned in Npart sub-domain in which the gauss-lobotto quadrature of order Ord can be applied. A total number of Npart*Ord points is required. It accepts options dictionaries of the form:

  • ‘partitions’: number of partitions
  • ‘order’: quadrature order.

Example: The following dictionary

DictBalFreq={ ‘frequency’: 1.2,
‘method_low’: ‘trapz’, ‘options_low’: {‘points’: 12}, ‘method_high’: ‘gauss’, ‘options_high’: {‘partitions’: 2, ‘order’: 8}, ‘check_stability’: True }

balances the state-space model self.SS in the frequency range [0, 1.2] using

  1. 12 equally-spaced points integration of the Gramians in
the low-frequency range [0,1.2] and
(b) a 2 Gauss-Lobotto 8-th order quadratures of the controllability Gramian in the high-frequency range.

A total number of 28 integration points will be required, which will result into a balanced model with number of states

min{ 2*28* number_inputs, 2*28* number_outputs }

The model is finally truncated so as to retain only the first Ns stable modes.

freqresp(kv)[source]

Ad-hoc method for fast UVLM frequency response over the frequencies kv. The method, only requires inversion of a K x K matrix at each frequency as the equation for propagation of wake circulation are solved exactly. The algorithm implemented here can be used also upon projection of the state-space model.

Note: This method is very similar to the “minsize” solution option is the steady_solve.

nondimss()[source]

Scale state-space model based of self.ScalingFacts.

solve_step(x_n, u_n, u_n1=None, transform_state=False)[source]

Solve step.

If the predictor term has not been removed (remove_predictor = False) then the system is solved as:

\[\begin{split}\mathbf{x}^{n+1} &= \mathbf{A\,x}^n + \mathbf{B\,u}^n \\ \mathbf{y}^{n+1} &= \mathbf{C\,x}^{n+1} + \mathbf{D\,u}^n\end{split}\]

Else, if remove_predictor = True, the state is modified as

\[\mathbf{h}^n = \mathbf{x}^n - \mathbf{B\,u}^n\]

And the system solved by:

\[\begin{split}\mathbf{h}^{n+1} &= \mathbf{A\,h}^n + \mathbf{B_{mod}\,u}^{n} \\ \mathbf{y}^{n+1} &= \mathbf{C\,h}^{n+1} + \mathbf{D_{mod}\,u}^{n+1}\end{split}\]

Finally, the original state is recovered using the reverse transformation:

\[\mathbf{x}^{n+1} = \mathbf{h}^{n+1} + \mathbf{B\,u}^{n+1}\]

where the modifications to the \(\mathbf{B}_{mod}\) and \(\mathbf{D}_{mod}\) are detailed in Dynamic.assemble_ss().

Notes

Although the original equations include the term \(\mathbf{u}_{n+1}\), it is a reasonable approximation to take \(\mathbf{u}_{n+1}\approx\mathbf{u}_n\) given a sufficiently small time step, hence if the input at time n+1 is not parsed, it is estimated from \(u^n\).

Parameters:
  • x_n (np.array) – State vector at the current time step \(\mathbf{x}^n\)
  • u_n (np.array) – Input vector at time step \(\mathbf{u}^n\)
  • u_n1 (np.array) – Input vector at time step \(\mathbf{u}^{n+1}\)
  • transform_state (bool) – When the predictor term is removed, if true it will transform the state vector. If false it will be assumed that the state vector that is parsed is already transformed i.e. it is \(\mathbf{h}\).
Returns:

Updated state and output vector packed in a tuple \((\mathbf{x}^{n+1},\,\mathbf{y}^{n+1})\)

Return type:

Tuple

Notes

Because in BlockDynamics the predictor is never removed when building ‘self.SS’, the implementation change with respect to Dynamic. However, formulas are consistent.

Frequency
class sharpy.linear.src.linuvlm.Frequency(tsdata, dt, integr_order=2, RemovePredictor=True, ScalingDict=None, UseSparse=True)[source]

Class for frequency description of linearised UVLM solution. Linearisation around steady-state are only supported. The class is built upon Static, and inherits all the methods contained there.

The class supports most of the features of Dynamics but has lower memory requirements of Dynamic, and should be preferred for:

  1. producing memory and computationally cheap frequency responses
  2. building reduced order models using RFA/polynomial fitting

Usage: Upon initialisation, the assemble method produces all the matrices required for the frequency description of the UVLM (see assemble for details). A state-space model is not allocated but:

  • Time stepping is also possible (but not implemented yet) as all the fundamental terms describing the UVLM equations are still produced (except the propagation of wake circulation)
  • ad-hoc methods for scaling, unscaling and frequency response are provided.

Input:

  • tsdata: aero timestep data from SHARPy solution

  • dt: time-step

  • integr_order=0,1,2: integration order for UVLM unsteady aerodynamic force. If 0, the derivative is computed exactly.

  • RemovePredictor=True: This flag is only used for the frequency response calculation. The frequency description, in fact, naturally arises without the predictor, but lags can be included during the frequency response calculation. See Dynamic documentation for more details.

  • ScalingDict=None: disctionary containing fundamental reference units

    {'length':  reference_length,
     'speed':   reference_speed,
     'density': reference density}
    

    used to derive scaling quantities for the state-space model variables. The scaling factors are stores in self.ScalingFact.

    Note that while time, circulation, angular speeds) are scaled accordingly, FORCES ARE NOT. These scale by qinf*b**2, where b is the reference length and qinf is the dinamic pressure.

  • UseSparse=False: builds the A and B matrices in sparse form. C and D are dense, hence the sparce format is not used.

- nondimss

normalises matrices produced by the assemble method based on the scaling factors in self.ScalingFact.

- dimss

inverse of nondimss.

- assemble

builds matrices for UVLM minimal size description.

- assemble_profiling

generate profiling report of the assembly and saves it into self.prof_out. To read the report:

import pstats
p=pstats.Stats(self.prof_out)
- freqresp

fast algorithm for frequency response.

Methods to implement:

  • solve_steady: runs freqresp at 0 frequency.
  • solve_step: solves one time-step
assemble()[source]

Assembles matrices for minumal size frequency description of UVLM. The state equation is represented in the form:

\[\mathbf{A_0} \mathbf{\Gamma} + \mathbf{A_{w_0}} \mathbf{\Gamma_w} = \mathbf{B_0} \mathbf{u}\]

While the output equation is as per the Dynamic class, namely:

\[\mathbf{y} = \mathbf{C} \mathbf{x} + \mathbf{D} \mathbf{u}\]

where

\[\mathbf{x} = [\mathbf{\Gamma}; \mathbf{\Gamma_w}; \Delta\mathbf(\Gamma)]\]

The propagation of wake circulation matrices are not produced as these are not required for frequency response analysis.

assemble_profiling()[source]

Generate profiling report for assembly and save it in self.prof_out.

To read the report:
import pstats p=pstats.Stats(self.prof_out)
freqresp(kv)[source]

Ad-hoc method for fast UVLM frequency response over the frequencies kv. The method, only requires inversion of a K x K matrix at each frequency as the equation for propagation of wake circulation are solved exactly.

get_Cw_cpx(zval)[source]

Produces a sparse matrix

\[\bar{\mathbf{C}}(z)\]

where

\[z = e^{k \Delta t}\]

such that the wake circulation frequency response at \(z\) is

\[\bar{\goldsymbol{\Gamma}}_w = \bar{\mathbf{C}}(z) \bar{\boldsymbol{\Gamma}}\]
nondimss()[source]

Scale state-space model based of self.ScalingFacts

Static
class sharpy.linear.src.linuvlm.Static(tsdata, for_vel=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Static linear solver

assemble()[source]

Assemble global matrices

assemble_profiling()[source]

Generate profiling report for assembly and save it in self.prof_out.

To read the report:
import pstats p=pstats.Stats(self.prof_out)
get_rigid_motion_gains(zeta_rotation=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Gains to reproduce rigid-body motion such that grid displacements and velocities are given by:

  • dzeta     = Ktra*u_tra         + Krot*u_rot
  • dzeta_dot = Ktra_vel*u_tra_dot + Krot*u_rot_dot

Rotations are assumed to happen independently with respect to the zeta_rotation point and about the x,y and z axes of the inertial frame.

get_sect_forces_gain()[source]

Gains to computes sectional forces. Moments are computed w.r.t. mid-vertex (chord-wise index M/2) of each section.

get_total_forces_gain(zeta_pole=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Calculates gain matrices to calculate the total force (Kftot) and moment (Kmtot, Kmtot_disp) about the pole zeta_pole.

Being \(f\) and \(\zeta\) the force and position at the vertex (m,n) of the lattice these are produced as:

  • ftot=sum(f) -> dftot += df
  • mtot-sum((zeta-zeta_pole) x f) ->       dmtot +=  cross(zeta0-zeta_pole) df - cross(f0) dzeta
reshape()[source]

Reshapes state/output according to SHARPy format

solve()[source]

Solve for bound \(\\Gamma\) using the equation;

\[\begin{split}\\mathcal{A}(\\Gamma^n) = u^n\end{split}\]

# … at constant rotation speed self.Dfqsdzeta+=scalg.block_diag(*ass.dfqsdzeta_omega(MS.Surfs,MS.Surfs_star))

total_forces(zeta_pole=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Calculates total force (Ftot) and moment (Mtot) (about pole zeta_pole).

Generation of multiple aerodynamic surfaces
  1. Maraniello, 25 May 2018
MultiAeroGridSurfaces
class sharpy.linear.src.multisurfaces.MultiAeroGridSurfaces(tsdata, for_vel=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Creates and assembles multiple aerodynamic surfaces from data

get_ind_velocities_at_collocation_points()[source]

Computes normal induced velocities at collocation points.

get_ind_velocities_at_segments(overwrite=False)[source]

Computes induced velocities at mid-segment points.

get_joukovski_qs(overwrite=False)[source]

Returns quasi-steady forces over

Warning: forces are stored in a NON-redundant format:
(3,4,M,N)
where the element
(:,ss,mm,nn)

is the contribution to the force over the ss-th segment due to the circulation of panel (mm,nn).

get_normal_ind_velocities_at_collocation_points()[source]

Computes normal induced velocities at collocation points.

Note: for state-equation both projected and not projected induced velocities are required at the collocation points. Hence, this method tries to first the u_ind_coll attribute in each surface.

verify_aic_coll()[source]

Verify aic at collocaiton points using non-penetration condition

verify_joukovski_qs()[source]

Verify quasi-steady contribution for forces matches against SHARPy.

verify_non_penetration()[source]

Verify state variables fulfill non-penetration condition at bound surfaces

Geometrical methods for bound surfaces

Geometrical methods for bound surfaces

  1. Maraniello, 20 May 2018
AeroGridGeo
class sharpy.linear.src.surface.AeroGridGeo(Map: gridmapping.AeroGridMap instance, zeta: Array of vertex coordinates at each surface, aM: chord-wise position of collocation point in panel = 0.5, aN: span-wise position of collocation point in panel = 0.5)[source]

Allows retrieving geometrical information of a surface. Requires a gridmapping.AeroGridMap mapping structure in input and the surface vertices coordinates.

Indices convention: each panel is characterised through the following indices: - m,n: chord/span-wise indices

Methods: - get_*: retrieve information of a panel (e.g. normal, surface area) - generate_*: apply get_* method to each panel and store info into array.

Interpolation matrices, W: - these are labelled as ‘Wba’, where ‘a’ defines the initial format, b the final. Hence, given the array vb, it holds va=Wab*vb

get_panel_collocation(zetav_here)[source]

Using bilinear interpolation, retrieves panel collocation point, where aN,aM in [0,1] are distances in the chordwise and spanwise directions such that:

  • (aM,aN)=(0,0) –> quantity at vertex 0
  • (aM,aN)=(1,0) –> quantity at vertex 1
  • (aM,aN)=(1,1) –> quantity at vertex 2
  • (aM,aN)=(0,1) –> quantity at vertex 3
get_panel_vertices_coords(m, n)[source]

Retrieves coordinates of panel (m,n) vertices.

get_panel_wcv()[source]

Produces a compact array with weights for bilinear interpolation, where aN,aM in [0,1] are distances in the chordwise and spanwise directions such that:

  • (aM,aN)=(0,0) –> quantity at vertex 0
  • (aM,aN)=(1,0) –> quantity at vertex 1
  • (aM,aN)=(1,1) –> quantity at vertex 2
  • (aM,aN)=(0,1) –> quantity at vertex 3
interp_vertex_to_coll(q_vert)[source]

Project a quantity q_vert (scalar or vector) defined at vertices to collocation points.

project_coll_to_normal(q_coll)[source]

Project a vector quantity q_coll defined at collocation points to normal.

AeroGridSurface
class sharpy.linear.src.surface.AeroGridSurface(Map, zeta, gamma, u_ext=None, zeta_dot=None, gamma_dot=None, rho=1.0, aM=0.5, aN=0.5, for_vel=<sphinx.ext.autodoc.importer._MockObject object>)[source]

Contains geometric and aerodynamic information about bound/wake surface.

Compulsory input are those that apply to both bound and wake surfaces:
  • zeta: defines geometry
  • gamma: circulation
With respect to AeroGridGeo, the class contains methods to:
  • project prescribed input velocity at nodes (u_ext, zeta_dot) over collocation points.
  • compute induced velocity over ANOTHER surface.
  • compute AIC induced over ANOTHER surface
Parameters:
  • Map (gridmapping.AeroGridMap) – Map of grid.
  • zeta (list(np.ndarray)) – Grid vertices coordinates in inertial (G) frame.
  • zeta_dot (list(np.ndarray)) – Grid vertices velocities in inertial (G) frame. Default is None.
  • u_ext (list(np.ndarray)) – Grid external velocities in inertial (G) frame. Default is None.
  • gamma_dot (list(np.ndarray)) – Panel circulation derivative. Default is None.
  • rho (float) – Air density. Default is 1.
  • aM (float) – Chordwise position in panel of collocation point. Default is 0.5
  • aN (float) – Spanwise position in panel of collocation point. Default is 0.5
  • for_vel (np.ndarray) – Frame of reference velocity (including rotational velocity) in the inertial frame.
To add:
  • project prescribed input velocity at nodes (u_ext, zeta_dot) over

mid-point segments

get_aic3(zeta_target)[source]

Produces influence coefficinet matrix to calculate the induced velocity at a target point. The aic3 matrix has shape (3,K)

get_aic_over_surface(Surf_target, target='collocation', Project=True)[source]

Produces influence coefficient matrices such that the velocity induced over the Surface_target is given by the product:

if target==’collocation’:
if Project:
u_ind_coll_norm.rehape(-1)=AIC*self.gamma.reshape(-1,order=’C’)
else:
u_ind_coll_norm[ii,:,:].rehape(-1)=
AIC[ii,:,:]*self.gamma.reshape(-1,order=’C’)

where ii=0,1,2

if targer==’segments’:
  • AIC has shape (3,self.maps.K,4,Mout,Nout), such that
    AIC[:,:,ss,mm,nn]

is the influence coefficient matrix associated to the induced velocity at segment ss of panel (mm,nn)

get_induced_velocity(zeta_target)[source]

Computes induced velocity at a point zeta_target.

get_induced_velocity_over_surface(Surf_target, target='collocation', Project=False)[source]

Computes induced velocity over an instance of AeroGridSurface, where target specifies the target grid (collocation or segments). If Project is True, velocities are projected onver panel normal (only available at collocation points).

Note: for state-equation, both projected and non-projected velocities at the collocation points are required. Hence, it is suggested to use this method with Projection=False, and project afterwards.

Warning: induced velocities at grid segments are stored in a redundant format:

(3,4,M,N)
where the element
(:,ss,mm,nn)

is the induced velocity over the ss-th segment of panel (mm,nn). A fast looping is implemented to re-use previously computed velocities

get_input_velocities_at_collocation_points()[source]

Returns velocities at collocation points from nodal values u_ext and zeta_dot of shape (3, M+1, N+1) at the collocation points.

Notes:

\[oldsymbol{u}_{c} = \mathcal{W}_{cv}(oldsymbol(\]

u)_0 - oldsymbol{zeta}_0)

is the input velocity at the collocation point, where \(\mathcal{W}_{cv} projects the velocity from the grid points onto the collocation point. This variable is referred to as \) and depends on the coordinates zeta when the body is rotating.
get_input_velocities_at_segments()[source]

Returns velocities at mid-segment points from nodal values u_ext and zeta_dot of shape (3,M+1,N+1).

Warning: input velocities at grid segments are stored in a redundant format:

(3,4,M,N)
where the element
(:,ss,mm,nn)

is the induced velocity over the ss-th segment of panel (mm,nn). A fast looping is implemented to re-use previously computed velocities

2018/08/24: Include effects due to rotation (omega x zeta). Now it depends on the coordinates zeta

get_joukovski_qs(gammaw_TE=None, recompute_velocities=True)[source]

Returns quasi-steady forces evaluated at mid-segment points over the surface.

Important: the circulation at the first row of wake panel is required! Hence all

Warning: forces are stored in a NON-redundant format:
(3,4,M,N)
where the element
(:,ss,mm,nn)

is the contribution to the force over the ss-th segment due to the circulation of panel (mm,nn).

get_joukovski_unsteady()[source]

Returns added mass effects over lattive grid

get_normal_input_velocities_at_collocation_points()[source]

From nodal input velocity to normal velocities at collocation points.

get_aic3_cpp

Used by autodoc_mock_imports.

Utils
State-space modules loading utilities
sys_list_from_path

Returns the files containing linear system state space elements

param cwd:Current working directory
type cwd:str

Returns:

Linear State Space Element Class

Linear State Space Element Class

Element
class sharpy.linear.utils.sselements.Element[source]

State space member

Model Order Reduction

Balancing Methods

The following classes are available to reduce a linear system employing balancing methods.

The main class is Balanced and the other available classes:

correspond to the reduction algorithm.

Balanced
class sharpy.rom.balanced.Balanced[source]

Balancing ROM methods

Main class to load a balancing ROM. See below for the appropriate settings to be parsed in the algorithm_settings based on your selection.

Supported algorithms:

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
print_info bool Write output to screen True  
algorithm str Balanced realisation method   Direct, Iterative, FrequencyLimited
algorithm_settings dict Settings for the desired algorithm {}  
Direct
class sharpy.rom.balanced.Direct[source]

Find balanced realisation of continuous (DLTI = False) and discrete (DLTI = True) time of LTI systems using scipy libraries.

The function proceeds to achieve balanced realisation of the state-space system by first solving the Lyapunov equations. They are solved using Barlets-Stewart algorithm for Sylvester equation, which is based on A matrix Schur decomposition.

\[\begin{split}\mathbf{A\,W_c + W_c\,A^T + B\,B^T} &= 0 \\ \mathbf{A^T\,W_o + W_o\,A + C^T\,C} &= 0\end{split}\]

to obtain the reachability and observability gramians, which are positive definite matrices.

Then, the gramians are decomposed into their Cholesky factors such that:

\[\begin{split}\mathbf{W_c} &= \mathbf{Q_c\,Q_c^T} \\ \mathbf{W_o} &= \mathbf{Q_o\,Q_o^T}\end{split}\]

A singular value decomposition (SVD) of the product of the Cholesky factors is performed

\[(\mathbf{Q_o^T\,Q_c}) = \mathbf{U\,\Sigma\,V^*}\]

The singular values are then used to build the transformation matrix \(\mathbf{T}\)

\[\begin{split}\mathbf{T} &= \mathbf{Q_c\,V\,\Sigma}^{-1/2} \\ \mathbf{T}^{-1} &= \mathbf{\Sigma}^{-1/2}\,\mathbf{U^T\,Q_o^T}\end{split}\]

The balanced system is therefore of the form:

\[\begin{split}\mathbf{A_b} &= \mathbf{T\,A\,T^{-1}} \\ \mathbf{B_b} &= \mathbf{T\,B} \\ \mathbf{C_b} &= \mathbf{C\,T^{-1}} \\ \mathbf{D_b} &= \mathbf{D}\end{split}\]

Warning

This function may be less computationally efficient than the balreal Matlab implementation and does not offer the option to bound the realisation in frequency and time.

Notes

Lyapunov equations are solved using Barlets-Stewart algorithm for Sylvester equation, which is based on A matrix Schur decomposition.

Parameters:
  • A (np.ndarray) – Plant Matrix
  • B (np.ndarray) – Input Matrix
  • C (np.ndarray) – Output Matrix
  • DLTI (bool) – Discrete time state-space flag
  • Schur (bool) – Use Schur decomposition to solve the Lyapunov equations
Returns:

Tuple of the form (S, T, Tinv) containing:
  • Singular values in diagonal matrix (S)
  • Transformation matrix (T).
  • Inverse transformation matrix(Tinv).

Return type:

tuple of np.ndarrays

References

Anthoulas, A.C.. Approximation of Large Scale Dynamical Systems. Chapter 7. Advances in Design and Control. SIAM. 2005.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
tune bool Tune ROM to specified tolerance True  
use_schur bool Use Schur decomposition during build False  
rom_tolerance float Absolute accuracy with respect to full order frequency response 0.01  
rom_tune_freq_range list(float) Beginning and end of frequency range where to tune ROM [0, 1]  
convergence str ROM tuning convergence. If min attempts to find minimal number of states.If all it starts from larger size ROM until convergence to specified tolerance is found. min  
reduction_method str Desired reduction method realisation realisation, truncation
FrequencyLimited
class sharpy.rom.balanced.FrequencyLimited[source]

Method for frequency limited balancing.

The Observability and controllability Gramians over the frequencies kv are solved in factorised form. Balanced modes are then obtained with a square-root method.

Details:

  • Observability and controllability Gramians are solved in factorised form through explicit integration. The number of integration points determines both the accuracy and the maximum size of the balanced model.

  • Stability over all (Nb) balanced states is achieved if:

    1. one of the Gramian is integrated through the full Nyquist range
    2. the integration points are enough.

Input:

  • DictBalFreq: dictionary specifying integration method with keys:

    • frequency: defines limit frequencies for balancing. The balanced
      model will be accurate in the range [0,F], where F is the value of this key. Note that F units must be consistent with the units specified in the self.ScalingFacts dictionary.
    • method_low: ['gauss','trapz'] specifies whether to use gauss quadrature or trapezoidal rule in the low-frequency range [0,F].
    • options_low: options to use for integration in the low-frequencies. These depend on the integration scheme (See below).
    • method_high: method to use for integration in the range [F,F_N], where F_N is the Nyquist frequency. See ‘method_low’.
    • options_high: options to use for integration in the high-frequencies.
    • check_stability: if True, the balanced model is truncated to eliminate unstable modes - if any is found. Note that very accurate balanced model can still be obtained, even if high order modes are unstable. Note that this option is overridden if “”
    • get_frequency_response: if True, the function also returns the frequency response evaluated at the low-frequency range integration points. If True, this option also allows to automatically tune the balanced model.
Future options:
  • Ncpu: for parallel run
The following integration schemes are available:
  • trapz: performs integration over equally spaced points using trapezoidal rule. It accepts options dictionaries with keys:

    • points: number of integration points to use (including domain boundary)
  • gauss performs gauss-lobotto quadrature. The domain can be partitioned in Npart sub-domain in which the gauss-lobotto quadrature of order Ord can be applied. A total number of Npart*Ord points is required. It accepts options dictionaries of the form:

    • partitions: number of partitions
    • order: quadrature order.

Examples

The following dictionary

>>>   DictBalFreq={'frequency': 1.2,
>>>                'method_low': 'trapz',
>>>                'options_low': {'points': 12},
>>>                'method_high': 'gauss',
>>>                'options_high': {'partitions': 2, 'order': 8},
>>>                'check_stability': True }

balances the state-space model in the frequency range [0, 1.2] using:

  1. 12 equally-spaced points integration of the Gramians in the low-frequency range [0,1.2] and
  2. A 2 Gauss-Lobotto 8-th order quadratures of the controllability Gramian in the high-frequency range.

A total number of 28 integration points will be required, which will result into a balanced model with number of states

>>>    min{ 2*28* number_inputs, 2*28* number_outputs }

The model is finally truncated so as to retain only the first Ns stable modes.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
frequency float defines limit frequencies for balancing. The balanced model will be accurate in the range [0,F], where F is the value of this key. Note that F units must be consistent with the units specified in the in the self.ScalingFacts dictionary. 1.0  
method_low str Specifies whether to use gauss quadrature or trapezoidal rule in the low-frequency range [0,F] trapz gauss, trapz
options_low dict Settings for the low frequency integration. See Notes. {}  
method_high str Specifies whether to use gauss quadrature or trapezoidal rule in the high-frequency range [F,FN] trapz gauss, trapz
options_high dict Settings for the high frequency integration. See Notes. {}  
check_stability bool if True, the balanced model is truncated to eliminate unstable modes - if any is found. Note that very accurate balanced model can still be obtained, even if high order modes are unstable. True  
get_frequency_response bool if True, the function also returns the frequency response evaluated at the low-frequency range integration points. If True, this option also allows to automatically tune the balanced model. False  

The parameters of integration take the following options:

Name Type Description Default
points int Trapezoidal points of integration 12
partitions int Number of Gauss-Lobotto quadratures 2
order int Order of Gauss-Lobotto quadratures 2
Iterative
class sharpy.rom.balanced.Iterative[source]

Find balanced realisation of DLTI system.

Notes

Lyapunov equations are solved using iterative squared Smith algorithm, in its low or full rank version. These implementations are as per the low_rank_smith and smith_iter functions respectively but, for computational efficiency, the iterations are rewritten here so as to solve for the observability and controllability Gramians contemporary.

  • Exploiting sparsity:

    This algorithm is not ideal to exploit sparsity. However, the following strategies are implemented:

    • if the A matrix is provided in sparse format, the powers of A will be calculated exploiting sparsity UNTIL the number of non-zero elements is below 15% the size of A. Upon this threshold, the cost of the matrix multiplication rises dramatically, and A is hence converted to a dense numpy array.

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default
lowrank bool Use low rank methods True
smith_tol float Smith tolerance 1e-10
tolSVD float SVD threshold 1e-06
Krylov-subspaces model order reduction techniques
Krylov
class sharpy.rom.krylov.Krylov[source]

Model Order Reduction Methods for Single Input Single Output (SISO) and MIMO Linear Time-Invariant (LTI) Systems using moment matching (Krylov Methods).

Examples

General calling sequences for different systems

SISO single point interpolation:
>>> algorithm = 'one_sided_arnoldi'
>>> interpolation_point = np.array([0.0])
>>> krylov_r = 4
>>>
>>> rom = Krylov()
>>> rom.initialise(sharpy_data, FullOrderModelSS)
>>> rom.run(algorithm, krylov_r, interpolation_point)
2 by 2 MIMO with tangential, multipoint interpolation:
>>> algorithm = 'dual_rational_arnoldi'
>>> interpolation_point = np.array([0.0, 1.0j])
>>> krylov_r = 4
>>> right_vector = np.block([[1, 0], [0, 1]])
>>> left_vector = right_vector
>>>
>>> rom = Krylov()
>>> rom.initialise(sharpy_data, FullOrderModelSS)
>>> rom.run(algorithm, krylov_r, interpolation_point, right_vector, left_vector)
2 by 2 MIMO multipoint interpolation:
>>> algorithm = 'mimo_rational_arnoldi'
>>> interpolation_point = np.array([0.0])
>>> krylov_r = 4
>>>
>>> rom = Krylov()
>>> rom.initialise(sharpy_data, FullOrderModelSS)
>>> rom.run(algorithm, krylov_r, interpolation_point)

The settings that this solver accepts are given by a dictionary, with the following key-value pairs:

Name Type Description Default Options
print_info bool Write ROM information to screen and log True  
frequency list(complex) Interpolation points in the continuous time complex plane [rad/s] [0]  
algorithm str Krylov reduction method algorithm    
r int Moments to match at the interpolation points 1  
single_side str Construct the rom using a single side. Leave blank (or empty string) for both.   controllability, observability
tangent_input_file str Filepath to .h5 file containing tangent interpolation vectors    
restart_arnoldi bool Restart Arnoldi iteration with r-=1 if ROM is unstable False  
check_stability(restart_arnoldi=False)[source]

Checks the stability of the ROM by computing its eigenvalues.

If the resulting system is unstable, the Arnoldi procedure can be restarted to eliminate the eigenvalues outside the stability boundary.

However, if this is the case, the ROM no longer matches the moments of the original system at the specific frequencies since now the approximation is done with respect to a system of the form:

\[\begin{split}\Sigma = \left(\begin{array}{c|c} \mathbf{A} & \mathbf{\bar{B}} \\ \hline \mathbf{C} & \ \end{array}\right)\end{split}\]

where \(\mathbf{\bar{B}} = (\mu \mathbf{I}_n - \mathbf{A})\mathbf{B}\)

Parameters:restart_arnoldi (bool) – Restart the relevant Arnoldi algorithm with the unstable eigenvalues removed.
dual_rational_arnoldi(frequency, r)[source]

Dual Rational Arnoli Interpolation for SISO sytems [1] and MIMO systems through tangential interpolation [2].

Effectively the same as the two_sided_arnoldi and the resulting V matrices for each interpolation point are concatenated

\[\begin{split}\bigcup\limits_{k = 1}^K\mathcal{K}_{b_k}((\sigma_i\mathbf{I}_n - \mathbf{A})^{-1}, (\sigma_i\mathbf{I}_n - \mathbf{A})^{-1}\mathbf{b})\subseteq\mathcal{V}&=\text{range}(\mathbf{V}) \\ \bigcup\limits_{k = 1}^K\mathcal{K}_{c_k}((\sigma_i\mathbf{I}_n - \mathbf{A})^{-T}, (\sigma_i\mathbf{I}_n - \mathbf{A})^{-T}\mathbf{c}^T)\subseteq\mathcal{Z}&=\text{range}(\mathbf{Z})\end{split}\]

For MIMO systems, tangential interpolation is used through the right and left tangential direction vectors \(\mathbf{r}_i\) and \(\mathbf{l}_i\).

\[\begin{split}\bigcup\limits_{k = 1}^K\mathcal{K}_{b_k}((\sigma_i\mathbf{I}_n - \mathbf{A})^{-1}, (\sigma_i\mathbf{I}_n - \mathbf{A})^{-1}\mathbf{Br}_i)\subseteq\mathcal{V}&=\text{range}(\mathbf{V}) \\ \bigcup\limits_{k = 1}^K\mathcal{K}_{c_k}((\sigma_i\mathbf{I}_n - \mathbf{A})^{-T}, (\sigma_i\mathbf{I}_n - \mathbf{A})^{-T}\mathbf{C}^T\mathbf{l}_i)\subseteq\mathcal{Z}&=\text{range}(\mathbf{Z})\end{split}\]
Parameters:
  • frequency (np.ndarray) – Array containing the interpolation points \(\sigma = \{\sigma_1, \dots, \sigma_K\}\in\mathbb{C}\)
  • r (int) – Krylov space order \(b_k\) and \(c_k\). At the moment, different orders for the controllability and observability constructions are not supported.
  • right_tangent (np.ndarray) – Matrix containing the right tangential direction interpolation vector for each interpolation point in column form, i.e. \(\mathbf{r}\in\mathbb{R}^{m \times K}\).
  • left_tangent (np.ndarray) – Matrix containing the left tangential direction interpolation vector for each interpolation point in column form, i.e. \(\mathbf{l}\in\mathbb{R}^{p \times K}\).
Returns:

The reduced order model matrices: \(\mathbf{A}_r\), \(\mathbf{B}_r\) and \(\mathbf{C}_r\).

Return type:

tuple

References

[1] Grimme [2] Gallivan

mimo_rational_arnoldi(frequency, r)[source]

Construct full rank orthonormal projection basis \(\mathbf{V}\) and \(\mathbf{W}\).

The main issue that one normally encounters with MIMO systems is that the minimality assumption of the system does not guarantee the resulting Krylov space to be full rank, unlike in the SISO case. Therefore, the construction is performed vector by vector, where linearly dependent vectors are eliminated or deflated from the Krylov subspace.

If the number of inputs differs the number of outputs, both Krylov spaces will be built such that both are the same size, therefore one Krylov space may be of higher order than the other one.

Following the method for vector-wise construction in Gugercin [1].

Parameters:
  • frequency (np.ndarray) – Array containing interpolation frequencies
  • r (int) – Krylov space order
Returns:

Tuple of reduced system matrices A, B and C.

Return type:

tuple

References

[1] Gugercin, S. Projection Methods for Model Reduction of Large-Scale Dynamical
Systems PhD Thesis. Rice University 2003.
one_sided_arnoldi(frequency, r)[source]

One-sided Arnoldi method expansion about a single interpolation point, \(\sigma\). The projection matrix \(\mathbf{V}\) is constructed using an order \(r\) Krylov space. The space for a single finite interpolation point known as a Pade approximation is described by:

\[\text{range}(\textbf{V}) = \mathcal{K}_r((\sigma\mathbf{I}_n - \mathbf{A})^{-1}, (\sigma\mathbf{I}_n - \mathbf{A})^{-1}\mathbf{b})\]

In the case of an interpolation about infinity, the problem is known as partial realisation and the Krylov space is

\[\text{range}(\textbf{V}) = \mathcal{K}_r(\mathbf{A}, \mathbf{b})\]

The resulting orthogonal projection leads to the following reduced order system:

\[\begin{split}\hat{\Sigma} : \left(\begin{array}{c|c} \hat{A} & \hat{B} \\ \hline \hat{C} & {D}\end{array}\right) \text{with } \begin{cases}\hat{A}=V^TAV\in\mathbb{R}^{k\times k},\,\\ \hat{B}=V^TB\in\mathbb{R}^{k\times m},\,\\ \hat{C}=CV\in\mathbb{R}^{p\times k},\,\\ \hat{D}=D\in\mathbb{R}^{p\times m}\end{cases}\end{split}\]
Parameters:
  • frequency (complex) – Interpolation point \(\sigma \in \mathbb{C}\)
  • r (int) – Number of moments to match. Equivalent to Krylov space order and order of the ROM.
Returns:

The reduced order model matrices: \(\mathbf{A}_r\), \(\mathbf{B}_r\) and \(\mathbf{C}_r\)

Return type:

tuple

real_rational_arnoldi(frequency, r)[source]

When employing complex frequencies, the projection matrix can be normalised to be real Following Algorithm 1b in Lee(2006) :param frequency: :param r:

Returns:

restart()[source]

Implicitly Restarted Krylov Algorithm

run(ss)[source]

Performs Model Order Reduction employing Krylov space projection methods.

Supported methods include:

Algorithm Interpolation Points Systems
one_sided_arnoldi 1 SISO Systems
two_sided_arnoldi 1 SISO Systems
dual_rational_arnoldi K SISO systems and Tangential interpolation for MIMO systems
mimo_rational_arnoldi K MIMO systems. Uses vector-wise construction (more robust)
mimo_block_arnoldi K MIMO systems. Uses block Arnoldi methods (more efficient)
Parameters:ss (sharpy.linear.src.libss.ss) – State space to reduce
Returns:Reduced state space system
Return type:(libss.ss)
stable_realisation(*args, **kwargs)[source]

Remove unstable poles left after reduction

Using a Schur decomposition of the reduced plant matrix \(\mathbf{A}_m\in\mathbb{C}^{m\times m}\), the method removes the unstable eigenvalues that could have appeared after the moment-matching reduction.

The oblique projection matrices \(\mathbf{T}_L\in\mathbb{C}^{m \times p}\) and \(\mathbf{T}_R\in\mathbb{C}^{m \times p}\) result in a stable realisation

\[\mathbf{A}_s = \mathbf{T}_L^\top\mathbf{AT}_R \in \mathbb{C}^{p\times p}.\]
Parameters:A (np.ndarray) – plant matrix (if not provided self.ssrom.A will be used).
Returns:
Left and right projection matrices \(\mathbf{T}_L\in\mathbb{C}^{m \times p}\) and
\(\mathbf{T}_R\in\mathbb{C}^{m \times p}\)
Return type:tuple

References

Jaimoukha, I. M., Kasenally, E. D.. Implicitly Restarted Krylov Subspace Methods for Stable Partial Realizations. SIAM Journal of Matrix Analysis and Applications, 1997.

two_sided_arnoldi(frequency, r)[source]

Two-sided projection with a single interpolation point following the Arnoldi procedure. Very similar to the one-sided method available, but it adds the projection \(\mathbf{W}\) built using the Krylov space for the \(\mathbf{c}\) vector:

\[\mathcal{K}_r((\sigma\mathbf{I}_n - \mathbf{A})^{-T}, (\sigma\mathbf{I}_n - \mathbf{A})^{-T}\mathbf{c}^T)\subseteq\mathcal{W}=\text{range}(\mathbf{W})\]

The oblique projection \(\mathbf{VW}^T\) matches twice as many moments as the single sided projection.

The resulting system takes the form:

\[\begin{split}\hat{\Sigma} : \left(\begin{array}{c|c} \hat{A} & \hat{B} \\ \hline \hat{C} & {D}\end{array}\right) \text{with } \begin{cases}\hat{A}=W^TAV\in\mathbb{R}^{k\times k},\,\\ \hat{B}=W^TB\in\mathbb{R}^{k\times m},\,\\ \hat{C}=CV\in\mathbb{R}^{p\times k},\,\\ \hat{D}=D\in\mathbb{R}^{p\times m}\end{cases}\end{split}\]
Parameters:
  • frequency (complex) – Interpolation point \(\sigma \in \mathbb{C}\)
  • r (int) – Number of moments to match on each side. The resulting ROM will be of order \(2r\).
Returns:

The reduced order model matrices: \(\mathbf{A}_r\), \(\mathbf{B}_r\) and \(\mathbf{C}_r\).

Return type:

tuple

Utils
Krylov Model Reduction Methods Utilities
check_eye

Simple utility to verify matrix inverses

Asserts that

\[\mathbf{T}^{-1}\mathbf{T} = \mathbf{I}\]
param T:Matrix to test
type T:np.ndarray
param Tinv:Supposed matrix inverse
type Tinv:np.ndarray
param msg:Output error message if inverse check not satisfied
type msg:str
param eps:Error threshold (\(10^\varepsilon\))
type eps:float
raises:AssertionError – if matrix inverse check is not satisfied
construct_krylov

Contructs a Krylov subspace in an iterative manner following the methods of Gugercin [1].

The construction of the Krylov space is focused on Pade and partial realisation cases for the purposes of model reduction. I.e. the partial realisation form of the Krylov space is used if approx_type = 'partial_realisation'

\[\text{range}(\textbf{V}) = \mathcal{K}_r(\mathbf{A}, \mathbf{b})\]

Else, it is replaced by the Pade approximation form:

\[\text{range}(\textbf{V}) = \mathcal{K}_r((\sigma\mathbf{I}_n - \mathbf{A})^{-1}, (\sigma\mathbf{I}_n - \mathbf{A})^{-1}\mathbf{b})\]

Note that no inverses are actually computed but rather a single LU decomposition is performed at the beginning of the algorithm. Forward and backward substitution is used thereinafter to calculate the required vectors.

The algorithm also builds the Krylov space for the \(\mathbf{C}^T\) matrix. It should simply replace B and side should be side = 'c'.

Examples

Partial Realisation:

>>> V = construct_krylov(r, A, B, 'partial_realisation', 'b')
>>> W = construct_krylov(r, A, C.T, 'partial_realisation', 'c')

Pade Approximation:

>>> V = construct_krylov(r, (sigma * np.eye(nx) - A), B, 'Pade', 'b')
>>> W = construct_krylov(r, (sigma * np.eye(nx) - A), C.T, 'Pade', 'c')

References

[1]. Gugercin, S. - Projection Methods for Model Reduction of Large-Scale Dynamical Systems. PhD Thesis. Rice University. 2003.

param r:Krylov space order
type r:int
param lu_A:For Pade approximations it should be the LU decomposition of \((\sigma I - \mathbf{A})\) in tuple form, as output from the scipy.linalg.lu_factor(). For partial realisations it is simply \(\mathbf{A}\).
type lu_A:np.ndarray
param B:If doing the B side it should be \(\mathbf{B}\), else \(\mathbf{C}^T\).
type B:np.ndarray
param approx_type:
 Type of approximation: partial_realisation or Pade.
type approx_type:
 str
param side:Side of the projection b or c.
returns:Projection matrix
rtype:np.ndarray
evec

j-th unit vector (in row format)

param j:Unit vector dimension
returns:j-th unit vector
rtype:np.ndarray

Examples

>>> evec(2)
np.array([0, 1])
>>> evec(3)
np.array([0, 0, 1])
lu_factor

LU Factorisation wrapper of:

\[LU = (\sigma \mathbf{I} - \mathbf{A})\]

In the case of A being a sparse matrix, the sparse methods in scipy are employed

param sigma:Expansion frequency
type sigma:float
param A:Dynamics matrix
type A:csc_matrix or np.ndarray
returns:tuple (dense) or SuperLU (sparse) objects containing the LU factorisation
rtype:tuple or SuperLU
lu_solve

LU solve wrapper.

Computes the solution to

\[\mathbf{Ax} = \mathbf{b}\]

or

\[\mathbf{A}^T\mathbf{x} = \mathbf{b}\]

if trans=1.

It uses the SuperLU.solve() method if the input is a SuperLU or else will revert to the dense methods in scipy.

param lu_A:object or tuple containing the information of the LU factorisation
type lu_A:SuperLU or tuple
param b:Right hand side vector to solve
type b:np.ndarray
param trans:0 or 1 for either solution option.
type trans:int
returns:Solution to the system.
rtype:np.ndarray
mgs_ortho

Modified Gram-Schmidt Orthogonalisation

Orthogonalises input matrix \(\mathbf{X}\) column by column.

param X:Input matrix of dimensions \(n\) by \(m\).
type X:np.ndarray
returns:Orthogonalised matrix of dimensions \(n\) by \(m\).
rtype:np.ndarray

Notes

This method is faster than scipy’s scipy.linalg.qr() method that returns an orthogonal matrix as part of the QR decomposition, albeit at a higher number of function calls.

remove_a12

Basis change to remove the (1, 2) block of the block-ordered real Schur matrix \(\mathbf{A}\)

Being \(\mathbf{A}_s\in\mathbb{R}^{m\times m}\) a matrix of the form

\[\begin{split}\mathbf{A}_s = \begin{bmatrix} A_{11} & A_{12} \\ 0 & A_{22} \end{bmatrix}\end{split}\]

the (1,2) block is removed by solving the Sylvester equation

\[\mathbf{A}_{11}\mathbf{X} - \mathbf{X}\mathbf{A}_{22} + \mathbf{A}_{12} = 0\]

used to build the change of basis

\[\begin{split}\mathbf{T} = \begin{bmatrix} \mathbf{I}_{s,s} & -\mathbf{X}_{s,u} \\ \mathbf{0}_{u, s} & \mathbf{I}_{u,u} \end{bmatrix}\end{split}\]

where \(s\) and \(u\) are the respective number of stable and unstable eigenvalues, such that

\[\begin{split}\mathbf{TA}_s\mathbf{T}^\top = \begin{bmatrix} A_{11} & \mathbf{0} \\ 0 & A_{22} \end{bmatrix}.\end{split}\]
param As:Block-ordered real Schur matrix (can be built using sharpy.rom.utils.krylovutils.schur_ordered()).
type As:np.ndarray
param n_stable:Number of stable eigenvalues in As.
type n_stable:int
returns:Basis transformation \(\mathbf{T}\in\mathbb{R}^{m\times m}\).
rtype:np.ndarray

References

Jaimoukha, I. M., Kasenally, E. D.. Implicitly Restarted Krylov Subspace Methods for Stable Partial Realizations SIAM Journal of Matrix Analysis and Applications, 1997.

schur_ordered

Returns block ordered complex Schur form of matrix \(\mathbf{A}\)

\[\begin{split}\mathbf{TAT}^H = \mathbf{A}_s = \begin{bmatrix} A_{11} & A_{12} \\ 0 & A_{22} \end{bmatrix}\end{split}\]

where \(A_{11}\in\mathbb{C}^{s\times s}\) contains the \(s\) stable eigenvalues of \(\mathbf{A}\in\mathbb{R}^{m\times m}\).

param A:Matrix to decompose.
type A:np.ndarray
param ct:Continuous time system.
type ct:bool
returns:Tuple containing the Schur decomposition of \(\mathbf{A}\), \(\mathbf{A}_s\); the transformation \(\mathbf{T}\in\mathbb{C}^{m\times m}\); and the number of stable eigenvalues of \(\mathbf{A}\).
rtype:tuple

Notes

This function is a wrapper of scipy.linalg.schur imposing the settings required for this application.

General ROM utilities
  1. Maraniello, 14 Feb 2018
balfreq

Method for frequency limited balancing.

The Observability and controllability Gramians over the frequencies kv are solved in factorised form. Balanced modes are then obtained with a square-root method.

Details:

  • Observability and controllability Gramians are solved in factorised form through explicit integration. The number of integration points determines both the accuracy and the maximum size of the balanced model.

  • Stability over all (Nb) balanced states is achieved if:

    1. one of the Gramian is integrated through the full Nyquist range
    2. the integration points are enough.

Input:

  • DictBalFreq: dictionary specifying integration method with keys:

    • frequency: defines limit frequencies for balancing. The balanced
      model will be accurate in the range [0,F], where F is the value of this key. Note that F units must be consistent with the units specified in the self.ScalingFacts dictionary.
    • method_low: ['gauss','trapz'] specifies whether to use gauss quadrature or trapezoidal rule in the low-frequency range [0,F].
    • options_low: options to use for integration in the low-frequencies. These depend on the integration scheme (See below).
    • method_high: method to use for integration in the range [F,F_N], where F_N is the Nyquist frequency. See ‘method_low’.
    • options_high: options to use for integration in the high-frequencies.
    • check_stability: if True, the balanced model is truncated to eliminate unstable modes - if any is found. Note that very accurate balanced model can still be obtained, even if high order modes are unstable. Note that this option is overridden if “”
    • get_frequency_response: if True, the function also returns the frequency response evaluated at the low-frequency range integration points. If True, this option also allows to automatically tune the balanced model.
Future options:
  • Ncpu: for parallel run
The following integration schemes are available:
  • trapz: performs integration over equally spaced points using trapezoidal rule. It accepts options dictionaries with keys:

    • points: number of integration points to use (including domain boundary)
  • gauss performs gauss-lobotto quadrature. The domain can be partitioned in Npart sub-domain in which the gauss-lobotto quadrature of order Ord can be applied. A total number of Npart*Ord points is required. It accepts options dictionaries of the form:

    • partitions: number of partitions
    • order: quadrature order.

Examples

The following dictionary

>>>   DictBalFreq={'frequency': 1.2,
>>>                'method_low': 'trapz',
>>>                'options_low': {'points': 12},
>>>                'method_high': 'gauss',
>>>                'options_high': {'partitions': 2, 'order': 8},
>>>                'check_stability': True }

balances the state-space model in the frequency range [0, 1.2] using:

  1. 12 equally-spaced points integration of the Gramians in the low-frequency range [0,1.2] and
  2. A 2 Gauss-Lobotto 8-th order quadratures of the controllability Gramian in the high-frequency range.

A total number of 28 integration points will be required, which will result into a balanced model with number of states

>>>    min{ 2*28* number_inputs, 2*28* number_outputs }

The model is finally truncated so as to retain only the first Ns stable modes.

balreal_direct_py

Find balanced realisation of continuous (DLTI = False) and discrete (DLTI = True) time of LTI systems using scipy libraries.

The function proceeds to achieve balanced realisation of the state-space system by first solving the Lyapunov equations. They are solved using Barlets-Stewart algorithm for Sylvester equation, which is based on A matrix Schur decomposition.

\[\begin{split}\mathbf{A\,W_c + W_c\,A^T + B\,B^T} &= 0 \\ \mathbf{A^T\,W_o + W_o\,A + C^T\,C} &= 0\end{split}\]

to obtain the reachability and observability gramians, which are positive definite matrices.

Then, the gramians are decomposed into their Cholesky factors such that:

\[\begin{split}\mathbf{W_c} &= \mathbf{Q_c\,Q_c^T} \\ \mathbf{W_o} &= \mathbf{Q_o\,Q_o^T}\end{split}\]

A singular value decomposition (SVD) of the product of the Cholesky factors is performed

\[(\mathbf{Q_o^T\,Q_c}) = \mathbf{U\,\Sigma\,V^*}\]

The singular values are then used to build the transformation matrix \(\mathbf{T}\)

\[\begin{split}\mathbf{T} &= \mathbf{Q_c\,V\,\Sigma}^{-1/2} \\ \mathbf{T}^{-1} &= \mathbf{\Sigma}^{-1/2}\,\mathbf{U^T\,Q_o^T}\end{split}\]

The balanced system is therefore of the form:

\[\begin{split}\mathbf{A_b} &= \mathbf{T\,A\,T^{-1}} \\ \mathbf{B_b} &= \mathbf{T\,B} \\ \mathbf{C_b} &= \mathbf{C\,T^{-1}} \\ \mathbf{D_b} &= \mathbf{D}\end{split}\]

Warning

This function may be less computationally efficient than the balreal Matlab implementation and does not offer the option to bound the realisation in frequency and time.

Notes

Lyapunov equations are solved using Barlets-Stewart algorithm for Sylvester equation, which is based on A matrix Schur decomposition.

param A:

Plant Matrix

type A:

np.ndarray

param B:

Input Matrix

type B:

np.ndarray

param C:

Output Matrix

type C:

np.ndarray

param DLTI:

Discrete time state-space flag

type DLTI:

bool

param Schur:

Use Schur decomposition to solve the Lyapunov equations

type Schur:

bool

returns:
Tuple of the form (S, T, Tinv) containing:
  • Singular values in diagonal matrix (S)
  • Transformation matrix (T).
  • Inverse transformation matrix(Tinv).
rtype:

tuple of np.ndarrays

References

Anthoulas, A.C.. Approximation of Large Scale Dynamical Systems. Chapter 7. Advances in Design and Control. SIAM. 2005.

balreal_iter

Find balanced realisation of DLTI system.

Notes

Lyapunov equations are solved using iterative squared Smith algorithm, in its low or full rank version. These implementations are as per the low_rank_smith and smith_iter functions respectively but, for computational efficiency, the iterations are rewritten here so as to solve for the observability and controllability Gramians contemporary.

  • Exploiting sparsity:

    This algorithm is not ideal to exploit sparsity. However, the following strategies are implemented:

    • if the A matrix is provided in sparse format, the powers of A will be calculated exploiting sparsity UNTIL the number of non-zero elements is below 15% the size of A. Upon this threshold, the cost of the matrix multiplication rises dramatically, and A is hence converted to a dense numpy array.
balreal_iter_old

Find balanced realisation of DLTI system.

Notes: Lyapunov equations are solved using iterative squared Smith algorithm, in its low or full rank version. These implementations are as per the low_rank_smith and smith_iter functions respectively but, for computational efficiency,, the iterations are rewritten here so as to solve for the observability and controllability Gramians contemporary.

check_stability

Checks the stability of the system.

param A:System plant matrix
type A:np.ndarray
param dt:Discrete time system
type dt:bool
returns:True if the system is stable
rtype:bool
eigen_dec

Eigen decomposition of state-space model (either discrete or continuous time) defined by the A,B,C matrices. Eigen-states are organised in decreasing damping order or increased frequency order such that the truncation

A[:N,:N], B[:N,:], C[:,:N]

will retain the least N damped (or lower frequency) modes.

If the eigenvalues of A, eigs, are complex, the state-space is automatically convert into real by separating its real and imaginary part. This procedure retains the minimal number of states as only 2 equations are added for each pair of complex conj eigenvalues. Extra care is however required when truncating the system, so as to ensure that the chosen value of N does not retain the real part, but not the imaginary part, of a complex pair.

For this reason, the function also returns an optional output, Nlist, such that, for each N in Nlist, the truncation

A[:N,:N], B[:N,:], C[:,:N]

does guarantee that both the real and imaginary part of a complex conj pair is included in the truncated model. Note that if `order_by == None, the eigs and UR must be given in input and must be such that complex pairs are stored consecutively.

param A:state-space matrix
param B:state-space matrix
param C:matrices of state-space model
param dlti:specifies whether discrete (True) or continuous-time. This information is only required to order the eigenvalues in decreasing dmaping order
param N:number of states to retain. If None, all states are retained
param eigs,Ur:eigenvalues and right eigenvector of A matrix as given by: eigs,Ur=scipy.linalg.eig(A,b=None,left=False,right=True)
param Urinv:inverse of Ur
param order_by={‘damp’,’freq’,’stab’}:
 order according to increasing damping (damp)
param or decreasing frequency:
 If None, the same order as eigs/UR is followed.
type or decreasing frequency:
 freq) or decreasing damping (stab
param tol:absolute tolerance used to identify complex conj pair of eigenvalues
param complex:if true, the system is left in complex form

Returns: (Aproj,Bproj,Cproj): state-space matrices projected over the first N (or N+1

if N removes the imaginary part equations of a complex conj pair of eigenvalues) related to the least damped modes

Nlist: list of acceptable truncation values

get_gauss_weights

Returns gauss-legendre frequency grid (kv of length Npart*order) and weights (wv) for Gramians integration.

The integration grid is divided into Npart partitions, and in each of them integration is performed using a Gauss-Legendre quadrature of order order.

Note: integration points are never located at k0 or kend, hence there is no need for special treatment as in (for e.g.) a uniform grid case (see get_unif_weights)

get_trapz_weights

Returns uniform frequency grid (kv of length Nk) and weights (wv) for Gramians integration using trapezoidal rule. If knyq is True, it is assumed that kend is also the Nyquist frequency.

low_rank_smith
Low-rank smith algorithm for Stein equation
A.T X A - X = -Q Q.T

The algorithm can only be used if T is symmetric positive-definite, but this is not checked in this routine for computational performance. The solution X is provided in its factorised form:

X=Z Z.T

As in the most general case, a solution X exists only if the eigenvalues of S are stricktly smaller than one, and the algorithm will not converge otherwise. The algorithm can not exploits parsity, hence, while convergence can be improved for very large matrices, it can not be employed if matrices are too large to be stored in memory.

Parameters: - tol: tolerance for stopping convergence of Smith algorithm - Square: if true the squared-Smith algorithm is used - tolSVD: tolerance for reduce Z matrix based on singular values - kmax: if given, the Z matrix is forced to have size kmax - tolAbs: if True, the tolerance - fullOut: not implemented - Convergence: ‘Zk’,’res’.

  • If ‘Zk’ the iteration is stopped when the inf norm of the incremental

matrix goes below tol. - If ‘res’ the residual of the Lyapunov equation is computed. This strategy may fail to converge if kmax is too low or tolSVD too large!

Ref. P. Benner, G.E. Khoury and M. Sadkane, “On the squared Smith method for large-scale Stein equations”, 2014.

modred

Produces a reduced order model with N states from balanced or modal system SSb. Both “truncation” and “residualisation” methods are employed.

Note: - this method is designed for small size systems, i.e. a deep copy of SSb is produced by default.

res_discrete_lyap
Provides residual of discrete Lyapunov equation:
A.T X A - X = -Q Q.T
If Factorised option is true,
X=Z*Z.T

otherwise X=Z is chosen.

Reminder: contr: A W A.T - W = - B B.T obser: A.T W A - W = - C.T C

smith_iter
Solves the Stein equation
S.T X S - X = -T

by mean of Smith or squared-Smith algorithm. Note that a solution X exists only if the eigenvalues of S are stricktly smaller than one, and the algorithm will not converge otherwise. The algorithm can not exploit sparsity, hence, while convergence can be improved for very large matrices, it can not be employed if matrices are too large to be stored in memory.

Ref. Penzt, “A cyclic low-rank Smith method for large sparse Lyapunov equations”, 2000.

tune_rom

Starting from a balanced DLTI, this function determines the number of states N required in a ROM (obtained either through ‘residualisation’ or ‘truncation’ as specified in method - see also librom.modred) to match the frequency response of SSb over the frequency array, kv, with absolute accuracy tol. gv contains the balanced system Hankel singular value, and is used to determine the upper bound for the ROM order N.

Unless kv does not conver the full Nyquist frequency range, the ROM accuracy is not guaranteed to increase monothonically with the number of states. To account for this, two criteria can be used to determine the ROM convergence:

  • convergence=’all’: in this case, the number of ROM states N is chosen

such that any ROM of order greater than N produces an error smaller than tol. To guarantee this the ROM frequency response is computed for all N<=Nb, where Nb is the number of balanced states. This method is numerically inefficient.

  • convergence=’min’: atempts to find the minimal number of states to

achieve the accuracy tol.

Note: - the input state-space model, SSb, must be balanced. - the routine in not implemented for numerical efficiency and assumes that SSb is small.

Methods for the interpolation of DLTI ROMs

This is library for state-space models interpolation. These routines are intended for small size state-space models (ROMs), hence some methods may not be optimised to exploit sparsity structures. For generality purposes, all methods require in input interpolatory weights.

The module includes the methods:

  • transfer_function(): returns an interpolatory state-space model based on the transfer function method [1]. This method is general and is, effectively, a wrapper of the sharpy.linear.src.libss.join() method.
  • BT_transfer_function(): evolution of transfer function methods. The growth of the interpolated system size is avoided through balancing.

References:

[1] Benner, P., Gugercin, S. & Willcox, K., 2015. A Survey of Projection-Based Model Reduction Methods for Parametric Dynamical Systems. SIAM Review, 57(4), pp.483–531.

Author: S. Maraniello

Date: Mar-Apr 2019

FLB_transfer_function

Returns an interpolatory state-space model based on the transfer function method [1]. This method is applicable to frequency limited balanced state-space models only.

Features:

  • stability preserved
  • the interpolated state-space model has the same size than the tabulated ones
  • all state-space models, need to have the same size and the same numbers of hankel singular values.
  • suitable for any ROM
param SS_list:

List of state-space models instances of sharpy.linear.src.libss.ss class.

type SS_list:

list

param wv:

list of interpolatory weights.

type wv:

list

param U_list:

small size, thin SVD factors of Gramians square roots of each state space model (\(\mathbf{U}\)).

type U_list:

list

param VT_list:

small size, thin SVD factors of Gramians square roots of each state space model (\(\mathbf{V}^\top\)).

type VT_list:

list

param hsv_list:

small size, thin SVD factors of Gramians square roots of each state space model. If None, it is assumed that

U_list = [ U_i sqrt(hsv_i) ] VT_list = [ sqrt(hsv_i) V_i.T ]

where U_i and V_i.T are square matrices and hsv is an array.

type hsv_list:

list

param M_list:

for fast on-line evaluation. Small size product of Gramians factors of each state-space model. Each element of this list is equal to: M_i = U_i hsv_i V_i.T

type M_list:

list

Notes

Message for future generations:

  • the implementation is divided into an offline and online part.

References:

Maraniello S. and Palacios R., Frequency-limited balanced truncation for parametric reduced-order modelling of the UVLM. Only in the best theaters.

See also

Frequency-Limited Balanced ROMs may be obtained from SHARPy using sharpy.rom.balanced.FrequencyLimited.

InterpROM
class sharpy.rom.utils.librom_interp.InterpROM(SS, VV=None, WWT=None, Vref=None, WTref=None, method_proj=None)[source]

State-space 1D interpolation class.

This class allows interpolating from a list of state-space models, SS.

State-space models are required to have the same number of inputs and outputs and need to have the same number of states.

For state-space interpolation, state-space models also need to be defined over the same set of generalised coordinates. If this is not the case, the projection matrices W and V used to produce the ROMs, ie

\[\mathbf{A}_{proj} = \mathbf{W}^\top \mathbf{A V}\]

where A is the full-states matrix, also need to be provided. This will allow projecting the state-space models onto a common set of generalised coordinates before interpoling.

For development purposes, the method currently creates a hard copy of the projected matrices into the self.AA, self.BB, self.CC lists

Inputs:

  • SS: list of state-space models (instances of libss.ss class)

  • VV: list of V matrices used to produce SS. If None, it is assumed that ROMs are defined over the same basis

  • WWT: list of W^T matrices used to derive the ROMs.

  • Vref, WTref: reference subspaces for projection. Some methods neglect this input (e.g. panzer)

  • method_proj: method for projection of state-space models over common coordinates. Available options are:

    • leastsq: find left/right projectors using least squares approx. Suitable for all basis.

    • strongMAC: strong Modal Assurance Criterion [4] enforcement for general basis. See Ref. [3], Eq. (7)

    • strongMAC_BT: strong Modal Assurance Criterion [4] enforcement for basis obtained by Balanced Truncation. Equivalent to strongMAC

    • maraniello_BT: this is equivalent to strongMAC and strongMAC_BT but avoids inversions. However, performance are the same as other strongMAC approaches - it works only when basis map the same subspaces

    • weakMAC_right_orth: weak MAC enforcement [1,3] for state-space models with right orthonoraml basis, i.e. V.T V = I. This is like Ref. [1], but implemented only on one side.

    • weakMAC: implementation of weak MAC enforcement for a general system. The method orthonormalises the right basis (V) and then solves the orthogonal Procrustes problem.

    • for orthonormal basis (V.T V = I): !!! These methods are not tested !!!

      • panzer: produces a new reference point based on svd [2]
      • amsallem: project over Vref,WTref [1]

References:

[1] D. Amsallem and C. Farhat, An online method for interpolating linear parametric reduced-order models, SIAM J. Sci. Comput., 33 (2011), pp. 2169–2198.

[2] Panzer, J. Mohring, R. Eid, and B. Lohmann, Parametric model order reduction by matrix interpolation, at–Automatisierungstechnik, 58 (2010), pp. 475–484.

[3] Mahony, R., Sepulchre, R. & Absil, P. -a., 2004. Riemannian Geometry of Grassmann Manifolds with a View on Algorithmic Computation. Acta Applicandae Mathematicae, 80(2), pp.199–220.

[4] Geuss, M., Panzer, H. & Lohmann, B., 2013. On parametric model order reduction by matrix interpolation. 2013 European Control Conference (ECC), pp.3433–3438.

project()[source]

Project the state-space models onto the generalised coordinates of state-space model IImap

transfer_function

Returns an interpolatory state-space model based on the transfer function method [1]. This method is general and is, effectively, a wrapper of the sharpy.linear.src.libss.join() method.

Features:

  • stability preserved
  • system size increases with interpolatory order, but can be optimised for fast on-line evaluation
param SS_list:List of state-space models instances of sharpy.linear.src.libss.ss class.
type SS_list:list
param wv:list of interpolatory weights.
type wv:list

Notes

For fast online evaluation, this routine can be optimised to return a class that handles each state-space model independently. See ref. [1] for more details.

References

[1] Benner, P., Gugercin, S. & Willcox, K., 2015. A Survey of Projection-Based Model Reduction Methods for Parametric Dynamical Systems. SIAM Review, 57(4), pp.483–531.

Structural Packages

Models
Element
class sharpy.structure.models.beamstructures.Element(ielem, n_nodes, global_connectivities, coordinates, frame_of_reference_delta, structural_twist, num_mem, stiff_index, mass_index)[source]

This class stores all the required data for the definition of a linear or quadratic beam element.

get_triad()[source]

Generates two unit vectors in body FoR that define the local FoR for a beam element. These vectors are calculated using frame_of_reference_delta :return:

Utils
LagrangeConstraints library

LagrangeConstraints library

Library used to create the matrices associate to boundary conditions through the method of Lagrange Multipliers

Args:

Returns:

Examples:
To use this library: import sharpy.structure.utils.lagrangeconstraints as lagrangeconstraints

Notes:

define_FoR_dof

define_FoR_dof

Define the position of the first degree of freedom associated to a certain frame of reference

param MB_beam:list of ‘Beam’
type MB_beam:list
param node_body:
 body to which the node belongs
type node_body:int
param num_node:number os the node within the body
type num_node:int
returns:first degree of freedom associated to the node
rtype:node_dof(int)

Examples:

Notes:

define_node_dof

define_node_dof

Define the position of the first degree of freedom associated to a certain node

param MB_beam:list of ‘Beam’
type MB_beam:list
param node_body:
 body to which the node belongs
type node_body:int
param num_node:number os the node within the body
type num_node:int
returns:first degree of freedom associated to the node
rtype:node_dof(int)

Examples:

Notes:

define_num_LM_eq

define_num_LM_eq

Define the number of equations needed to define the boundary boundary conditions

param lc_list():
 list of all the defined contraints
returns:number of new equations needed to define the boundary boundary conditions
rtype:num_LM_eq(int)

Examples

num_LM_eq = lagrangeconstraints.define_num_LM_eq(lc_list)

Notes:

generate_lagrange_matrix

generate_lagrange_matrix

Generates the matrices associated to the Lagrange multipliers boundary conditions

param lc_list():
 list of all the defined contraints
param MBdict:dictionary with the MultiBody and LagrangeMultipliers information
type MBdict:MBdict
param MB_beam:list of ‘beams’ of each of the bodies that form the system
type MB_beam:list
param MB_tstep:list of ‘StructTimeStepInfo’ of each of the bodies that form the system
type MB_tstep:list
param num_LM_eq:
 number of new equations needed to define the boundary boundary conditions
type num_LM_eq:int
param sys_size:total number of degrees of freedom of the multibody system
type sys_size:int
param dt:time step
type dt:float
param Lambda:list of Lagrange multipliers values
type Lambda:numpy array
param Lambda_dot:
 list of the first derivative of the Lagrange multipliers values
type Lambda_dot:
 numpy array
param dynamic_or_static:
 string defining if the computation is dynamic or static
type dynamic_or_static:
 str
returns:Damping matrix associated to the Lagrange Multipliers equations LM_K (numpy array): Stiffness matrix associated to the Lagrange Multipliers equations LM_Q (numpy array): Vector of independent terms associated to the Lagrange Multipliers equations
rtype:LM_C (numpy array)

Examples:

Notes:

get_mode_zeta

Retrieves the UVLM grid nodal displacements associated to the eigenvector eigvect

scale_mode
Scales the eigenvector such that:
  1. the maximum change in component of the beam cartesian rotation vector
is equal to rot_max_deg degrees.
  1. the maximum translational displacement does not exceed perc_max the

maximum nodal position.

Warning

If the eigenvector is in state-space form, only the first half of the eigenvector is scanned for determining the scaling.

write_modes_vtk

Writes a vtk file for each of the first NumLambda eigenvectors. When these are associated to the state-space form of the structural equations, only the displacement field is saved.

write_zeta_vtk

Given a list of arrays representing the coordinates of a set of n_surf UVLM lattices and organised as:

zeta[n_surf][3,M+1,N=1]

this function writes a vtk for each of the n_surf surfaces.

Input:
  • zeta: lattice coordinates to plot
  • zeta_ref: reference lattice used to compute the magnitude of displacements
  • filename_root: initial part of filename (full path) without file

extension (.vtk)

Xbopts
sharpy.structure.utils.xbeamlib.Xbopts
cbeam3_asbly_dynamic

Used by autodoc_mock_imports.

cbeam3_asbly_static

Used by autodoc_mock_imports.

cbeam3_correct_gravity_forces

Used by autodoc_mock_imports.

cbeam3_loads

Used by autodoc_mock_imports.

cbeam3_solv_modal

Used by autodoc_mock_imports.

cbeam3_solv_nlnstatic

Used by autodoc_mock_imports.

xbeam3_asbly_dynamic

Used by autodoc_mock_imports.

Utilities

Algebra package

Algebra package

Extensive library with geometrical and algebraic operations

Note:
Tests can be found in tests/utils/algebra_test
cross3

Computes the cross product of two vectors (v and w) with size 3

crv2quat

Converts a Cartesian rotation vector,

\[\vec{\psi} = \psi\,\mathbf{\hat{n}}\]

into a “minimal rotation” quaternion, i.e. being the quaternion, \(\vec{\chi}\), defined as:

\[\vec{\chi}= \left[\cos\left(\frac{\psi}{2}\right),\, \sin\left(\frac{\psi}{2}\right)\mathbf{\hat{n}}\right]\]

the rotation axis, \(\mathbf{\hat{n}}\) is such that the rotation angle, \(\psi\), is in \([-\pi,\,\pi]\) or, equivalently, \(\chi_0\ge0\).

param psi:Cartesian Rotation Vector, CRV: \(\vec{\psi} = \psi\,\mathbf{\hat{n}}\).
type psi:np.array
returns:equivalent quaternion \(\vec{\chi}\)
rtype:np.array
crv2rotation

Given a Cartesian rotation vector, \(\boldsymbol{\Psi}\), the function produces the rotation matrix required to rotate a vector according to \(\boldsymbol{\Psi}\).

The rotation matrix is given by

\[\mathbf{R} = \mathbf{I} + \frac{\sin||\boldsymbol{\Psi}||}{||\boldsymbol{\Psi}||} \tilde{\boldsymbol{\Psi}} + \frac{1-\cos{||\boldsymbol{\Psi}||}}{||\boldsymbol{\Psi}||^2}\tilde{\boldsymbol{\Psi}} \tilde{\boldsymbol{\Psi}}\]

To avoid the singularity when \(||\boldsymbol{\Psi}||=0\), the series expansion is used

\[\mathbf{R} = \mathbf{I} + \tilde{\boldsymbol{\Psi}} + \frac{1}{2!}\tilde{\boldsymbol{\Psi}}^2.\]
param psi:Cartesian rotation vector \(\boldsymbol{\Psi}\).
type psi:np.array
returns:equivalent rotation matrix
rtype:np.array

References

Geradin and Cardona, Flexible Multibody Dynamics: A finite element approach. Chapter 4

crv2tan

Returns the tangential operator, \(\mathbf{T}(\boldsymbol{\Psi})\), that is a function of the Cartesian Rotation Vector, \(\boldsymbol{\Psi}\).

\[\boldsymbol{T}(\boldsymbol{\Psi}) = \mathbf{I} + \left(\frac{\cos ||\boldsymbol{\Psi}|| - 1}{||\boldsymbol{\Psi}||^2}\right)\tilde{\boldsymbol{\Psi}} + \left(1 - \frac{\sin||\boldsymbol{\Psi}||}{||\boldsymbol{\Psi}||}\right) \frac{\tilde{\boldsymbol{\Psi}}\tilde{\boldsymbol{\Psi}}}{||\boldsymbol{\Psi}||^2}\]

When the norm of the CRV approaches 0, the series expansion expression is used in-lieu of the above expression

\[\boldsymbol{T}(\boldsymbol{\Psi}) = \mathbf{I} -\frac{1}{2!}\tilde{\boldsymbol{\Psi}} + \frac{1}{3!}\tilde{\boldsymbol{\Psi}}^2\]
param psi:Cartesian Rotation Vector, \(\boldsymbol{\Psi}\).
type psi:np.array
returns:Tangential operator
rtype:np.array

References

Geradin and Cardona. Flexible Multibody Dynamics: A Finite Element Approach. Chapter 4.

crv_bounds

Forces the Cartesian rotation vector norm, \(\|\vec{\psi}\|\), to be in the range \([-\pi,\pi]\), i.e. determines the rotation axis orientation, \(\mathbf{\hat{n}}\), so as to ensure “minimal rotation”.

param crv_ini:Cartesian rotation vector, \(\vec{\psi}\)
type crv_ini:np.array
returns:modified and bounded, equivalent Cartesian rotation vector
rtype:np.array
der_CcrvT_by_v

Being C=C(fv0) the rotation matrix depending on the Cartesian rotation vector fv0 and defined as C=crv2rotation(fv0), the function returns the derivative, w.r.t. the CRV components, of the vector dot(C.T,v), where v is a constant vector.

The elements of the resulting derivative matrix D are ordered such that:

\[d(C.T*v) = D*d(fv0)\]

where \(d(.)\) is a delta operator.

der_Ccrv_by_v

Being C=C(fv0) the rotational matrix depending on the Cartesian rotation vector fv0 and defined as C=crv2rotation(fv0), the function returns the derivative, w.r.t. the CRV components, of the vector dot(C,v), where v is a constant vector.

The elements of the resulting derivative matrix D are ordered such that:

\[d(C*v) = D*d(fv0)\]

where \(d(.)\) is a delta operator.

der_Ceuler_by_v

Provides the derivative of the product between the rotation matrix \(C^{AG}(\mathbf{\Theta})\) and a constant vector, \(\mathbf{v}\), with respect to the Euler angles, \(\mathbf{\Theta}=[\phi,\theta,\psi]^T\):

\[\frac{\partial}{\partial\Theta}(C^{AG}(\Theta)\mathbf{v}^G) = \frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\]

where \(\frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\) is the resulting 3 by 3 matrix.

Being \(C^{AG}(\Theta)\) the rotation matrix from the G frame to the A frame in terms of the Euler angles \(\Theta\) as:

\[\begin{split}C^{AG}(\Theta) = \begin{bmatrix} \cos\theta\cos\psi & -\cos\theta\sin\psi & \sin\theta \\ \cos\phi\sin\psi + \sin\phi\sin\theta\cos\psi & \cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi & -\sin\phi\cos\theta \\ \sin\phi\sin\psi - \cos\phi\sin\theta\cos\psi & \sin\phi\cos\psi + \cos\phi\sin\theta\sin\psi & \cos\phi\cos\theta \end{bmatrix}\end{split}\]

the components of the derivative at hand are the following, where \(f_{1\theta} = \frac{\partial \mathbf{f}_1}{\partial\theta}\).

\[\begin{split}f_{1\phi} =&0 \\ f_{1\theta} = &-v_1\sin\theta\cos\psi \\ &+v_2\sin\theta\sin\psi \\ &+v_3\cos\theta \\ f_{1\psi} = &-v_1\cos\theta\sin\psi \\ &- v_2\cos\theta\cos\psi\end{split}\]
\[\begin{split}f_{2\phi} = &+v_1(-\sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi) + \\ &+v_2(-\sin\phi\cos\psi - \cos\phi\sin\theta\sin\psi) + \\ &+v_3(-\cos\phi\cos\theta)\\ f_{2\theta} = &+v_1(\sin\phi\cos\theta\cos\psi) + \\ &+v_2(-\sin\phi\cos\theta\sin\psi) +\\ &+v_3(\sin\phi\sin\theta) \\ f_{2\psi} = &+v_1(\cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi) + \\ &+v_2(-\cos\phi\sin\psi - \sin\phi\sin\theta\cos\psi)\end{split}\]
\[\begin{split}f_{3\phi} = &+v_1(\cos\phi\sin\psi+\sin\phi\sin\theta\cos\psi) + \\ &+v_2(\cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi) + \\ &+v_3(-\sin\phi\cos\theta)\\ f_{3\theta} = &+v_1(-\cos\phi\cos\theta\cos\psi)+\\ &+v_2(\cos\phi\cos\theta\sin\psi) + \\ &+v_3(-\cos\phi\sin\theta)\\ f_{3\psi} = &+v_1(\sin\phi\cos\psi+\cos\phi\sin\theta\sin\psi) + \\ &+v_2(-\sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi)\end{split}\]
param euler:Vector of Euler angles, \(\mathbf{\Theta} = [\phi, \theta, \psi]\), in radians.
type euler:np.ndarray
param v:3 dimensional vector in G frame.
type v:np.ndarray
returns:Resulting 3 by 3 matrix \(\frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\).
rtype:np.ndarray
der_Ceuler_by_v_NED

Provides the derivative of the product between the rotation matrix \(C^{AG}(\mathbf{\Theta})\) and a constant vector, \(\mathbf{v}\), with respect to the Euler angles, \(\mathbf{\Theta}=[\phi,\theta,\psi]^T\):

\[\frac{\partial}{\partial\Theta}(C^{AG}(\Theta)\mathbf{v}^G) = \frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\]

where \(\frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\) is the resulting 3 by 3 matrix.

Being \(C^{AG}(\Theta)\) the rotation matrix from the G frame to the A frame in terms of the Euler angles \(\Theta\) as:

\[\begin{split}C^{AG}(\Theta) = \begin{bmatrix} \cos\theta\cos\psi & \cos\theta\sin\psi & -\sin\theta \\ -\cos\phi\sin\psi + \sin\phi\sin\theta\cos\psi & \cos\phi\cos\psi + \sin\phi\sin\theta\sin\psi & \sin\phi\cos\theta \\ \sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi & -\sin\phi\cos\psi + \cos\psi\sin\theta\sin\psi & \cos\phi\cos\theta \end{bmatrix}\end{split}\]

the components of the derivative at hand are the following, where \(f_{1\theta} = \frac{\partial \mathbf{f}_1}{\partial\theta}\).

\[\begin{split}f_{1\phi} =&0 \\ f_{1\theta} = &-v_1\sin\theta\cos\psi \\ &-v_2\sin\theta\sin\psi \\ &-v_3\cos\theta \\ f_{1\psi} = &-v_1\cos\theta\sin\psi + v_2\cos\theta\cos\psi\end{split}\]
\[\begin{split}f_{2\phi} = &+v_1(\sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi) + \\ &+v_2(-\sin\phi\cos\psi + \cos\phi\sin\theta\sin\psi) + \\ &+v_3(\cos\phi\cos\theta) \\ f_{2\theta} = &+v_1(\sin\phi\cos\theta\cos\psi) + \\ &+v_2(\sin\phi\cos\theta\sin\psi) +\\ &-v_3(\sin\phi\sin\theta) \\ f_{2\psi} = &+v_1(-\cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi) + \\ &+v_2(-\cos\phi\sin\psi + \sin\phi\sin\theta\cos\psi)\end{split}\]
\[\begin{split}f_{3\phi} = &+v_1(\cos\phi\sin\psi-\sin\phi\sin\theta\cos\psi) + \\ &+v_2(-\cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi) + \\ &+v_3(-\sin\phi\cos\theta) \\ f_{3\theta} = &+v_1(\cos\phi\cos\theta\cos\psi)+\\ &+v_2(\cos\phi\cos\theta\sin\psi) + \\ &+v_3(-\cos\phi\sin\theta) \\ f_{3\psi} = &+v_1(\sin\phi\cos\psi-\cos\phi\sin\theta\sin\psi) + \\ &+v_2(\sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi)\end{split}\]

Note

This function is defined in a North East Down frame which is not the typically used one in SHARPy.

param euler:Vector of Euler angles, \(\mathbf{\Theta} = [\phi, \theta, \psi]\), in radians.
type euler:np.ndarray
param v:3 dimensional vector in G frame.
type v:np.ndarray
returns:Resulting 3 by 3 matrix \(\frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\).
rtype:np.ndarray
der_CquatT_by_v

Returns the derivative with respect to quaternion components of a projection matrix times a constant vector.

Being \(\mathbf{C}=\mathbf{R}(\boldsymbol{\chi})^\top\) the projection matrix depending on the quaternion \(\boldsymbol{\chi}\) and obtained through the function defined as C=quat2rotation(q).T, this function returns the derivative with respect to the quaternion components, of the vector \((\mathbf{C\cdot v})\), where \(\mathbf{v}\) is a constant vector.

The derivative operation is defined as:

\[\delta(\mathbf{C}\cdot \mathbf{v}) = \frac{\partial}{\partial\boldsymbol{\chi}}\left(\mathbf{C\cdot v}\right)\delta\boldsymbol{\chi}\]

where, for simplicity, we define

\[\mathbf{D} = \frac{\partial}{\partial\boldsymbol{\chi}}\left(\mathbf{C\cdot v}\right) \in \mathbb{R}^{3\times4}\]

and \(\delta(\bullet)\) is a delta operator.

The members of \(\mathbf{D}\) are the following:

\[\begin{split}\mathbf{D}_{11} &= 2 (q_0 v_x - q_2 v_z + q_3 v_y)\\ \mathbf{D}_{12} &= 2 (q_1 v_x - q_2 v_y + q_3 v_z)\\ \mathbf{D}_{13} &= 2 (-q_0 v_z + q_1 v_y - q_2 v_x)\\ \mathbf{D}_{14} &= 2 (q_0 v_y + q_1 v_z - q_3 v_x)\end{split}\]
\[\begin{split}\mathbf{D}_{21} &= 2 (q_0 v_y + q_1 v_z - q_3 v_x)\\ \mathbf{D}_{22} &= 2 (q_0 v_z - q_1 v_y + q_2 v_x)\\ \mathbf{D}_{23} &= 2 (q_1 v_x + q_2 v_y + q_3 v_z)\\ \mathbf{D}_{24} &= 2 (-q_0 v_x + q_2 v_z - q_3 v_y)\end{split}\]
\[\begin{split}\mathbf{D}_{31} &= 2 (q_0 v_z - q_1 v_y + q_2 v_x)\\ \mathbf{D}_{32} &= 2 (-q_0 v_y - q_1 v_z + q_3 v_x)\\ \mathbf{D}_{33} &= 2 (q_0 v_x - q_2 v_z + q_3 v_y)\\ \mathbf{D}_{34} &= 2 (q_1 v_x + q_2 v_y + q_3 v_z)\\\end{split}\]
returns:\(\mathbf{D}\) matrix.
rtype:np.array
der_Cquat_by_v

Being C=C(quat) the rotational matrix depending on the quaternion q and defined as C=quat2rotation(q), the function returns the derivative, w.r.t. the quanternion components, of the vector dot(C,v), where v is a constant vector.

The elements of the resulting derivative matrix D are ordered such that:

\[d(C*v) = D*d(q)\]

where \(d(.)\) is a delta operator.

der_Peuler_by_v

Provides the derivative of the product between the projection matrix \(P^{AG}(\mathbf{\Theta})\) (that projects a vector in G frame onto A frame) and a constant vector expressed in G frame of reference, \(\mathbf{v}_G\), with respect to the Euler angles, \(\mathbf{\Theta}=[\phi,\theta,\psi]^T\):

\[\frac{\partial}{\partial\Theta}(P^{AG}(\Theta)\mathbf{v}^G) = \frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\]

where \(\frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\) is the resulting 3 by 3 matrix.

Being \(P^{AG}(\Theta)\) the projection matrix from the G frame to the A frame in terms of the Euler angles \(\Theta\) as \(P^{AG}(\Theta) = \tau_x(-\Phi)\tau_y(-\Theta)\tau_z(-\Psi)\), where the rotation matrix is expressed as:

\[\begin{split}C^{AG}(\Theta) = \begin{bmatrix} \cos\theta\cos\psi & -\cos\theta\sin\psi & \sin\theta \\ \cos\phi\sin\psi + \sin\phi\sin\theta\cos\psi & \cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi & -\sin\phi\cos\theta \\ \sin\phi\sin\psi - \cos\phi\sin\theta\cos\psi & \sin\phi\cos\psi + \cos\phi\sin\theta\sin\psi & \cos\phi\cos\theta \end{bmatrix}\end{split}\]

and the projection matrix as:

\[\begin{split}P^{AG}(\Theta) = \begin{bmatrix} \cos\theta\cos\psi & \cos\theta\sin\psi & -\sin\theta \\ -\cos\phi\sin\psi + \sin\phi\sin\theta\cos\psi & \cos\phi\cos\psi + \sin\phi\sin\theta\sin\psi & \sin\phi\cos\theta \\ \sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi & -\sin\phi\cos\psi + \cos\phi\sin\theta\sin\psi & \cos\phi\cos\theta \end{bmatrix}\end{split}\]

the components of the derivative at hand are the following, where \(f_{1\theta} = \frac{\partial \mathbf{f}_1}{\partial\theta}\).

\[\begin{split}f_{1\phi} =&0 \\ f_{1\theta} = &-v_1\sin\theta\cos\psi \\ &+v_2\sin\theta\sin\psi \\ &+v_3\cos\theta \\ f_{1\psi} = &-v_1\cos\theta\sin\psi \\ &- v_2\cos\theta\cos\psi\end{split}\]
\[\begin{split}f_{2\phi} = &+v_1(-\sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi) + \\ &+v_2(-\sin\phi\cos\psi - \cos\phi\sin\theta\sin\psi) + \\ &+v_3(-\cos\phi\cos\theta)\\ f_{2\theta} = &+v_1(\sin\phi\cos\theta\cos\psi) + \\ &+v_2(-\sin\phi\cos\theta\sin\psi) +\\ &+v_3(\sin\phi\sin\theta)\\ f_{2\psi} = &+v_1(\cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi) + \\ &+v_2(-\cos\phi\sin\psi - \sin\phi\sin\theta\cos\psi)\end{split}\]
\[\begin{split}f_{3\phi} = &+v_1(\cos\phi\sin\psi+\sin\phi\sin\theta\cos\psi) + \\ &+v_2(\cos\phi\cos\psi - \sin\phi\sin\theta\sin\psi) + \\ &+v_3(-\sin\phi\cos\theta)\\ f_{3\theta} = &+v_1(-\cos\phi\cos\theta\cos\psi)+\\ &+v_2(\cos\phi\cos\theta\sin\psi) + \\ &+v_3(-\cos\phi\sin\theta)\\ f_{3\psi} = &+v_1(\sin\phi\cos\psi+\cos\phi\sin\theta\sin\psi) + \\ &+v_2(-\sin\phi\sin\psi + \cos\phi\sin\theta\cos\psi)\end{split}\]
param euler:Vector of Euler angles, \(\mathbf{\Theta} = [\phi, \theta, \psi]\), in radians.
type euler:np.ndarray
param v:3 dimensional vector in G frame.
type v:np.ndarray
returns:Resulting 3 by 3 matrix \(\frac{\partial \mathbf{f}}{\partial\mathbf{\Theta}}\).
rtype:np.ndarray
der_TanT_by_xv

Being fv0 a cartesian rotation vector and Tan the corresponding tangential operator (computed through crv2tan(fv)), the function returns the derivative of dot(Tan^T,xv), where xv is a constant vector.

The elements of the resulting derivative matrix D are ordered such that:

\[d(Tan^T*xv) = D*d(fv)\]

where \(d(.)\) is a delta operator.

Note

The derivative expression has been derived symbolically and verified by FDs. A more compact expression may be possible.

der_Tan_by_xv

Being fv0 a cartesian rotation vector and Tan the corresponding tangential operator (computed through crv2tan(fv)), the function returns the derivative of dot(Tan,xv), where xv is a constant vector.

The elements of the resulting derivative matrix D are ordered such that:

\[d(Tan*xv) = D*d(fv)\]

where \(d(.)\) is a delta operator.

Note

The derivative expression has been derived symbolically and verified by FDs. A more compact expression may be possible.

der_Teuler_by_w

Calculates the matrix

\[\frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta}) \mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0}\]

from the linearised euler propagation equations

\[\delta\mathbf{\dot{\Theta}} = \frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta}) \mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0}\delta\mathbf{\Theta} + T^{GA}(\mathbf{\Theta_0}) \delta\mathbf{\omega}^A\]

where \(T^{GA}\) is the nonlinear relation between the euler angle rates and the rotational velocities and is provided by deuler_dt().

The concerned matrix is calculated as follows:

\[\begin{split}\frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta}) \mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0} = \\ \begin{bmatrix} q\cos\phi\tan\theta-r\sin\phi\tan\theta & q\sin\phi\sec^2\theta + r\cos\phi\sec^2\theta & 0 \\ -q\sin\phi - r\cos\phi & 0 & 0 \\ q\frac{\cos\phi}{\cos\theta}-r\frac{\sin\phi}{\cos\theta} & q\sin\phi\tan\theta\sec\theta + r\cos\phi\tan\theta\sec\theta & 0 \end{bmatrix}_{\Theta_0, \omega^A_0}\end{split}\]

Note

This function is defined in a North East Down frame which is not the typically used one in SHARPy.

param euler:Euler angles at the linearisation point \(\mathbf{\Theta}_0 = [\phi,\theta,\psi]\) or roll, pitch and yaw angles, respectively.
type euler:np.ndarray
param w:Rotational velocities at the linearisation point in A frame \(\omega^A_0\).
type w:np.ndarray
returns:Computed \(\frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta})\mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0}\)
rtype:np.ndarray
der_Teuler_by_w_NED

Warning

Based on a NED G frame

Calculates the matrix

\[\frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta}) \mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0}\]

from the linearised euler propagation equations

\[\delta\mathbf{\dot{\Theta}} = \frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta}) \mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0}\delta\mathbf{\Theta} + T^{GA}(\mathbf{\Theta_0}) \delta\mathbf{\omega}^A\]

where \(T^{GA}\) is the nonlinear relation between the euler angle rates and the rotational velocities and is provided by deuler_dt().

The concerned matrix is calculated as follows:

\[\begin{split}\frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta}) \mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0} = \\ \begin{bmatrix} q\cos\phi\tan\theta-r\sin\phi\tan\theta & q\sin\phi\sec^2\theta + r\cos\phi\sec^2\theta & 0 \\ -q\sin\phi - r\cos\phi & 0 & 0 \\ q\frac{\cos\phi}{\cos\theta}-r\frac{\sin\phi}{\cos\theta} & q\sin\phi\tan\theta\sec\theta + r\cos\phi\tan\theta\sec\theta & 0 \end{bmatrix}_{\Theta_0, \omega^A_0}\end{split}\]
param euler:Euler angles at the linearisation point \(\mathbf{\Theta}_0 = [\phi,\theta,\psi]\) or roll, pitch and yaw angles, respectively.
type euler:np.ndarray
param w:Rotational velocities at the linearisation point in A frame \(\omega^A_0\).
type w:np.ndarray
returns:Computed \(\frac{\partial}{\partial\Theta}\left.\left(T^{GA}(\mathbf{\Theta})\mathbf{\omega}^A\right)\right|_{\Theta_0,\omega^A_0}\)
rtype:np.ndarray
der_quat_wrt_crv

Provides change of quaternion, dquat, due to elementary rotation, dcrv, expressed as a 3 components Cartesian rotation vector such that

\[C(quat + dquat) = C(quat0)C(dw)\]

where C are rotation matrices.

Examples

Assume 3 FoRs, G, A and B where:
  • G is the initial FoR

  • quat0 defines te rotation required to obtain A from G, namely: Cga=quat2rotation(quat0)

  • dcrv is an inifinitesimal Cartesian rotation vector, defined in A components, which describes an infinitesimal rotation A -> B, namely:

    ..math :: Cab=crv2rotation(dcrv)

  • The total rotation G -> B is:

    Cga = Cga * Cab

  • As dcrv -> 0, Cga is equal to:

    \[algebra.quat2rotation(quat0 + dquat),\]

    where dquat is the output of this function.

deuler_dt

Rate of change of the Euler angles in time for a given angular velocity in A frame \(\omega^A=[p, q, r]\).

\[\begin{split}\begin{bmatrix}\dot{\phi} \\ \dot{\theta} \\ \dot{\psi}\end{bmatrix} = \begin{bmatrix} 1 & \sin\phi\tan\theta & -\cos\phi\tan\theta \\ 0 & \cos\phi & \sin\phi \\ 0 & -\frac{\sin\phi}{\cos\theta} & \frac{\cos\phi}{\cos\theta} \end{bmatrix} \begin{bmatrix} p \\ q \\ r \end{bmatrix}\end{split}\]
param euler:Euler angles \([\phi, \theta, \psi]\) for roll, pitch and yaw, respectively.
type euler:np.ndarray
returns:Propagation matrix relating the rotational velocities to the euler angles.
rtype:np.ndarray
deuler_dt_NED

Warning

Based on a NED frame

Rate of change of the Euler angles in time for a given angular velocity in A frame \(\omega^A=[p, q, r]\).

\[\begin{split}\begin{bmatrix}\dot{\phi} \\ \dot{\theta} \\ \dot{\psi}\end{bmatrix} = \begin{bmatrix} 1 & \sin\phi\tan\theta & \cos\phi\tan\theta \\ 0 & \cos\phi & -\sin\phi \\ 0 & \frac{\sin\phi}{\cos\theta} & \frac{\cos\phi}{\cos\theta} \end{bmatrix} \begin{bmatrix} p \\ q \\ r \end{bmatrix}\end{split}\]

Note

This function is defined in a North East Down frame which is not the typically used one in SHARPy.

param euler:Euler angles \([\phi, \theta, \psi]\) for roll, pitch and yaw, respectively.
type euler:np.ndarray
returns:Propagation matrix relating the rotational velocities to the euler angles.
rtype:np.ndarray
euler2quat
param euler:Euler angles
returns:Equivalent quaternion.
rtype:np.ndarray
euler2rot

Transforms Euler angles (roll, pitch and yaw \(\Phi, \Theta, \Psi\)) into a 3x3 rotation matrix describing that rotates a vector in yaw pitch, and roll.

The rotations are performed successively, first in yaw, then in pitch and finally in roll.

\[\mathbf{T}_{AG} = \mathbf{\tau}_x(\Phi) \mathbf{\tau}_y(\Theta) \mathbf{\tau}_z(\Psi)\]

where \(\mathbf{\tau}\) represents the rotation about the subscripted axis.

param euler:1x3 array with the Euler angles in the form [roll, pitch, yaw] in radians
type euler:np.array
returns:3x3 transformation matrix describing the rotation by the input Euler angles.
rtype:np.array
get_triad

Generates two unit vectors in body FoR that define the local FoR for a beam element. These vectors are calculated using frame_of_reference_delta :return:

mat2quat

Rotation matrix to quaternion function.

Warning

This function is deprecated and now longer supported. Please use algebra.rotation2quat(rot.T) instead.

param rot:Rotation matrix
returns:equivalent quaternion
rtype:np.array
multiply_matrices

multiply_matrices

Multiply a series of matrices from left to right

param *argv:series of numpy arrays
returns:product of all the given matrices
rtype:sol(numpy array)

Examples

solution = multiply_matrices(A, B, C)

norm3d

Norm of a 3D vector

Notes

Faster than np.linalg.norm

param v:3D vector
type v:np.ndarray
returns:Norm of the vector
rtype:np.ndarray
normsq3d

Square of the norm of a 3D vector

param v:3D vector
type v:np.ndarray
returns:Square of the norm of the vector
rtype:np.ndarray
quadskew

Generates the matrix needed to obtain the quaternion in the following time step through integration of the FoR angular velocity.

param vector:FoR angular velocity
type vector:np.array

Notes

The angular velocity is assumed to be constant in the time interval Equivalent to lib_xbeam function Quaternion ODE to compute orientation of body-fixed frame a See Shearer and Cesnik (2007) for definition

returns:matrix
rtype:np.array
quat2euler

Quaternion to Euler angles transformation.

Transforms a normalised quaternion \(\chi\longrightarrow[\phi, \theta, \psi]\) to roll, pitch and yaw angles respectively.

The transformation is valid away from the singularity present at:

\[\Delta = \frac{1}{2}\]

where \(\Delta = q_0 q_2 - q_1 q_3\).

The transformation is carried out as follows:

\[\begin{split}\psi &= \arctan{\left(2\frac{q_0q_3+q_1q_2}{1-2(q_2^2+q_3^2)}\right)} \\ \theta &= \arcsin(2\Delta) \\ \phi &= \arctan\left(2\frac{q_0q_1 + q_2q_3}{1-2(q_1^2+q_2^2)}\right)\end{split}\]
param quat:Normalised quaternion.
type quat:np.ndarray
returns:Array containing the Euler angles \([\phi, \theta, \psi]\) for roll, pitch and yaw, respectively.
rtype:np.ndarray

References

Blanco, J.L. - A tutorial on SE(3) transformation parameterizations and on-manifold optimization. Technical Report 012010. ETS Ingenieria Informatica. Universidad de Malaga. 2013.

quat2rotation

Calculate rotation matrix based on quaternions.

If B is a FoR obtained rotating a FoR A by an angle \(\phi\) about an axis \(\mathbf{n}\) (recall \(\mathbf{n}\) will be invariant during the rotation), and \(\mathbf{q}\) is the related quaternion, \(\mathbf{q}(\phi,\mathbf{n})\), the function will return the matrix \(C^{AB}\) such that:

  • \(C^{AB}\) rotates FoR A onto FoR B.
  • \(C^{AB}\) transforms the coordinates of a vector defined in B component to A components i.e. \(\mathbf{v}^A = C^{AB}(\mathbf{q})\mathbf{v}^B\).
\[\begin{split}C^{AB}(\mathbf{q}) = \begin{pmatrix} q_0^2 + q_1^2 - q_2^2 -q_3^2 & 2(q_1 q_2 - q_0 q_3) & 2(q_1 q_3 + q_0 q_2) \\ 2(q_1 q_2 + q_0 q_3) & q_0^2 - q_1^2 + q_2^2 - q_3^2 & 2(q_2 q_3 - q_0 q_1) \\ 2(q_1 q_3 - q_0 q_2) & 2(q_2 q_3 + q_0 q_1) & q_0^2 -q_1^2 -q_2^2 +q_3^2 \end{pmatrix}\end{split}\]

Notes

The inverse rotation is defined as the transpose of the matrix \(C^{BA} = C^{{AB}^T}\).

In typical SHARPy applications, the quaternion relation between the A and G frames is expressed as \(C^{GA}(\mathbf{q})\), and in the context of this function it corresponds to:

>>> C_ga = quat2rotation(q1)
>>> C_ag = quat2rotation.T(q1)
param q:Quaternion \(\mathbf{q}(\phi, \mathbf{n})\).
type q:np.ndarray
returns:\(C^{AB}\) rotation matrix from FoR B to FoR A.
rtype:np.ndarray

References

Stevens, L. Aircraft Control and Simulation. 1985. pg 41

quat_bound

Given a quaternion, \(\vec{\chi}\), associated to a rotation of angle \(\psi\) about an axis \(\mathbf{\hat{n}}\), the function “bounds” the quaternion, i.e. sets the rotation axis \(\mathbf{\hat{n}}\) such that \(\psi\) in \([-\pi,\pi]\).

Notes

As quaternions are defined as:

\[\vec{\chi}= \left[\cos\left(\frac{\psi}{2}\right),\, \sin\left(\frac{\psi}{2}\right)\mathbf{\hat{n}}\right]\]

this is equivalent to enforcing \(\chi_0\ge0\).

param quat:quaternion to bound
type quat:np.array
returns:bounded quaternion
rtype:np.array
rotation2crv

Given a rotation matrix \(C^{AB}\) rotating the frame A onto B, the function returns the minimal size Cartesian rotation vector, \(\vec{\psi}\) representing this rotation.

param Cab:rotation matrix \(C^{AB}\)
type Cab:np.array
returns:equivalent Cartesian rotation vector, \(\vec{\psi}\).
rtype:np.array

Notes

this is the inverse of algebra.crv2rotation for Cartesian rotation vectors associated to rotations in the range \([-\pi,\,\pi]\), i.e.:

fv == algebra.rotation2crv(algebra.crv2rotation(fv))

for each Cartesian rotation vector of the form \(\vec{\psi} = \psi\,\mathbf{\hat{n}}\) represented as fv=a*nv such that nv is a unit vector and the scalar a is in the range \([-\pi,\,\pi]\).

rotation2quat

Given a rotation matrix \(C^{AB}\) rotating the frame A onto B, the function returns the minimal “positive angle” quaternion representing this rotation, where the quaternion, \(\vec{\chi}\) is defined as:

\[\vec{\chi}= \left[\cos\left(\frac{\psi}{2}\right),\, \sin\left(\frac{\psi}{2}\right)\mathbf{\hat{n}}\right]\]
param Cab:rotation matrix \(C^{AB}\) from frame A to B
type Cab:np.array
returns:equivalent quaternion \(\vec{\chi}\)
rtype:np.array

Notes

This is the inverse of algebra.quat2rotation for Cartesian rotation vectors associated to rotations in the range \([-\pi,\pi]\), i.e.:

fv == algebra.rotation2crv(algebra.crv2rotation(fv))

where fv represents the Cartesian Rotation Vector, \(\vec{\psi}\) defined as:

\[\vec{\psi} = \psi\,\mathbf{\hat{n}}\]

such that \(\mathbf{\hat{n}}\) is a unit vector and the scalar \(\psi\) is in the range \([-\pi,\,\pi]\).

rotation3d_x

Rotation matrix about the x axis by the input angle \(\Phi\)

\[\begin{split}\mathbf{\tau}_x = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos(\Phi) & -\sin(\Phi) \\ 0 & \sin(\Phi) & \cos(\Phi) \end{bmatrix}\end{split}\]
param angle:angle of rotation in radians about the x axis
type angle:float
returns:3x3 rotation matrix about the x axis
rtype:np.array
rotation3d_y

Rotation matrix about the y axis by the input angle \(\Theta\)

\[\begin{split}\mathbf{\tau}_y = \begin{bmatrix} \cos(\Theta) & 0 & -\sin(\Theta) \\ 0 & 1 & 0 \\ \sin(\Theta) & 0 & \cos(\Theta) \end{bmatrix}\end{split}\]
param angle:angle of rotation in radians about the y axis
type angle:float
returns:3x3 rotation matrix about the y axis
rtype:np.array
rotation3d_z

Rotation matrix about the z axis by the input angle \(\Psi\)

\[\begin{split}\mathbf{\tau}_z = \begin{bmatrix} \cos(\Psi) & -\sin(\Psi) & 0 \\ \sin(\Psi) & \cos(\Psi) & 0 \\ 0 & 0 & 1 \end{bmatrix}\end{split}\]
param angle:angle of rotation in radians about the z axis
type angle:float
returns:3x3 rotation matrix about the z axis
rtype:np.array
skew

Returns a skew symmetric matrix such that

\[\boldsymbol{v} \times \boldsymbol{u} = \tilde{\boldsymbol{v}}{\boldsymbol{u}\]

where

\[\begin{split}\tilde{\boldsymbol{v}} = \begin{bmatrix} 0 & -v_z & v_y \\ v_z & 0 & -v_x \\ -v_y & v_x & 0 \end{bmatrix}.\end{split}\]
param vector:3-dimensional vector
type vector:np.ndarray
returns:Skew-symmetric matrix.
rtype:np.array
tangent_vector

Tangent vector calculation for 2+ noded elements.

Calculates the tangent vector interpolating every dimension separately. It uses a (n_nodes - 1) degree polynomial, and the differentiation is analytical.

Calculation method:

  1. A n_nodes-1 polynomial is fitted through the nodes per dimension.
  2. Those polynomials are analytically differentiated with respect to the node index
  3. The tangent vector is given by:
\[\vec{t} = \frac{s_x'\vec{i} + s_y'\vec{j} + s_z'\vec{k}}{\left| s_x'\vec{i} + s_y'\vec{j} + s_z'\vec{k}\right|}\]

where \('\) notes the differentiation with respect to the index number

param in_coord:array of coordinates of the nodes. Dimensions = [n_nodes, ndim]
type in_coord:np.ndarray

Notes

Dimensions are treated independent from each other, interpolating polynomials are computed individually.

triad2rotation

If the input triad is the “b” coord system given in “a” frame, (the vectors of the triad are xb, yb, zb), this function returns Rab, ie the rotation matrix required to rotate the FoR A onto B. :param xb: :param yb: :param zb: :return: rotation matrix Rab

unit_vector

Transforms the input vector into a unit vector

\[\mathbf{\hat{v}} = \frac{\mathbf{v}}{\|\mathbf{v}\|}\]
param vector:vector to normalise
type vector:np.array
returns:unit vector
rtype:np.array
Analytical Functions

Analytical solutions for 2D aerofoil based on thin plates theory

Author: Salvatore Maraniello

Date: 23 May 2017

References:

  1. Simpson, R.J.S., Palacios, R. & Murua, J., 2013. Induced-Drag Calculations in the Unsteady Vortex Lattice Method. AIAA Journal, 51(7), pp.1775–1779.
  2. Gulcat, U., 2009. Propulsive Force of a Flexible Flapping Thin Airfoil. Journal of Aircraft, 46(2), pp.465–473.
flat_plate_analytical

Computes the analytical frequency response of a plat plate for the input output sequences in input_seq and output_seq over the frequency points kv, if available.

The output complex values array Yan has shape (Nout, Nin, Nk); if an analytical solution is not available, the response is assumed to be zero.

If plunge_deriv is True, the plunge response is expressed in terms of first derivative dh.

param kv:

Frequency range of length Nk.

type kv:

np.array

param x_ea_perc:
 

Elastic axis location along the chord as chord length percentage.

type x_ea_perc:

float

param x_fh_perc:
 

Flap hinge location along the chord as chord length percentage.

type x_fh_perc:

float

param input_seq:
 

List of Nin number of inputs. Supported inputs include:

  • gust_sears: Response to a continuous sinusoidal gust.
  • pitch: Response to an oscillatory pitching motion.
  • plunge: Response to an oscillatory plunging motion.
type input_seq:

list(str)

param output_seq:
 

List of Nout number of outputs. Supported outputs include:

  • Fy: Vertical force.
  • Mz: Pitching moment.
type output_seq:
 

list(str)

param output_scal:
 

Array of factors by which to divide the desired outputs. Dimensions of Nout.

type output_scal:
 

np.array

param plunge_deriv:
 

If True expresses the plunge response in terms of the first derivative, i.e. the

type plunge_deriv:
 

bool

:param rate of change of plunge \(d\dot{h}\).:

returns:A (Nout, Nin, Nk) array containing the scaled frequency response for the inputs and outputs specified.
rtype:np.array

See also

The lift coefficient due to pitch and plunging motions is calculated using sharpy.utils.analytical.theo_CL_freq_resp(). In turn, the pitching moment is found using sharpy.utils.analytical.theo_CM_freq_resp().

The response to the continuous sinusoidal gust is calculated using sharpy.utils.analytical.sears_CL_freq_resp().

garrick_drag_pitch

Returns Garrick solution for drag coefficient at a specific time. Ref.[1], eq.(9), (10) and (11)

The aerofoil pitching motion is assumed to be:

\[a(t)=A\sin(\omegat)=A\sin(ks)\]

The \(C_d\) is such that:

  • \(C_d>0\): drag
  • \(C_d<0\): suction
garrick_drag_plunge

Returns Garrick solution for drag coefficient at a specific time. Ref.[1], eq.(8) (see also eq.(1) and (2)) or Ref[2], eq.(2)

The aerofoil vertical motion is assumed to be:

\[h(t)=-H\cos(wt)\]

The \(C_d\) is such that:

  • \(C_d>0\): drag
  • \(C_d<0\): suction
nc_derivs

Provides non-circulatory aerodynamic lift and moment coefficients derivatives Ref. Palacios and Cesnik, Chap 3.

param x_ea_perc:
 position of axis of rotation in percentage of chord (measured from LE)
param x_fc_perc:
 position of flap axis of rotation in percentage of chord (measured from LE)
qs_derivs

Provides quasi-steady aerodynamic lift and moment coefficients derivatives Ref. Palacios and Cesnik, Chap 3.

param x_ea_perc:
 position of axis of rotation in percentage of chord (measured from LE)
param x_fc_perc:
 position of flap axis of rotation in percentage of chord (measured from LE)
sears_CL_freq_resp

Frequency response of lift coefficient according Sear’s solution. Ref. Palacios and Cesnik, Chap.3

sears_fun

Produces Sears function

sears_lift_sin_gust

Returns the lift coefficient for a sinusoidal gust (see set_gust.sin) as the imaginary part of the CL complex function defined below. The input gust must be the imaginary part of

\[wgust = w0*\exp(1.0j*C*(Ux*S.time[tt] - xcoord) )\]

with:

\[C=2\pi/L\]

and xcoord=0 at the aerofoil half-chord.

theo_CL_freq_resp

Frequency response of lift coefficient according Theodorsen’s theory.

The output is a 3 elements array containing the CL frequency response w.r.t. to pitch, plunge and flap motion, respectively. Sign conventions are as follows:

  • plunge: positive when moving upward
  • x_ea_perc: position of axis of rotation in percentage of chord (measured from LE)
  • x_fc_perc: position of flap axis of rotation in percentage of chord (measured from LE)

Warning

this function uses different input/output w.r.t. theo_lift

theo_CM_freq_resp

Frequency response of moment coefficient according Theodorsen’s theory.

The output is a 3 elements array containing the CL frequency response w.r.t. to pitch, plunge and flap motion, respectively.

theo_fun

Returns the value of Theodorsen’s function at a reduced frequency \(k\).

\[\mathcal{C}(jk) = \frac{H_1^{(2)}(k)}{H_1^{(2)}(k) + jH_0^{(2)}(k)}\]

where \(H_0^{(2)}(k)\) and \(H_1^{(2)}(k)\) are Hankel functions of the second kind.

param k:Reduced frequency/frequencies at which to evaluate the function.
type k:np.array
returns:Value of Theodorsen’s function evaluated at the desired reduced frequencies.
rtype:np.array
theo_lift

Theodorsen’s solution for lift of aerofoil undergoing sinusoidal motion.

Time histories are built assuming:

  • a(t)=+/- A cos(w t) ??? not verified
  • \(h(t)=-H\cos(w t)\)
param w:frequency (rad/sec) of oscillation
param A:amplitude of angle of attack change
param H:amplitude of plunge motion
param c:aerofoil chord
param rhoinf:flow density
param uinf:flow speed
param x12:distance of elastic axis from mid-point of aerofoil (positive if the elastic axis is ahead)
wagner_imp_start

Lift coefficient resulting from impulsive start solution.

Controller Utilities
PID
class sharpy.utils.control_utils.PID(gain_p, gain_i, gain_d, dt)[source]

Class implementing a classic PID controller

Instance attributes: :param gain_p: Proportional gain. :param gain_i: Integral gain. :param gain_d: Derivative gain. :param dt: Simulation time step.

The class should be used as:

pid = PID(100, 10, 0.1, 0.1) pid.set_point(target_point) control = pid(current_point)
Data Management Structures

Classes for the Aerotimestep and Structuraltimestep, amongst others

LinearTimeStepInfo
class sharpy.utils.datastructures.LinearTimeStepInfo[source]

Linear timestep info containing the state, input and output variables for a given timestep

Documentation Generator

Functions to automatically document the code.

Comments and complaints: N. Goizueta

check_folder_in_ignore

Checks whether a folder is in the ignore_list.

param folder:Absolute path to folder
type folder:str
param ignore_list:
 Ignore list
type ignore_list:
 list
returns:Bool whether file/folder is in ignore list.
rtype:bool
generate_documentation

Main routine that generates the documentation in ./docs/source/includes

output_documentation_module_page

Generates the documentation for a package with a single page per module in the desired folder Returns:

write_file

Writes the contents of a python file with one module per page.

Warning

If the function to be written does not have a docstring no output will be produced and a warning will be given.

param file:Absolute path to file
type file:str
write_folder

Creates the documentation for the contents in a folder.

It checks that the file folder is not in the ignore_list. If there is a subfolder in the folder, this gets opened, written and an index file is created.

param folder:

Absolute path to folder

type folder:

str

param ignore_list:
 

List with filenames and folders to ignore and skip

type ignore_list:
 

list

returns:
Tuple containing the title and body of the docstring found for it to be added to the index of the

current folder.

rtype:

tuple

SHARPy Exception Classes
DocumentationError
class sharpy.utils.exceptions.DocumentationError[source]

Error in documentation

NotConvergedSolver
class sharpy.utils.exceptions.NotConvergedSolver[source]

To be raised when the solver does not converge. Before this, SHARPy would add a pdb trace, but this causes problems when using SHARPy as a black box.

NotValidSetting
class sharpy.utils.exceptions.NotValidSetting(setting, variable, options, value=None, message='')[source]

Raised when a user gives a setting an invalid value

Generate cases

Generate cases

This library provides functions and classes to help in the definition of SHARPy cases

Examples:

tests in: tests/utils/generate_cases examples: test/coupled/multibody/fix_node_velocity_wrtG/test_fix_node_velocity_wrtG

test/coupled/multibody/fix_node_velocity_wrtA/test_fix_node_velocity_wrtA test/coupled/multibody/double_pendulum/test_double_pendulum_geradin test/coupled/prescribed/WindTurbine/test_rotor

Notes:

To use this library: import sharpy.utils.generate_cases as generate_cases
AerodynamicInformation
class sharpy.utils.generate_cases.AerodynamicInformation[source]

Aerodynamic information needed to build a case

Note

It should be defined after the StructuralInformation of the case

assembly_aerodynamics(*args)[source]

This function concatenates aerodynamic properties to be writen in the same h5 File

Parameters:*args – list of AerodynamicInformation() to be meged into ‘self’
change_airfoils_discretezation(airfoils, new_num_nodes)[source]

Changes the discretization of the matrix of airfoil coordinates

Parameters:
  • airfoils (np.array) – Matrix with the x-y coordinates of all the airfoils to be modified
  • new_num_nodes (int) – Number of points that the output coordinates will have
Returns:

Matrix with the x-y coordinates of all the airfoils with the new discretization

Return type:

new_airfoils (np.array)

check_AerodynamicInformation(StructuralInformation)[source]

Check some properties of the AerodynamicInformation()

Notes

These conditions have to be to correctly define a case but they are not the only ones

copy()[source]

Returns a copy of the object

Returns:new object with the same properties
Return type:copied(AerodynamicInformation)
create_aerodynamics_from_vec(StructuralInformation, vec_aero_node, vec_chord, vec_twist, vec_sweep, vec_surface_m, vec_surface_distribution, vec_m_distribution, vec_elastic_axis, vec_airfoil_distribution, airfoils, user_defined_m_distribution=None)[source]

Defines the whole case from the appropiated variables in vector form (associated to nodes)

Parameters:
  • StructuralInformation (StructuralInformation) – Structural infromation of the case
  • vec_aero_node (np.array) – defines if a node has aerodynamic properties or not
  • vec_chord (np.array) – chord of the nodes
  • vec_twist (np.array) – twist of the nodes
  • vec_sweep (np.array) – sweep of the nodes
  • vec_surface_m (np.array) – Number of panels in the chord direction
  • vec_surface_distribution (np.array) – Surface at which each element belongs
  • vec_m_distribution (np.array) – distribution of the panels along the chord
  • vec_elastic_axis (np.array) – position of the elastic axis in the chord
  • vec_airfoil_distribution (np.array) – airfoil at each element node
  • airfoils (np.array) – coordinates of the camber lines of the airfoils
create_one_uniform_aerodynamics(StructuralInformation, chord, twist, sweep, num_chord_panels, m_distribution, elastic_axis, num_points_camber, airfoil)[source]

Defines the whole case from the appropiated variables constant at every point

Parameters:
  • StructuralInformation (StructuralInformation) – Structural infromation of the case
  • chord (float) – chord
  • twist (float) – twist
  • sweep (float) – sweep
  • num_chord_panels (int) – Number of panels in the chord direction
  • m_distribution (str) – distribution of the panels along the chord
  • elastic_axis (float) – position of the elastic axis in the chord
  • num_points_camber (int) – Number of points to define the camber line
  • airfoils (np.array) – coordinates of the camber lines of the airfoils
generate_aero_file(route, case_name, StructuralInformation)[source]

Writes the h5 file with the aerodynamic information

Parameters:
  • route (string) – path of the case
  • case_name (string) – name of the case
generate_full_aerodynamics(aero_node, chord, twist, sweep, surface_m, surface_distribution, m_distribution, elastic_axis, airfoil_distribution, airfoils)[source]

Defines the whole case from the appropiated variables

Parameters:
  • aero_node (np.array) – defines if a node has aerodynamic properties or not
  • chord (np.array) – chord of the elements
  • twist (np.array) – twist of the elements
  • sweep (np.array) – sweep of the elements
  • surface_m (np.array) – Number of panels in the chord direction
  • surface_distribution (np.array) – Surface at which each element belongs
  • m_distribution (str) – distribution of the panels along the chord
  • elastic_axis (np.array) – position of the elastic axis in the chord
  • airfoil_distribution (np.array) – airfoil at each element node
  • airfoils (np.array) – coordinates of the camber lines of the airfoils
interpolate_airfoils_camber(pure_airfoils_camber, r_pure_airfoils, r, n_points_camber)[source]

Create the camber of the airfoil at each node position from the camber of the pure airfoils present in the blade

Parameters:
  • pure_airfoils_camber (np.array) – xy coordinates of the camber lines of the pure airfoils
  • r_pure_airfoils (np.array) – radial position of the pure airfoils
  • r (np.array) – radial positions to compute the camber lines through linear interpolation
Returns:

camber lines at the new radial positions

Return type:

airfoils_camber (np.array)

interpolate_airfoils_camber_thickness(pure_airfoils_camber, thickness_pure_airfoils, blade_thickness, n_points_camber)[source]

Create the camber of the airfoil at each node position from the camber of the pure airfoils present in the blade based on the thickness

Parameters:
  • pure_airfoils_camber (np.array) – xy coordinates of the camber lines of the pure airfoils
  • thicknesss_pure_airfoils (np.array) – thickness of the pure airfoils
  • blade_thickness (np.array) – thickness of the blade positions
Returns:

camber lines at the new radial positions

Return type:

airfoils_camber (np.array)

set_to_zero(num_node_elem, num_node, num_elem, num_airfoils=1, num_surfaces=0, num_points_camber=100)[source]

Sets to zero all the variables

Parameters:
  • num_node_elem (int) – number of nodes per element
  • num_node (int) – number of nodes
  • num_elem (int) – number of elements
  • num_airfoils (int) – number of different airfoils
  • num_surfaces (int) – number of aerodynamic surfaces
  • num_points_camber (int) – number of points to define the camber line of the airfoil
AeroelasticInformation
class sharpy.utils.generate_cases.AeroelasticInformation[source]

Structural and aerodynamic information needed to build a case

assembly(*args)[source]

This function concatenates structures and aerodynamic properties to be writen in the same h5 File

Parameters:*args – list of AeroelasticInformation() to be meged into ‘self’

Notes:

copy()[source]

Returns a copy of the object

Returns:new object with the same properties
Return type:copied(AeroelasticInformation)
generate(StructuralInformation, AerodynamicInformation)[source]

Generates an object from the structural and the aerodynamic information

Parameters:
generate_h5_files(route, case_name)[source]

write_h5_files

Writes the structural and aerodynamic h5 files

remove_duplicated_points(tol)[source]

Removes the points that are closer than ‘tol’ and modifies the aeroelastic information accordingly

Parameters:tol (float) – tolerance. Maximum distance between nodes to be merged

Notes

This function will not work if an element or an aerdoynamic surface is completely eliminated This function only checks geometrical proximity, not aeroelastic properties as a merging criteria

SimulationInformation
class sharpy.utils.generate_cases.SimulationInformation[source]

Simulation information needed to build a case

define_num_steps(num_steps)[source]

Set the number of steps in the simulation for all the solvers

Parameters:num_steps (int) – number of steps
define_uinf(unit_vector, norm)[source]

Set the inflow velocity in the simulation for all the solvers

Parameters:
  • unit_vector (np.array) – direction of the inflow velocity
  • norm (float) – Norm of the inflow velocity
generate_dyn_file(num_steps)[source]

Generates the dynamic file

Parameters:
  • route (string) – path of the case
  • case_name (string) – name of the case
  • num_steps (int) – number of steps
generate_solver_file()[source]

Generates the solver file

Parameters:
  • route (string) – path of the case
  • case_name (string) – name of the case
set_default_values()[source]

Set the default values for all the solvers

set_variable_all_dicts(variable, value)[source]

Defines the value of a variable in all the available solvers

Parameters:
  • variable (str) – variable name
  • ( ) (value) – value
StructuralInformation
class sharpy.utils.generate_cases.StructuralInformation[source]

Structural information needed to build a case

assembly_structures(*args)[source]

This function concatenates structures to be writen in the same h5 File

Parameters:*args – list of StructuralInformation() to be meged into ‘self’

Notes

The structures does NOT merge any node (even if nodes are defined at the same coordinates)

check_StructuralInformation()[source]

Check some properties of the StructuralInformation()

Notes

These conditions have to be to correctly define a case but they are not the only ones

compute_basic_num_elem()[source]

It computes the number of elements when no nodes are shared between beams

compute_basic_num_node()[source]

It computes the number of nodes when no nodes are shared between beams

copy()[source]

Returns a copy of the object

Returns:new object with the same properties
Return type:copied(StructuralInformation)
create_frame_of_reference_delta(y_BFoR='y_AFoR')[source]

Define the coordinates of the yB axis in the AFoR

Parameters:y_BFoR (string) – Direction of the yB axis
create_mass_db_from_vector(vec_mass_per_unit_length, vec_mass_iner_x, vec_mass_iner_y, vec_mass_iner_z, vec_pos_cg_B, vec_mass_iner_yz=None)[source]

Create the mass matrices from the vectors of properties

Parameters:
  • vec_mass_per_unit_length (np.array) – masses per unit length
  • vec_mass_iner_x (np.array) – inertias around the x axis
  • vec_mass_iner_y (np.array) – inertias around the y axis
  • vec_mass_iner_z (np.array) – inertias around the z axis
  • vec_pos_cg_B (np.array) – position of the masses
  • vec_mass_iner_yz (np.array) – inertias around the yz axis
create_simple_connectivities()[source]

Create the matrix of connectivities for one single beam with the nodes ordered in increasing xB direction

create_stiff_db_from_vector(vec_EA, vec_GAy, vec_GAz, vec_GJ, vec_EIy, vec_EIz, vec_EIyz=None)[source]

Create the stiffness matrices from the vectors of properties

Parameters:
  • vec_EA (np.array) – Axial stiffness
  • vec_GAy (np.array) – Shear stiffness in the y direction
  • vec_GAz (np.array) – Shear stiffness in the z direction
  • vec_GJ (np.array) – Torsional stiffness
  • vec_EIy (np.array) – Bending stiffness in the y direction
  • vec_EIz (np.array) – Bending stiffness in the z direction
  • vec_EIyz (np.array) – Bending stiffness in the yz direction
generate_fem_file(route, case_name)[source]

Writes the h5 file with the structural information

Parameters:
  • route (string) – path of the case
  • case_name (string) – name of the case
generate_full_structure(num_node_elem, num_node, num_elem, coordinates, connectivities, elem_stiffness, stiffness_db, elem_mass, mass_db, frame_of_reference_delta, structural_twist, boundary_conditions, beam_number, app_forces, lumped_mass_nodes=None, lumped_mass=None, lumped_mass_inertia=None, lumped_mass_position=None)[source]

Defines the whole case from the appropiated variables

Parameters:
  • num_node_elem (int) – number of nodes per element
  • num_node (int) – number of nodes
  • num_elem (int) – number of elements
  • coordinates (np.array) – nodes coordinates
  • connectivities (np.array) – element connectivities
  • elem_stiffness (np.array) – element stiffness index
  • stiffness_db (np.array) – Stiffness matrices
  • elem_mass (np.array) – element mass index
  • mass_db (np.array) – Mass matrices
  • frame_of_reference_delta (np.array) – element direction of the y axis in the BFoR wrt the AFoR
  • structural_twist (np.array) – element based twist
  • boundary_conditions (np.array) – node boundary condition
  • beam_number (np.array) – node beam number
  • app_forces (np.array) – steady applied follower forces at the nodes
  • lumped_mass_nodes (np.array) – nodes with lumped masses
  • lumped_mass (np.array) – value of the lumped masses
  • lumped_mass_inertia (np.array) – inertia of the lumped masses
  • lumped_mass_position (np.array) – position of the lumped masses
generate_uniform_beam(node_pos, mass_per_unit_length, mass_iner_x, mass_iner_y, mass_iner_z, pos_cg_B, EA, GAy, GAz, GJ, EIy, EIz, num_node_elem=3, y_BFoR='y_AFoR', num_lumped_mass=0)[source]

Generates the input data for SHARPy of a uniform beam

Parameters:
  • node_pos (np.array) – coordinates of the nodes
  • mass_per_unit_length (float) – mass per unit length
  • mass_iner_x (float) – Inertia of the mass in the x direction
  • mass_iner_y (float) – Inertia of the mass in the y direction
  • mass_iner_z (float) – Inertia of the mass in the z direction
  • pos_cg_B (np.array) – position of the masses
  • EA (np.array) – Axial stiffness
  • GAy (np.array) – Shear stiffness in the y direction
  • GAz (np.array) – Shear stiffness in the z direction
  • GJ (np.array) – Torsional stiffness
  • EIy (np.array) – Bending stiffness in the y direction
  • EIz (np.array) – Bending stiffness in the z direction
  • num_node_elem (int) – number of nodes per element
  • y_BFoR (str) – orientation of the yB axis
  • num_lumped_mass (int) – number of lumped masses
generate_uniform_sym_beam(node_pos, mass_per_unit_length, mass_iner, EA, GA, GJ, EI, num_node_elem=3, y_BFoR='y_AFoR', num_lumped_mass=0)[source]

Generates the input data for SHARPy of a uniform symmetric beam

Parameters:
  • node_pos (np.array) – coordinates of the nodes
  • mass_per_unit_length (float) – mass per unit length
  • mass_iner (float) – Inertia of the mass
  • EA (float) – Axial stiffness
  • GA (float) – Shear stiffness
  • GJ (float) – Torsional stiffness
  • EI (float) – Bending stiffness
  • num_node_elem (int) – number of nodes per element
  • y_BFoR (str) – orientation of the yB axis
  • num_lumped_mass (int) – number of lumped masses
rotate_around_origin(axis, angle)[source]

Rotates a structure

Parameters:
  • axis (np.array) – axis of rotation
  • angle (float) – angle of rotation in radians
set_to_zero(num_node_elem, num_node, num_elem, num_mass_db=None, num_stiffness_db=None, num_lumped_mass=0)[source]

Sets to zero all the variables

Parameters:
  • num_node_elem (int) – number of nodes per element
  • num_node (int) – number of nodes
  • num_elem (int) – number of elements
  • num_mass_db (int) – number of different mass matrices in the case
  • num_stiffness_db (int) – number of different stiffness matrices in the case
  • num_lumped_mass (int) – number of lumped masses in the case
clean_test_files

clean_test_files

Removes the previous h5 files

param route:path of the case
type route:string
param case_name:
 name of the case
type case_name:string
from_node_array_to_elem_matrix

from_node_array_to_elem_matrix

Same as the previous function but with an array as input

from_node_list_to_elem_matrix

from_node_list_to_elem_matrix

Convert list of properties associated to nodes to matrix of properties associated to elements based on the connectivities

The ‘ith’ value of the ‘node_list’ array stores the property of the ‘ith’ node. The ‘jth’ ‘kth’ value of the ‘elem_matrix’ array stores the property of the ‘kth’ node within the ‘jth’ element

param node_list:
 Properties of the nodes
type node_list:np.array
param connectivities:
 Connectivities between the nodes to form elements
type connectivities:
 np.array
returns:Properties of the elements
rtype:elem_matrix (np.array)
get_airfoil_camber

get_airfoil_camber

Define the camber of an airfoil based on its coordinates

param x:x coordinates of the airfoil surface
type x:np.array
param y:y coordinates of the airfoil surface
type y:np.array
param n_points_camber:
 number of points to define the camber line
type n_points_camber:
 int
returns:x coordinates of the camber line camber_y (np.array): y coordinates of the camber line
rtype:camber_x (np.array)

Notes

The x and y vectors are expected in XFOIL format: TE - suction side - LE - pressure side - TE

get_aoacl0_from_camber

This section provies the angle of attach of zero lift for a thin airfoil which camber line is defined by ‘x’ and ‘y’ coordinates

Check Theory of wing sections. Abbott. pg 69

get_factor_geometric_progression

This function provides the factor in a geometric series which first element is ‘a0’, has ‘n’ points and the sum of the spacings is ‘Sn_target’ approximately.

\[\sum_{k=1}^n a_0 r^{k-1} = \frac{a_0 (1 - r^n)}{1 - r}\]
get_mu0_from_camber

This funrcion provides the constant \(\mu_0\) for a thin airfoil which camber line is defined by ‘x’ and ‘y’ coordinates

Check Theory of wing sections. Abbott. pg 69

read_column_sheet_type01

read_column_sheet_type01

This function reads a column from an excel file with the following format:

  • First row: column_name
  • Second row: units (not read, not checked)
  • Third row: type of data (see below)
param excel_file_name:
 File name
type excel_file_name:
 string
param excel_sheet:
 Name of the sheet inside the excel file
type excel_sheet:
 string
param column_name:
 Name of the column
type column_name:
 string
returns:Data in the excel file according to the type of data defined in the third row
rtype:var
Generator Interface
output_documentation

Creates the .rst files for the generators that have a docstring such that they can be parsed to Sphinx

param route:Path to folder where generator files are to be created.
type route:str
Airfoil Geometry Utils
generate_naca_camber

Defines the x and y coordinates of a 4-digit NACA profile’s camber line (i.e no thickness).

The NACA 4-series airfoils follow the nomenclature: NACA MPTT where:
  • M indicates the maximum camber \(M = 100m\)
  • P indicates the position of the maximum camber \(P=10p\)
  • TT indicates the thickness to chord ratio \(TT=(t/c)*100\)
param M:maximum camber times 100 (i.e. the first of the 4 digits)
type M:float
param P:position of the maximum camber times 10 (i.e. the second of the 4 digits)
type P:float
returns:x and y coordinates of the chosen airfoil
rtype:(x_vec,y_vec)

Example

The NACA2400 airfoil would have 2% camber with the maximum at 40% of the chord and 0 thickness. To plot the camber line one would use this function as:

x_vec, y_vec = generate_naca_camber(M = 2, P = 4)
interpolate_naca_camber

Interpolate aerofoil camber at non-dimensional coordinate eta in (0,1), where (M00,P00) and (M01,P01) define the camber properties at eta=0 and eta=1 respectively.

Notes

For two surfaces, eta can be in (-1,1). In this case, the root is eta=0 and the tips are at eta=+-1.

H5 File Management Utilities

Set of utilities for opening/reading files

add_array_to_grp

Add numpy array (data) as dataset ‘name’ to the group grp. If compress is True, 64-bit float arrays are converted to 32-bit

add_as_grp

Given a class, dictionary, list or tuples instance ‘obj’, the routine adds it as a sub-group of name grpname to the parent group grpParent. An attribute _read_as, specifying the type of obj, is added to the group so as to allow reading correctly the h5 file.

Usage and Remarks:
  • if obj contains dictionaries, listes or tuples, these are automatically saved
  • if list only contains scalars or arrays of the same dimension, this will be saved as a numpy array
  • if obj contains classes, only those that are instances of the classes specified in ClassesToSave will be saved
  • If grpParent already contains a sub-group with name grpname, this will not be overwritten. However, pre-existing attributes of the sub-group will be overwritten if obj contains attrributes with the same names.
  • attributes belonging to SkipAttr will not be saved - This functionality needs improving
  • if compress_float is True, numpy arrays will be saved in single precisions.
check_file_exists

Checks if the file exists and throws a FileNotFoundError exception that includes the route to the non-existing file.

param file_name:
 path to the HDF5 file
type file_name:str
returns:if the file does not exist, an error is raised with path to the non-existent file
rtype:FileNotFoundError
read_group

Read an hdf5 group

readh5

Read the HDF5 file ‘filename’ into a class. Groups within the hdf5 file are by default loaded as sub classes, unless they include a _read_as attribute (see sharpy.postproc.savedata). In this case, group can be loaded as classes, dictionaries, lists or tuples.

filename: string to file location

GroupName = string or list of strings. Default is None: if given, allows reading a specific group h5 file.

Warning

Groups that need to be read as lists and tuples are assumed to conform to the format used in sharpy.postproc.savedata

save_list_as_array

Works for both lists and tuples. Returns True if the saving was successful.

saveh5

Creates h5filename and saves all the classes specified in class_inst

Args
savedir: target directory h5filename: file name class_inst: a number of classes to save permission=[‘a’,’w’]: append or overwrite, according to h5py.File ClassesToSave: if the classes in class_inst contain sub-classes, these will be saved only if instances of the classes in this list
Modelling Utilities

Modelling Utilities

mass_matrix_generator

This function takes the mass, position of the center of gravity wrt the elastic axis and the inertia matrix J (3x3) and returns the complete 6x6 mass matrix.

Multibody library

Multibody library

Library used to manipulate multibody systems

Args:

Returns:

Examples:
To use this library: import sharpy.utils.multibody as mb

Notes:

disp2state

disp2state

Fills the vector of states according to the displacements information

Longer description

param MB_beam:each entry represents a body
type MB_beam:list of beam
param MB_tstep:each entry represents a body
type MB_tstep:list of StructTimeStepInfo
param q:Vector of states
type q:numpy array
param dqdt:Time derivatives of states
type dqdt:numpy array
param dqddt:Second time derivatives of states
type dqddt:numpy array

Returns:

Examples:

Notes:

merge_multibody

merge_multibody

This functions merges a series of bodies into a multibody system at a certain time step

Longer description

param MB_beam:each entry represents a body
type MB_beam:list of beam
param MB_tstep:each entry represents a body
type MB_tstep:list of StructTimeStepInfo
param beam:structural information of the multibody system
type beam:beam
param tstep:timestep information of the multibody system
type tstep:StructTimeStepInfo
param mb_data_dict ():
 Dictionary including the multibody information
param dt:time step
type dt:int
returns:structural information of the multibody system tstep (StructTimeStepInfo): timestep information of the multibody system
rtype:beam (beam)

Examples:

Notes:

split_multibody

split_multibody

This functions splits a structure at a certain time step in its different bodies

Longer description

param beam:structural information of the multibody system
type beam:beam
param tstep:timestep information of the multibody system
type tstep:StructTimeStepInfo
param mb_data_dict ():
 Dictionary including the multibody information
returns:each entry represents a body MB_tstep (list of StructTimeStepInfo): each entry represents a body
rtype:MB_beam (list of beam)

Examples:

Notes:

state2disp

state2disp

Recovers the displacements from the states

Longer description

param MB_beam:each entry represents a body
type MB_beam:list of beam
param MB_tstep:each entry represents a body
type MB_tstep:list of StructTimeStepInfo
param q:Vector of states
type q:numpy array
param dqdt:Time derivatives of states
type dqdt:numpy array
param dqddt:Second time derivatives of states
type dqddt:numpy array

Returns:

Examples:

Notes:

update_mb_dB_before_merge

update_mb_db_before_merge

Updates the FoR information database before merge the bodies

Longer description

param tstep:timestep information of the multibody system
type tstep:StructTimeStepInfo
param MB_tstep:each entry represents a body
type MB_tstep:list of StructTimeStepInfo

Returns:

Examples:

Notes:

update_mb_db_before_split

update_mb_db_before_split

Updates the FoR information database before split the system

Longer description

param tstep:timestep information of the multibody system
type tstep:StructTimeStepInfo

Returns:

Examples:

Notes

At this point, this function does nothing, but we might need it at some point

Plotting utilities
set_axes_equal

Make axes of 3D plot have equal scale so that spheres appear as spheres, cubes as cubes, etc.. This is one possible solution to Matplotlib’s ax.set_aspect(‘equal’) and ax.axis(‘equal’) not working for 3D.

Input
ax: a matplotlib axis, e.g., as output from plt.gca().
Settings Generator Utilities

Settings Generator Utilities

SettingsTable
class sharpy.utils.settings.SettingsTable[source]

Generates the documentation’s setting table at runtime.

Sphinx is our chosen documentation manager and takes docstrings in reStructuredText format. Given that the SHARPy solvers contain several settings, this class produces a table in reStructuredText format with the solver’s settings and adds it to the solver’s docstring.

This table will then be printed alongside the remaining docstrings.

To generate the table, parse the setting’s description to a solver dictionary named settings_description, in a similar fashion to what is done with settings_types and settings_default. If no description is given it will be left blank.

Then, add at the end of the solver’s class declaration method an instance of the SettingsTable class and a call to the SettingsTable.generate() method.

Examples

The end of the solver’s class declaration should contain

# Generate documentation table
settings_table = settings.SettingsTable()
__doc__ += settings_table.generate(settings_types, settings_default, settings_description)

to generate the settings table.

generate(settings_types, settings_default, settings_description, settings_options={}, header_line=None)[source]

Returns a rst-format table with the settings’ names, types, description and default values

Parameters:
  • settings_types (dict) – Setting types.
  • settings_default (dict) – Settings default value.
  • settings_description (dict) – Setting description.
  • header_line (str) – Header line description (optional)
Returns:

.rst formatted string with a table containing the settings’ information.

Return type:

str

check_settings_in_options

Checks that settings given a type str or int and allowable options are indeed valid.

param settings:Dictionary of processed settings
type settings:dict
param settings_types:
 Dictionary of settings types
type settings_types:
 dict
param settings_options:
 Dictionary of options (may be empty)
type settings_options:
 dict
raises:exception.NotValidSetting – if the setting is not allowed.
load_config_file

This function reads the flight condition and solver input files.

param file_name:
 contains the path and file name of the file to be read by the configparser reader.
type file_name:str
returns:a ConfigParser object that behaves like a dictionary
rtype:config (dict)

SHARPy Test Cases

The following test cases are provided as a tutorial and introduction to SHARPy as well as for code validation purposes.

  • Geradin and Cardona Beam - See Installation and see test case in ./sharpy/tests/xbeam/

A Short Debugging Guide

We have put together a list of common traps you may fall into, hopefully you will find the tools here to get yourself out of them!

  • Did you forget conda activate sharpy_env and source bin/sharpy_vars.sh?

    • If you do in the terminal: which sharpy, do you get the one you want?
    • If you do which python, does the result point to anaconda3/envs/sharpy_env/bin (or similar)?
  • Wrong input (inconsistent connectivities, mass = 0…)

    • Sometimes not easy to detect. For the structural model, run BeamLoader and BeamPlot with no structural solver in between. Go over the structure in Paraview. Check the fem.h5 file with HDFView.
    • Remember that connectivities are ordered as $[0, 2, 1]$ (the central node goes last).
    • Make sure the num_elem and num_node variables are actually your correct number of elements and nodes.
  • Not running the actual case you want to.

    • Cleanup the folder and regenerate the case
  • Not running the SHARPy version you want.

    • Check at the beginning of the execution the path to the SHARPy folder.
  • Not running the correct branch of the code.

    • You probably want to use develop. Again, check the first few lines of SHARPy output.
  • Very different (I’m talking orders of magnitude) stiffnesses between nodes or directions?

  • Maybe the UVLM requires a smaller a smaller vortex core cutoff (only for linear UVLM simulations, as the nonlinear uses another vortex core model).

  • Newmark damping is not enough for this case?

  • Do you have an element with almost 0 mass or inertia?

  • Are you mass matrices consistent? Check that \(I_{xx} = I_{yy} + I_{zz}\).

  • Have a look at the $dot{Gamma}$ filtering and numerical parameters in the settings of StepUvlm and DynamicCoupled.

  • Add more relaxation to the StaticCoupled or DynamicCoupled solvers.

  • The code has a bug (depending on where, it may be likely).

    • Go over the rest of the list. Plot the case in paraview. Go over the rest of the list again. Prepare the simplest example that reproduces the problem and raise an issue.
  • The code diverges because it has to (physical unstable behaviour)
    • Then don’t complain
  • Your model still doesn’t work and you don’t know why.
    • import pdb; pdb.set_trace() and patience
  • If nothing else works… get a rubber duck (or a very very patient good friend) and go over every step

A rubber duck could be a good friend

If your model doesn’t do what it is supposed to do:

  • Check for symmetric response where the model is symmetric.

    • If it is not, run the beam solver first and make sure your properties are correct. Make sure the matrices for mass and stiffness are rotated if they need to be (remember the Material FoR definition and the for_delta?)
    • Now run the aerodynamic solver only and double check that the forces are symmetric.
    • Make sure your tolerances are low enough so that at least 4 FSI iterations are performed in StaticCoupled or DynamicCoupled.
  • Make sure your inputs are correct. For example: a dynamic case can be run with \(u_\infty = 0\) and the plane moving forwards, or \(u_\infty = x\) whatever and the plane velocity = 0. It is very easy to mix both, and end up with double the effective incoming speed (or none).

  • Run simple stuff before coupling it. For example, if your wing tip deflections don’t match what you’d expect, calculate the deflection under a small tip force (not too small, make sure the deflection is > 1% of the length!) by hand, and compare.

  • It is more difficult to do the same with the UVLM, as you need a VERY VERY high aspect ratio to get close to the 2D potential solutions. You are going to have to take my word for it: the UVLM works.

  • But check the aero grid geometry in Paraview, including chords lengths and angles.

Citing SHARPy

SHARPy has been published in the Journal of Open Source Software (JOSS) and the relevant paper can be found here.

If you are using SHARPy for your work, please remember to cite it using the paper in JOSS as:

del Carre et al., (2019). SHARPy: A dynamic aeroelastic simulation toolbox for very flexible aircraft and wind turbines. Journal of Open Source Software, 4(44), 1885, https://doi.org/10.21105/joss.01885

The bibtex entry for this citation is:

@Article{delCarre2019,
doi = {10.21105/joss.01885},
url = {https://doi.org/10.21105/joss.01885},
year = {2019},
month = dec,
publisher = {The Open Journal},
volume = {4},
number = {44},
pages = {1885},
author = {Alfonso del Carre and Arturo Mu{\~{n}}oz-Sim\'on and Norberto Goizueta and Rafael Palacios},
title = {{SHARPy}: A dynamic aeroelastic simulation toolbox for very flexible aircraft and wind turbines},
journal = {Journal of Open Source Software}
}

Indices and tables

Contact

SHARPy is developed at the Department of Aeronautics, Imperial College London. To get in touch, visit the Loads Control and Aeroelastics Lab website.