-
Notifications
You must be signed in to change notification settings - Fork 16
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
Improved cabin sizing documentation #101
Merged
Merged
Changes from 3 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# [Cabin sizing](@id cabin_sizing) | ||
When creating an aircraft input file, the fuselage geometry has to be specified (i.e., the pressure vessel start and end locations, cylindrical portion start and end locations and radius, guesses for the wing and tail). The user is given the option to resize the fuselage if, for example, these parameters are not known or if the radius is to be optimized. This can be accomplished via [`structures.update_fuse_for_pax!()`](@ref). | ||
|
||
## Theory | ||
!!! details "📖 Theory - Cabin sizing" | ||
The TASOPT input file requires the user to specify a radius and general fuselage layout, including the start and end of the pressure vessel, and the start and end of the cylindrical portions. Whether this provided layout is used or not depends on the flag `calculate_cabin_length` in the `Fuselage.Geometry` input field: this flag is `False` by default, implying that the fuselage length and layout does not get recalculated for the input radius. However, if the flag is set to `True`, the function [`structures.update_fuse_for_pax!()`](@ref) is used to update the fuselage length and layout to accommodate the desired number of passengers. | ||
|
||
To resize the fuselage, information about the number of passengers and seat properties are needed. The number of passengers used the resize the fuselage is set in the input file as `exit_limit` in `Mission`; this is assumed to be the maximum number of people that could fit in the cabin in an all-economy layout. The goal then is to determine the minimum cabin length corresponding to the specified radius and seat properties: seat pitch, width and height. Two key functions are used for this purpose: | ||
|
||
- [`structures.find_floor_angles()`](@ref): This function aims to determine the angular placement of the cabin floor inside the fuselage cross-section. If the cabin has a single deck, this is the angle that maximizes the cabin width. If the aircraft is a double-decker, the main (lower) cabin could be at any angle; the main-cabin angle must then be specified so that the upper-cabin angle can be calculated from the cabin height. The double-decker geometry problem is more involved and is described in the subsequent section. | ||
|
||
- [`structures.find_cabin_width()`](@ref) If the fuselage has a single deck, the angular position of the cabin floor is then used by the following function to calculate the maximum width corresponding to that section. For example, if the seat height is 0, the angular placement would be 0 and the maximum width of a single bubble fuselage is ``2R_{fuse}``. When the seat height is greater than 0, the effective cabin width is the distance between the top or bottom of the seats in the cabin, whichever is smallest. | ||
|
||
Once the geometric properties of the floor and cabin width have been determined, the seats are placed in the cabin so as to determine the total cabin length. A 10 ft offset from the front of the cabin is assumed. First, the number of seats abreast is determined by [`structures.findSeatsAbreast()`](@ref). This function assumes an aisle width of 20 inches and a fuselage offset of 6 inches, as seats do not start at the edge of the fuselage. Once the number of seats abreast is known, the number of rows is calculated from the exit-limit number of passengers and the cabin length is calculated from the seat pitch, taking emergency exits into account. | ||
|
||
When the cabin length has been determined, the [`structures.update_fuse_for_pax!()`](@ref) proceeds to update the position of all the structural elements that have to be specified by the user, such as the cylinder and pressure vessel ends, horizontal and vertical tail placements, etc. To do this, the relative distances between these elements specified by the user are maintained. For example, the distance from the end of the fuselage to the horizontal and vertical tails is the same in the resized aircraft as in the user-defined parameters. | ||
|
||
!!! details "📖 Theory - Double-decker aircraft" | ||
When the cabin has two decks, determining the best layout is more involved as the position of the lower floor and the passenger split between the lower and upper cabins is not known in advance. In TASOPT, this is solved as an optimization problem: the optimization variables are the number of passengers in the lower cabin and the lower-cabin floor angle. The geometry of the cabin is shown in the figure below. | ||
|
||
![cabin](../assets/cabin_layout.svg) | ||
|
||
The objective function to be minimized is the cabin length, which is the maximum of the lengths of the upper and lower cabins. An optimal design is expected to be one in which both cabins have similar lengths. Constraints are applied on the minimum cargo bay height, ``d_{cargo}`` (by default 1.626 m), and on the minimum height of the upper cabin, ``d_{cabin}`` (by default 2 m). The objective function is [`structures.find_double_decker_cabin_length()`](@ref), which returns the maximum of the lengths of either cabins (which is used as the objective function), and the number of seats abreast in the main cabin for a later check (ignored in the optimization process). The optimization is done using the `NLopt.jl` optimization suite via [`structures.optimize_double_decker_cabin()`](@ref). | ||
|
||
Since there are only two optimization variables, this function uses the `GN_AGS` global optimizer. Once the minimum cabin length has been determined, the fuselage and component layouts get updated in [`structures.update_fuse_for_pax!()`](@ref) as in the single deck case. | ||
|
||
!!! details "📖 Theory - Fuselage radius from seats abreast" | ||
In some circumstances, it may be of interest to calculate the minimum fuselage radius that results in a given number of seats abreast. If multiple fuselage radii are being tested, it is likely that the ones providing best performance are those with the narrowest cabin for a given number of seats abreast (and therefore cabin length). | ||
|
||
In TASOPT, this problem is solved as an optimization problem: the goal is to find the minimum fuselage radius such that the seats abreast in the main cabin are exactly equal to the desired number. This is done with `structures.find_minimum_radius_for_seats_per_row()`(@ref). | ||
|
||
In this function, two optimizers are used. First, the global optimizer `GN_DIRECT` is used to find the approximate location of the solution with up to 500 function evaluations. This optimizer cannot handle equality constraints directly; instead, the constraint is introduced with a penalty function. The objective function is simply | ||
```math | ||
f = R_{fuse}+10^3 \Delta s, | ||
``` | ||
where ``\Delta s`` is the difference between the desired and actual seats per row for a given radius. The function that computes this difference for a given radius is [`structures.check_seats_per_row_diff()`](@ref). | ||
``` | ||
|
||
Once the approximate solution has been found, a local optimizer `LN_NELDERMEAD` is used to polish off the solution at a lower computational cost. Finally, the solution is checked to verify it meets the equality constraint. | ||
|
||
## Functions | ||
|
||
```@docs | ||
TASOPT.structures.update_fuse_for_pax! | ||
TASOPT.structures.find_floor_angles | ||
TASOPT.structures.find_cabin_width | ||
TASOPT.structures.findSeatsAbreast | ||
TASOPT.structures.find_double_decker_cabin_length | ||
TASOPT.structures.optimize_double_decker_cabin | ||
TASOPT.structures.find_minimum_radius_for_seats_per_row | ||
TASOPT.structures.check_seats_per_row_diff | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ length. | |
**Inputs:** | ||
- `pax::Float64`: design number of passengers | ||
- `cabin_width::Float64`: width of cabin (m). | ||
- `seat_pitch::Float64`: longitudinal distance between seats (m). | ||
- `seat_width::Float64`: width of one seat (m). | ||
- `aisle_halfwidth::Float64`: half the width of an aisle (m). | ||
- `fuse_offset::Float64`: distance from outside of fuselage to edge of closest window seat (m). | ||
|
@@ -21,7 +22,7 @@ length. | |
function place_cabin_seats(pax, cabin_width, seat_pitch = 30.0*in_to_m, | ||
seat_width = 19.0*in_to_m, aisle_halfwidth = 10.0*in_to_m, fuse_offset = 6.0*in_to_m) | ||
|
||
cabin_offset = 10 * ft_to_m #Distance to the front and back of seats | ||
cabin_offset = 10 * ft_to_m #Distance to the front of seats | ||
#TODO the hardcoded 10 ft is not elegant | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed. off-the-cuff thought: perhaps it could be a default value for a field within the Cabin struct |
||
|
||
seats_per_row = findSeatsAbreast(cabin_width, seat_width, aisle_halfwidth, fuse_offset) | ||
|
@@ -49,6 +50,22 @@ function place_cabin_seats(pax, cabin_width, seat_pitch = 30.0*in_to_m, | |
return lcabin, xseats, seats_per_row | ||
end # function place_cabin_seats | ||
|
||
""" | ||
findSeatsAbreast(cabin_width, | ||
seat_width = 19.0*in_to_m, aisle_halfwidth = 10.0*in_to_m, fuse_offset = 6.0*in_to_m) | ||
|
||
Function to find the number of seats abreast that can fit in a given cabin width. | ||
|
||
!!! details "🔃 Inputs and Outputs" | ||
**Inputs:** | ||
- `cabin_width::Float64`: width of cabin (m). | ||
- `seat_width::Float64`: width of one seat (m). | ||
- `aisle_halfwidth::Float64`: half the width of an aisle (m). | ||
- `fuse_offset::Float64`: distance from outside of fuselage to edge of closest window seat (m). | ||
|
||
**Outputs:** | ||
- `seats_per_row::Float64`: number of seats per row. | ||
""" | ||
function findSeatsAbreast(cabin_width, | ||
seat_width = 19.0*in_to_m, aisle_halfwidth = 10.0*in_to_m, fuse_offset = 6.0*in_to_m) | ||
|
||
|
@@ -202,6 +219,7 @@ passengers on each deck. | |
|
||
**Outputs:** | ||
- `maxl::Float64`: required cabin length (m) | ||
- `pax_per_row_main::Float64`: number of seats abreast in lower cabin | ||
""" | ||
function find_double_decker_cabin_length(x::Vector{Float64}, fuse) | ||
seat_pitch = fuse.cabin.seat_pitch | ||
|
@@ -282,15 +300,16 @@ end | |
""" | ||
optimize_double_decker_cabin(fuse) | ||
|
||
This function can be used to optimize the passenger distribution across two decks in a double decker aircraft. | ||
If the cross-section is circular, it also optimizes the deck layouts. | ||
This function can be used to optimize the deck layouts and passenger distribution in a double decker aircraft. | ||
|
||
!!! details "🔃 Inputs and Outputs" | ||
**Inputs:** | ||
- `parg::Vector{Float64}`: vector with aircraft geometric and mass parameters | ||
- `fuse::Fuselage`: structure with fuselage parameters | ||
|
||
**Outputs:** | ||
- `xopt::Vector{Float64}`: vector with optimization results | ||
- `seats_per_row_main::Float64`: number of seats abreast in lower cabin | ||
""" | ||
function optimize_double_decker_cabin(fuse) | ||
dRfuse = fuse.layout.bubble_lower_downward_shift | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good detailed pass. Two suggestions:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. I just made these changes.