From 3617da6a0938ab58f3acbd1fe9591ece62906e16 Mon Sep 17 00:00:00 2001 From: bolt <58641698+boltyboi@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:21:57 +0100 Subject: [PATCH 1/7] Updated plotutils.py Added code for toggleable "custom_scaling" and "z_compression" which are used on the updated cantilever wing jupyter notebook file. --- sharpy/utils/plotutils.py | 58 ++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/sharpy/utils/plotutils.py b/sharpy/utils/plotutils.py index 76ca5bb9a..0f4cbb405 100644 --- a/sharpy/utils/plotutils.py +++ b/sharpy/utils/plotutils.py @@ -32,19 +32,37 @@ def set_axes_equal(ax): ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius]) -def plot_timestep(data, tstep=-1, minus_mstar=0, plotly=False): - ''' This function creates a simple plot with matplotlib of a +def plot_timestep(data, tstep=-1, minus_mstar=0, plotly=False, custom_scaling=False, z_compression=0.5): + ''' + This function creates a simple plot with matplotlib of a timestep in SHARPy. Notice that this function is not efficient at all for large surfaces, it just aims to provide a simple way of generating simple quick plots. Input: - data (``sharpy.presharpy.presharpy.PreSharpy``): Main data strucuture in SHARPy - tstep (int): Time step to plot - minus_mstar (int): number of wake panels to remove from the visuallisation (for efficiency) + data (``sharpy.presharpy.presharpy.PreSharpy``): + Main data strucuture in SHARPy + + tstep (int): + Time step to plot + + minus_mstar (int): + number of wake panels to remove from the visualisation (for efficiency) + + plotly(bool): + calls in the plotly library, graph will not plot if set to false. + + custom_scaling(bool): + aspect ratio of the wing will be modelled realistically if set to true. + + z_compression(int): + if custom scaling is enabled, this decides how much the z axis is compressed. + Returns: - Plot object: Can be matplotlib.pyplot.plt (plotly=False) or plotly.graph_objects.Figure() (plotly=True) + Plot object: + Can be matplotlib.pyplot.plt (plotly=False) or + plotly.graph_objects.Figure() (plotly=True) ''' if len(data.structure.timestep_info) == 0: @@ -94,7 +112,12 @@ def plot_timestep(data, tstep=-1, minus_mstar=0, plotly=False): print("Plotly package not found") return +# normal part fig = go.Figure() + +#another custom part + + # Plot aerodynamic grid if aero_tstep is not None: for isurf in range(aero_tstep.n_surf): @@ -183,6 +206,9 @@ def plot_timestep(data, tstep=-1, minus_mstar=0, plotly=False): line={'color':'grey'}, showlegend=False)) + + ##END####### + # Plot structure # Split into different beams nodes = data.structure.connectivities[0, :][[0, 2, 1]] @@ -200,6 +226,24 @@ def plot_timestep(data, tstep=-1, minus_mstar=0, plotly=False): marker= {'size':2, 'color':'blue'}, line = {'color':'blue', 'width':4}, showlegend=False)) - + +#I LOVE SEMICOLONS RAAAAH + +## Custom Scaling:: +# This changes how the plotly graph is scaled so the aspect ratio of your wing stays realistic. +# It takes the range of the x and y axes, and scales the graph based on them. +# z is set to 0.5 by default so the wake 'plane' is not as large as it originally is. +# This has the effect of making the wing flex less visible. +# Increase the z_compression value if you want to make it more visible. +# prints were used to check the min and max values of x and y in the graph while implementing this; if something goes wrong you might want to check those out. + + if custom_scaling==True: + #print(np.max(aero_tstep.zeta_star[isurf][0,:(Mstar - minus_mstar),:])) + #print(np.min(aero_tstep.zeta[isurf][0,:,:])) + #print(np.max(aero_tstep.zeta[isurf][1,:,:])) + #print(np.min(aero_tstep.zeta[isurf][1,:,:])) + rangex=np.max(aero_tstep.zeta_star[isurf][0,:(Mstar - minus_mstar),:])-np.min(aero_tstep.zeta[isurf][0,:,:]);rangey=np.max(aero_tstep.zeta[isurf][1,:,:])-np.min(aero_tstep.zeta[isurf][1,:,:]);fig.update_layout(scene=dict(aspectmode='manual', + aspectratio=dict(x=rangex,y=rangey,z=z_compression))) return fig + From 42f4428e2dd5503394c85947639fb720437817fc Mon Sep 17 00:00:00 2001 From: bolt <58641698+boltyboi@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:22:52 +0100 Subject: [PATCH 2/7] Added custom_scaling & z_compression to simulation Various grammar & typo fixes alongside extra clarifications Added a new "custom_scaling" and "z_compression" parameters: If custom_scaling is set to True, the aspect ratio of the wing will be modelled realistically, and the z axis will be compressed. The integer in z_compression determines how compressed the z axis is when custom_scaling is set to true. --- .../example_notebooks/cantilever_wing.ipynb | 16045 ++++++++-------- 1 file changed, 8081 insertions(+), 7964 deletions(-) diff --git a/docs/source/content/example_notebooks/cantilever_wing.ipynb b/docs/source/content/example_notebooks/cantilever_wing.ipynb index 3066fe131..a81018805 100644 --- a/docs/source/content/example_notebooks/cantilever_wing.ipynb +++ b/docs/source/content/example_notebooks/cantilever_wing.ipynb @@ -2,7 +2,9 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [] + }, "source": [ "# A first test case with SHARPy\n", "This notebook explains how to create a prismatic cantilever and flexible wing in SHARPy. It aims to provide a big picture about the simulations available in SHARPy describing the very fundamental concepts. \n", @@ -20,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -47,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -65,7 +67,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -77,7 +79,7 @@ "" ] }, - "execution_count": 5, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -92,42 +94,42 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Geometry\n", - "chord = 1. # Chord of the wing\n", - "aspect_ratio = 16. # Ratio between lenght and chord: aspect_ratio = length/chord\n", - "wake_length = 50 # Length of the wake in chord lengths\n", + "chord = 1. # Chord of the wing | Set to 1 by default\n", + "aspect_ratio = 16. # Ratio between lenght and chord: aspect_ratio = length/chord | Set to 16 by default\n", + "wake_length = 50 # Length of the wake in chord lengths | Set to 50 by default\n", "\n", "# Discretization\n", "num_node = 21 # Number of nodes in the structural discretisation\n", " # The number of nodes will also define the aerodynamic panels in the \n", - " # spanwise direction\n", - "num_chord_panels = 4 # Number of aerodynamic panels in the chordwise direction\n", - "num_points_camber = 200 # The camber line of the wing will be defined by a series of (x,y) \n", - " # coordintes. Here, we define the size of the (x,y) vectors\n", + " # spanwise direction | Set to 21 by default\n", + "num_chord_panels = 4 # Number of aerodynamic panels in the chordwise direction | Set to 4 by default\n", + "num_points_camber = 200 # The camber line of the wing will be defined by a series of (x,y)\n", + " # coordintes. Here, we define the size of the (x,y) vectors | Set to 200 by default\n", "\n", "# Structural properties of the beam cross section\n", - "mass_per_unit_length = 0.75 # Mass per unit length\n", - "mass_iner_x = 0.1 # Mass inertia around the local x axis\n", - "mass_iner_y = 0.05 # Mass inertia around the local y axis\n", - "mass_iner_z = 0.05 # Mass inertia around the local z axis\n", + "mass_per_unit_length = 0.75 # Mass per unit length | Set to 0.75 by default\n", + "mass_iner_x = 0.1 # Mass inertia around the local x axis | Set to 0.1 by default\n", + "mass_iner_y = 0.05 # Mass inertia around the local y axis | Set to 0.05 by default\n", + "mass_iner_z = 0.05 # Mass inertia around the local z axis | Set to 0.05 by default\n", "pos_cg_B = np.zeros((3)) # position of the centre of mass with respect to the elastic axis\n", - "EA = 1e7 # Axial stiffness\n", - "GAy = 1e6 # Shear stiffness in the local y axis\n", - "GAz = 1e6 # Shear stiffness in the local z axis\n", - "GJ = 1e4 # Torsional stiffness\n", - "EIy = 2e4 # Bending stiffness around the flapwise direction\n", - "EIz = 5e6 # Bending stiffness around the edgewise direction\n", + "EA = 1e7 # Axial stiffness | Set to 1e7 by default\n", + "GAy = 1e6 # Shear stiffness in the local y axis | Set to 1e6 by default\n", + "GAz = 1e6 # Shear stiffness in the local z axis | Set to 1e6 by default\n", + "GJ = 1e4 # Torsional stiffness | Set to 1e4 by default\n", + "EIy = 2e4 # Bending stiffness around the flapwise direction | Set to 2e4 by default\n", + "EIz = 5e6 # Bending stiffness around the edgewise direction | Set to 5e6 by default\n", "\n", "# Operation\n", - "WSP = 2. # Wind speed \n", - "air_density = 0.1 # Air density \n", + "WSP = 2.0 # Wind speed | Set to 2.0 by default\n", + "air_density = 0.1 # Air density | Set to 0.1 by default\n", "\n", "# Time discretization\n", - "end_time = 5.0 # End time of the simulation\n", + "end_time = 5.0 # End time of the simulation | Set to 5.0 by default\n", "dt = chord/num_chord_panels/WSP # Always keep one timestep per panel" ] }, @@ -135,17 +137,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "First, we are going to compute the static equilibrium of the wing at an angle of attack (``aoa_ini_deg``). Next, we will change the angle of attack to ``aoa_end_deg`` and we will compute the dynamic response of the wing." + "First, we are going to compute the static equilibrium of the wing at an angle of attack (``aoa_ini_deg``). Next, we will change the angle of attack to ``aoa_end_deg`` and we will compute the dynamic response of the wing. Keep in mind we are not changing the angle of attack of the wing itself in these simulations but of the wind flowing toward it, which has the same effect." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ - "aoa_ini_deg = 2. # Angle of attack at the beginning of the simulation \n", - "aoa_end_deg = 1. # Angle of attack at the end of the simulation " + "aoa_ini_deg = 2. # Angle of attack at the beginning of the simulation | Set to 2 by default\n", + "aoa_end_deg = 1. # Angle of attack at the end of the simulation | Set to 1 by default" ] }, { @@ -161,7 +163,7 @@ "source": [ "### Structural model\n", "\n", - "This section creates a class called ``AeroelasticInformation``. This class is not directly used by SHARPy, it has been thought as an intermediate step between common engineering inputs and the input information that SHARPy needs. \n", + "This section creates a class called ``AeroelasticInformation``. This class is not directly used by SHARPy, it can be thought of as an intermediate step between common engineering inputs and the input information that SHARPy needs. \n", "\n", "It has many functionalities (rotate objects, assembly simple strucures together ...) which can be looked up in the [documentation](https://ic-sharpy.readthedocs.io/en/main/includes/utils/generate_cases/index.html).\n", "\n", @@ -170,7 +172,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -189,7 +191,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -198,7 +200,7 @@ "dict_keys(['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', 'body_number', 'app_forces', 'lumped_mass_nodes', 'lumped_mass', 'lumped_mass_inertia', 'lumped_mass_position', 'lumped_mass_mat', 'lumped_mass_mat_nodes'])" ] }, - "execution_count": 9, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -216,7 +218,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -237,12 +239,12 @@ "source": [ "For a list of methods that allow us to modify the structure, Check the [documentation ](https://ic-sharpy.readthedocs.io/en/main/includes/utils/generate_cases/index.html).\n", "\n", - "First, we need to define the basic characteristics of the equations as the number of nodes, the number of nodes per element, the number of elements and the location of the nodes in the space:" + "First, we need to define the basic characteristics of the equations. This includes the number of nodes, the number of nodes per element, the number of elements and the location of the nodes in the space:" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -255,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -302,7 +304,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -327,12 +329,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If we now show the connectivities between nodes, the function has created them for us. [Further information](https://ic-sharpy.readthedocs.io/en/main/content/casefiles.html?highlight=connectivities#fem-file)" + "Now we can show the connectivities between nodes, as the function has created them for us. [Further information](https://ic-sharpy.readthedocs.io/en/main/content/casefiles.html?highlight=connectivities#fem-file)" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -360,12 +362,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's define the boundary conditions as clamped for node 0 and free for the last node (-1) [Further information](https://ic-sharpy.readthedocs.io/en/main/content/casefiles.html?highlight=boundary#fem-file)" + " figLet's define the boundary conditions as clamped for node 0 and free for the last node (-1), where 1 denotes a clamped point and -1 denotes a free point. [Further information](https://ic-sharpy.readthedocs.io/en/main/content/casefiles.html?highlight=boundary#fem-file)" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -383,7 +385,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -404,7 +406,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -434,7 +436,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -446,6 +448,7 @@ "BeamLoader\n", "DynamicCoupled\n", "DynamicUVLM\n", + "InitialAeroelasticLoader\n", "LinDynamicSim\n", "LinearAssembler\n", "Modal\n", @@ -455,11 +458,11 @@ "NonLinearDynamicMultibody\n", "NonLinearDynamicPrescribedStep\n", "NonLinearStatic\n", + "NoStructural\n", "PrescribedUvlm\n", "RigidDynamicCoupledStep\n", "RigidDynamicPrescribedStep\n", "StaticCoupled\n", - "StaticCoupledRBM\n", "StaticTrim\n", "StaticUvlm\n", "StepLinearUVLM\n", @@ -468,36 +471,42 @@ "NewmarkBeta\n", "GeneralisedAlpha\n", "Trim\n", - "LiftDistribution\n", - "Cleanup\n", - "AerogridPlot\n", - "BeamPlot\n", - "UDPout\n", - "PlotFlowField\n", - "PickleData\n", - "SaveParametricCase\n", - "FrequencyResponse\n", - "StallCheck\n", + "UpdatePickle\n", + "StabilityDerivatives\n", "WriteVariablesTime\n", - "CreateSnapshot\n", "SHARPy\n", "SaveData\n", - "AeroForcesCalculator\n", - "AsymptoticStability\n", "BeamLoads\n", - "FloatingForces\n", - "ShearVelocityField\n", + "UDPout\n", + "SaveParametricCase\n", + "AerogridPlot\n", + "Cleanup\n", + "PlotFlowField\n", + "FrequencyResponse\n", + "AsymptoticStability\n", + "LiftDistribution\n", + "AeroForcesCalculator\n", + "StallCheck\n", + "BeamPlot\n", + "PickleData\n", "DynamicControlSurface\n", - "GustVelocityField\n", - "TrajectoryGenerator\n", + "FloatingForces\n", "TurbVelocityField\n", - "SteadyVelocityField\n", + "TrajectoryGenerator\n", + "PolarCorrection\n", + "EfficiencyCorrection\n", "ModifyStructure\n", - "StraightWake\n", + "GustVelocityField\n", + "SteadyVelocityField\n", "HelicoidalWake\n", - "GridBox\n", "BumpVelocityField\n", - "TurbVelocityFieldBts\n" + "GridBox\n", + "StraightWake\n", + "TurbVelocityFieldBts\n", + "ShearVelocityField\n", + "BladePitchPid\n", + "ControlSurfacePidController\n", + "TakeOffTrajectoryController\n" ] } ], @@ -515,12 +524,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's output as an example, the input parameters of the ``BeamLoader`` solver. This solver is in charge of loading the structural infromation" + "As an example, let's output the input parameters of the ``BeamLoader`` solver. This solver is in charge of loading the structural infromation." ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -529,7 +538,7 @@ "{'unsteady': True, 'orientation': [1.0, 0, 0, 0], 'for_pos': [0.0, 0, 0]}" ] }, - "execution_count": 19, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -542,12 +551,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The following dictionary defines the basic inputs of SHARPy including the solvers to be run (``flow`` variable), the case name and the route in the file system. In this case we are turning off the screen output because it is useless because we are not running any computation. " + "The following dictionary defines the basic inputs of SHARPy including the solvers to be run (``flow`` variable), the case name and the route in the file system. In this case we are turning off the screen output because we are not running any computation; it is useless." ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -563,12 +572,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We do not modify any of the default input paramteters in ``BeamLoader`` but we need to define the initial wake shape that we want and its size (``wake_panels``)" + "We do not modify any of the default input paramteters in ``BeamLoader`` but we need to define the initial wake shape that we want and its size (``wake_panels``)." ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -588,12 +597,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The following functions write the input files needed by SHARPy" + "The following functions write the input files needed by SHARPy." ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -606,14 +615,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The following line of code runs SHARPy inside the jupyter notebook. It is equivalent to run in a terminal: ``sharpy plot.sharpy`` being \"plot\" the case name defined above" + "The following line of code runs SHARPy inside of jupyter notebook. It is equivalent to running this in a terminal, with: ``sharpy plot.sharpy`` being \"plot\", the case name defined above." ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 21, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "fatal: not a git repository (or any of the parent directories): .git\n" + ] + } + ], "source": [ "sharpy_output = sharpy.sharpy_main.main(['',\n", " SimInfo.solvers['SHARPy']['route'] +\n", @@ -627,14 +644,20 @@ "source": [ "Let's plot the case we have created. The function below provides a quick way of generating an interactive plot but it is not suitable for large cases. Luckily SHARPy has other more complex plotting capabilities.\n", "\n", - "If you download the original [jupyter notebook](https://ic-sharpy.readthedocs.io/en/main/content/examples.html), change thee geometric parameters above and rerun the jupyter notebook you will see its impact on the geometry.\n", + "If you download the original [jupyter notebook](https://ic-sharpy.readthedocs.io/en/main/content/examples.html), change the geometric parameters above and rerun the notebook, you will see its impact on the geometry.\n", + "\n", + "In our simulations only the first 6 wake panels are plotted for the sake of efficiency. This can be changed by changing the number within ```minus_mstar```.\n", + "\n", + "Setting ```plotly``` to ```False``` will not plot a graph.\n", "\n", - "Only the first 6 wake panels are plotted for efficiency." + "```custom_scaling``` is a toggleable feature that realistically models the wing's aspect ratio and compresses the z axis. It is disabled by default.\n", + "\n", + "If ```custom_scaling``` is toggled on,```z_compression``` determines how compressed the z axis is. By default this is set to 0.5." ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -642,71 +665,18 @@ "text/html": [ "