Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Introducing local sensitivity analysis #575

Merged
merged 37 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0a27b7b
ENH: introducing ImportanceModel class for parameter importance analysis
Lucas-Prates Apr 25, 2024
52aeecb
MNT: adding imports and renaming analysis folder
Lucas-Prates May 9, 2024
a1b5f6b
ENH: implementing plot to ImportanceModel and fixing estimation/impor…
Lucas-Prates May 9, 2024
c8e5e73
ENH: implementing summary method to ImportanceModel
Lucas-Prates May 9, 2024
475dc15
MNT: adding optional requirements for ImportanceModel
Lucas-Prates May 9, 2024
79457ae
MNT: using optional import tools and adding sensitivity dependency in…
Lucas-Prates May 12, 2024
80b017d
MNT: renaming the term 'importance' to 'sensitivity' in variables, fi…
Lucas-Prates May 12, 2024
a53e3ce
MNT: completing renaming from 'importance' to 'sensitivity'
Lucas-Prates May 12, 2024
bf6328e
MNT: Improving doc and input validation.
Lucas-Prates May 13, 2024
0ed82a3
MNT: fixing plot and input validation in SensitivityModel.
Lucas-Prates May 14, 2024
ae50ff3
ENH: implementing function in tools to extract data from MonteCarlo s…
Lucas-Prates May 14, 2024
832eb81
DOC: providing a notebook for quick testing of SensitivityModel (with…
Lucas-Prates May 14, 2024
127c351
MNT: adding json dependency to tools.py
Lucas-Prates May 14, 2024
84f83ec
Fix code style issues with Black
lint-action May 14, 2024
f367dc5
MNT: removing type hints for consistency with codebase (#444)
Lucas-Prates May 16, 2024
a29e5f6
MNT: applying review suggestions to sensitivity analysis.
Lucas-Prates Jun 11, 2024
e0159a0
Changes due to the review
Gui-FernandesBR Aug 22, 2024
8a345c2
MNT: more small fixes
Gui-FernandesBR Aug 22, 2024
64f6849
STY: applies black
Gui-FernandesBR Aug 22, 2024
1f061f1
MNT: adding sources of variation image
Lucas-Prates Aug 24, 2024
b8ea4e7
MNT: rename typo file
Gui-FernandesBR Aug 25, 2024
26ebd92
DOC: improve sensitivity documentation
Gui-FernandesBR Aug 25, 2024
09fff5d
TST: first tests for the sensitivity analysis
Gui-FernandesBR Aug 25, 2024
3ebf3fc
DEV: remove python cache from the CI
Gui-FernandesBR Aug 25, 2024
a8691f6
MNT: remove p-value column from summary table
Lucas-Prates Sep 2, 2024
053aa73
MNT: Replacing Regression coefficient by Effect per sd on summary table.
Lucas-Prates Sep 2, 2024
b1a9c26
DOC: Moving sources of variation image to static doc folder
Lucas-Prates Sep 2, 2024
12c8f9c
DOC: draft documentation of sensitivity model in rst format
Lucas-Prates Sep 4, 2024
b98eea9
DOC: interpreting the results from the sensitivity plot and summary
Lucas-Prates Sep 6, 2024
c5273fe
DOC: fix documentation not building
Gui-FernandesBR Sep 7, 2024
90aff3b
DOC: delete useless sensitivity notebook
Gui-FernandesBR Sep 7, 2024
21d03b0
BUG: fix pip install all command
Gui-FernandesBR Sep 7, 2024
efd558f
TST: revert tests because they are not passing onCI
Gui-FernandesBR Sep 8, 2024
4bb0a18
DOC: fix more docs
Gui-FernandesBR Sep 8, 2024
24ebe66
DOC: fixing and improving technical document on sensitivity analysis
Lucas-Prates Sep 8, 2024
453c4fc
DOC: changing the parameters value to provide a better example
Lucas-Prates Sep 8, 2024
522c8fe
DOC: improving sensitivity analysis practical notebook
Lucas-Prates Sep 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
"ICONEU",
"idxmax",
"IGRA",
"Ilya",
"imageio",
"imread",
"imshow",
Expand All @@ -156,15 +157,18 @@
"Interquartile",
"intp",
"ipynb",
"ipython",
"ipywidgets",
"isbijective",
"isin",
"isort",
"ivar",
"jsonpickle",
"Junqueira",
"jupyter",
"Kaleb",
"Karman",
"labelrotation",
"linalg",
"linestyle",
"linewidth",
Expand Down Expand Up @@ -212,6 +216,7 @@
"noaaruc",
"noaarucsounding",
"num2pydate",
"numericalunits",
"numfig",
"numpy",
"numref",
Expand All @@ -221,18 +226,22 @@
"polystyle",
"powerseries",
"Prandtl",
"prettytable",
"Projeto",
"prometheus",
"pydata",
"pylint",
"PYPI",
"pyplot",
"pyproject",
"pytest",
"pytz",
"quantile",
"Rdot",
"referece",
"relativetoground",
"repr",
"reversesort",
"reynolds",
"rightarrow",
"ROABs",
Expand All @@ -252,6 +261,7 @@
"setrail",
"simplekml",
"SIRGAS",
"Sobol",
"solidmotor",
"somgl",
"Somigliana",
Expand All @@ -260,9 +270,12 @@
"SRTM",
"SRTMGL",
"Stano",
"statsmodels",
"STFT",
"subintervals",
"suptitle",
"supxlabel",
"supylabel",
"ticklabel",
"timedelta",
"timezonefinder",
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
# %% [markdown]
# # Monte Carlo sensitivity analysis simulation

# %% [markdown]
# This notebook shows how execute Monte Carlo simulations to create
# datasets used in the sensitivity analysis.

# %% [markdown]
# First, let's import the necessary libraries

import datetime

# %%
from rocketpy import Environment, Flight, MonteCarlo, Rocket, SolidMotor
from rocketpy.stochastic import (
StochasticEnvironment,
StochasticFlight,
StochasticNoseCone,
StochasticParachute,
StochasticRailButtons,
StochasticRocket,
StochasticSolidMotor,
StochasticTail,
StochasticTrapezoidalFins,
)

# %% [markdown]
# ## Set Distributions

# %% [markdown]
# The Monte Carlo class allows us to express the parameters uncertainty
# by specifying a probability distribution. We consider two possibilities: either the
# parameter is constant and there is no uncertainty about it, or we propose a normal
# distribution and specify its mean and standard deviation.
#
# In this example, the goal of the sensitivity analysis is to study the rocket, motor, flight and parachute
# parameters influence in the flight outputs (e.g. apogee). The dictionary below defines
# the stochastic parameters along with their mean and standard deviation.

# %%
analysis_parameters = {
# Rocket properties
"rocket_mass": {"mean": 14.426, "std": 0.5},
"rocket_radius": {"mean": 127 / 2000, "std": 1 / 1000},
# Motor Properties
"motors_dry_mass": {"mean": 1.815, "std": 1 / 100},
"motors_grain_density": {"mean": 1815, "std": 50},
"motors_total_impulse": {"mean": 5700, "std": 50},
"motors_burn_out_time": {"mean": 3.9, "std": 0.2},
"motors_nozzle_radius": {"mean": 33 / 1000, "std": 0.5 / 1000},
"motors_grain_separation": {"mean": 5 / 1000, "std": 1 / 1000},
"motors_grain_initial_height": {"mean": 120 / 1000, "std": 1 / 100},
"motors_grain_initial_inner_radius": {"mean": 15 / 1000, "std": 0.375 / 1000},
"motors_grain_outer_radius": {"mean": 33 / 1000, "std": 0.375 / 1000},
# Parachutes
"parachutes_main_cd_s": {"mean": 10, "std": 0.1},
"parachutes_main_lag": {"mean": 1.5, "std": 0.1},
"parachutes_drogue_cd_s": {"mean": 1, "std": 0.07},
"parachutes_drogue_lag": {"mean": 1.5, "std": 0.2},
# Flight
"heading": {"mean": 53, "std": 2},
"inclination": {"mean": 84.7, "std": 1},
}

# %% [markdown]
# ## Create Standard Objects
#

# %% [markdown]
# We will first create a standard RocketPy simulation objects (e.g. Environment, SolidMotor, etc.) to then create the Stochastic objects. All
# deterministic parameters are set to its values, and the stochastic ones are set to the `mean` value defined in the dictionary above.
#

# %%
# Environment

env = Environment(latitude=32.990254, longitude=-106.974998, elevation=1400)
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
env.set_date((tomorrow.year, tomorrow.month, tomorrow.day, 12))
env.set_atmospheric_model(type="Forecast", file="GFS")

# Motor
motor = SolidMotor(
thrust_source="../../../data/motors/Cesaroni_M1670.eng",
dry_mass=analysis_parameters["motors_dry_mass"]["mean"],
nozzle_radius=analysis_parameters["motors_nozzle_radius"]["mean"],
grain_density=analysis_parameters["motors_grain_density"]["mean"],
burn_time=analysis_parameters["motors_burn_out_time"]["mean"],
grain_outer_radius=analysis_parameters["motors_grain_outer_radius"]["mean"],
grain_initial_inner_radius=analysis_parameters["motors_grain_initial_inner_radius"][
"mean"
],
grain_initial_height=analysis_parameters["motors_grain_initial_height"]["mean"],
grain_separation=analysis_parameters["motors_grain_separation"]["mean"],
dry_inertia=(0.125, 0.125, 0.002),
grain_number=5,
grains_center_of_mass_position=0.397,
center_of_dry_mass_position=0.317,
nozzle_position=0,
throat_radius=11 / 1000,
coordinate_system_orientation="nozzle_to_combustion_chamber",
)

# Rocket
rocket = Rocket(
radius=analysis_parameters["rocket_radius"]["mean"],
mass=analysis_parameters["rocket_mass"]["mean"],
inertia=(6.321, 6.321, 0.034),
power_off_drag="../../../data/calisto/powerOffDragCurve.csv",
power_on_drag="../../../data/calisto/powerOnDragCurve.csv",
center_of_mass_without_motor=0,
coordinate_system_orientation="tail_to_nose",
)

rail_buttons = rocket.set_rail_buttons(
upper_button_position=0.0818,
lower_button_position=-0.618,
angular_position=45,
)

rocket.add_motor(motor, position=-1.255)

nose_cone = rocket.add_nose(length=0.55829, kind="vonKarman", position=1.278)

fin_set = rocket.add_trapezoidal_fins(
n=4,
root_chord=0.120,
tip_chord=0.060,
span=0.110,
position=-1.04956,
cant_angle=0.5,
airfoil=("../../../data/calisto/NACA0012-radians.csv", "radians"),
)

tail = rocket.add_tail(
top_radius=0.0635, bottom_radius=0.0435, length=0.060, position=-1.194656
)
Main = rocket.add_parachute(
"Main",
cd_s=analysis_parameters["parachutes_main_cd_s"]["mean"],
lag=analysis_parameters["parachutes_main_lag"]["mean"],
trigger=800,
sampling_rate=105,
noise=(0, 8.3, 0.5),
)

Drogue = rocket.add_parachute(
"Drogue",
cd_s=analysis_parameters["parachutes_drogue_cd_s"]["mean"],
lag=analysis_parameters["parachutes_drogue_lag"]["mean"],
trigger="apogee",
sampling_rate=105,
noise=(0, 8.3, 0.5),
)

# Flight
test_flight = Flight(
rocket=rocket,
environment=env,
rail_length=5,
inclination=analysis_parameters["inclination"]["mean"],
heading=analysis_parameters["heading"]["mean"],
)

# %% [markdown]
# ## Create Stochastic Objects

# %% [markdown]
# For each RocketPy object, we will create a ``Stochastic`` counterpart that extends the initial model, allowing us to define the uncertainties of each input parameter. The uncertainty is set as the `std` of the uncertainty dictionary.

# %% [markdown]
# ### Stochastic Environment

# %% [markdown]
# We create a `StochasticEnvironment` to pass to the Monte Carlo class. Our initial goal
# in the sensitivity analysis is to study the influence of motor, rocket, flight
# and parachute parameters in the flight variables. Therefore, the environment is kept
# constant and equals to the prediction made for tomorrow. Note we do not take into
# account the uncertainty of the prediction.

# %%
stochastic_env = StochasticEnvironment(
environment=env,
)

stochastic_env.visualize_attributes()

# %% [markdown]
# ### Motor
#

# %% [markdown]
# We can now create a `StochasticSolidMotor` object to define the uncertainties associated with the motor.

# %%
stochastic_motor = StochasticSolidMotor(
solid_motor=motor,
dry_mass=analysis_parameters["motors_dry_mass"]["std"],
grain_density=analysis_parameters["motors_grain_density"]["std"],
burn_out_time=analysis_parameters["motors_burn_out_time"]["std"],
nozzle_radius=analysis_parameters["motors_nozzle_radius"]["std"],
grain_separation=analysis_parameters["motors_grain_separation"]["std"],
grain_initial_height=analysis_parameters["motors_grain_initial_height"]["std"],
grain_initial_inner_radius=analysis_parameters["motors_grain_initial_inner_radius"][
"std"
],
grain_outer_radius=analysis_parameters["motors_grain_outer_radius"]["std"],
total_impulse=(
analysis_parameters["motors_total_impulse"]["mean"],
analysis_parameters["motors_total_impulse"]["std"],
),
)
stochastic_motor.visualize_attributes()

# %% [markdown]
# ### Rocket
#

# %% [markdown]
# We can now create a `StochasticRocket` object to define the uncertainties associated with the rocket.

# %%
stochastic_rocket = StochasticRocket(
rocket=rocket,
radius=analysis_parameters["rocket_radius"]["std"],
mass=analysis_parameters["rocket_mass"]["std"],
)
stochastic_rocket.visualize_attributes()

# %% [markdown]
# The `StochasticRocket` still needs to have its aerodynamic surfaces and parachutes added.
# As discussed, we need to set the uncertainties in parachute parameters.

# %%
stochastic_nose_cone = StochasticNoseCone(
nosecone=nose_cone,
)

stochastic_fin_set = StochasticTrapezoidalFins(
trapezoidal_fins=fin_set,
)

stochastic_tail = StochasticTail(
tail=tail,
)

stochastic_rail_buttons = StochasticRailButtons(
rail_buttons=rail_buttons,
)

stochastic_main = StochasticParachute(
parachute=Main,
cd_s=analysis_parameters["parachutes_main_cd_s"]["std"],
lag=analysis_parameters["parachutes_main_lag"]["std"],
)

stochastic_drogue = StochasticParachute(
parachute=Drogue,
cd_s=analysis_parameters["parachutes_drogue_cd_s"]["std"],
lag=analysis_parameters["parachutes_drogue_lag"]["std"],
)

# %% [markdown]
# Then we must add them to our stochastic rocket, much like we do in the normal Rocket.
#
#

# %%
stochastic_rocket.add_motor(stochastic_motor)
stochastic_rocket.add_nose(stochastic_nose_cone)
stochastic_rocket.add_trapezoidal_fins(
stochastic_fin_set,
)
stochastic_rocket.add_tail(stochastic_tail)
stochastic_rocket.set_rail_buttons(stochastic_rail_buttons)
stochastic_rocket.add_parachute(stochastic_main)
stochastic_rocket.add_parachute(stochastic_drogue)
stochastic_rocket.visualize_attributes()

# %% [markdown]
#
# ### Flight
#

# %% [markdown]
# The setup is concluded by creating the `StochasticFlight`.

# %%
stochastic_flight = StochasticFlight(
flight=test_flight,
inclination=analysis_parameters["inclination"]["std"],
heading=analysis_parameters["heading"]["std"],
)
stochastic_flight.visualize_attributes()

# %% [markdown]
# ### Run the Monte Carlo Simulations
#

# %% [markdown]
# Finally, we simulate our flights and save the data.

# %%
test_dispersion = MonteCarlo(
filename="monte_carlo_analysis_outputs/sensitivity_analysis_data",
environment=stochastic_env,
rocket=stochastic_rocket,
flight=stochastic_flight,
)
test_dispersion.simulate(number_of_simulations=100, append=False)

# %% [markdown]
# We give a last check on the variables summary results.

# %%
test_dispersion.prints.all()

# %%
Loading
Loading