# RCAIDE/Library/Plots/Geometry/generate_3d_propulsor_points.py
#
#
# Created: Jul 2023, M. Clarke
# ----------------------------------------------------------------------------------------------------------------------
# IMPORT
# ----------------------------------------------------------------------------------------------------------------------
import RCAIDE
from RCAIDE.Framework.Core import Data
import numpy as np
# ----------------------------------------------------------------------------------------------------------------------
# PLOTS
# ----------------------------------------------------------------------------------------------------------------------
[docs]
def generate_3d_propulsor_points(propulsor, tessellation = 24):
"""
Generates 3D coordinate points that define a propulsor surface.
Parameters
----------
propulsor : Propulsor
RCAIDE propulsor data structure containing geometry information
tessellation : int, optional
Number of points to use in circumferential discretization (default: 24)
Returns
-------
G : Data
Data structure containing generated points
- PTS : ndarray
Array of shape (num_segments, tessellation, 3) containing
x,y,z coordinates of surface points
Notes
-----
Points are generated by creating super-elliptical cross-sections at each segment
and positioning them according to segment locations.
**Major Assumptions**
* Cross-sections lie in y-z plane
* Segments are ordered from nose to tail
* Origin is at the nose of the fuselage
See Also
--------
plot_3d_fuselage : Function to visualize the generated surface
"""
if type(propulsor) == RCAIDE.Library.Components.Powertrain.Propulsors.Turbofan:
propulsor_geometry = generate_turbofan_geometry(propulsor)
G = generate_points_from_propulsor_geometry(propulsor_geometry, propulsor,tessellation)
return G
elif type(propulsor) == RCAIDE.Library.Components.Powertrain.Propulsors.Turbojet:
propulsor_geometry = generate_turbojet_geometry(propulsor)
G = generate_points_from_propulsor_geometry(propulsor_geometry, propulsor,tessellation)
return G
elif type(propulsor) == RCAIDE.Library.Components.Powertrain.Propulsors.Turboprop:
propulsor_geometry = generate_turboprop_geometry(propulsor)
G = generate_points_from_propulsor_geometry(propulsor_geometry, propulsor, tessellation)
return G
[docs]
def generate_points_from_propulsor_geometry(propulsor_geometry, propulsor,tessellation):
num_prop_segs = len(propulsor_geometry.segments.keys())
propulsor_points = np.zeros((num_prop_segs,tessellation ,3))
if num_prop_segs > 0:
for i_seg, segment in enumerate(propulsor_geometry.segments):
a = segment.width/2
n = segment.curvature
theta = np.linspace(0,2*np.pi,tessellation)
fus_ypts = (abs((np.cos(theta)))**(2/n))*a * ((np.cos(theta)>0)*1 - (np.cos(theta)<0)*1)
fus_zpts = (abs((np.sin(theta)))**(2/n))*a * ((np.sin(theta)>0)*1 - (np.sin(theta)<0)*1)
propulsor_points[i_seg,:,0] = segment.percent_x_location*propulsor_geometry.lengths.total + propulsor.origin[0][0]
propulsor_points[i_seg,:,1] = fus_ypts + segment.percent_y_location*propulsor_geometry.lengths.total + propulsor_geometry.origin[0][1]
propulsor_points[i_seg,:,2] = fus_zpts + segment.percent_z_location*propulsor_geometry.lengths.total + propulsor_geometry.origin[0][2]
G = Data()
G.PTS = propulsor_points
return G
[docs]
def generate_turbofan_geometry(propulsor):
"""
Generates a geometry data structure for a turbofan propulsor based on its parameters.
Parameters
----------
propulsor : Turbofan
RCAIDE turbofan propulsor data structure containing geometry information
Returns
-------
geometry : Data
Data structure containing geometric segments and properties of the turbofan
Notes
-----
The geometry is constructed by defining segments for the fan, core, and nacelle based on the propulsor's dimensions and locations.
**Major Assumptions**
* Segments are defined as super-elliptical cross-sections
* The origin is at the front of the fan
* The geometry is symmetric about the centerline
See Also
--------
generate_3d_propulsor_points : Function to generate 3D points from the geometry
"""
propulsor_geometry = RCAIDE.Library.Components.Booms.Boom() # use boom as a generic geometry container for the propulsor segments
propulsor_geometry.origin = propulsor.origin
propulsor_geometry.lengths.total = propulsor.length
# create generate segments for the fan, core, and nacelle based on the propulsor's dimensions and locations
# segments are defined as circular cross-sections with width
length_scale = 11.2
diameter_scale = 3
diameter = propulsor.diameter
# segment 1 is the front of the fan, which is a small circular cross-section
segment_1 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_1.width = 0
segment_1.percent_x_location = 0
propulsor_geometry.segments.append(segment_1)
# segment 2 is the rear of the fan, which is a circular cross-section with diameter of the cone of the fan blades
segment_2 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_2.width = diameter/diameter_scale * 0.7
segment_2.percent_x_location = 0.9/length_scale
propulsor_geometry.segments.append(segment_2)
# segment 3 is the rear of the fan, which is a circular cross-section with diameter of the fan
segment_3 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_3.width = diameter/diameter_scale * 3
segment_3.percent_x_location = 1/length_scale
propulsor_geometry.segments.append(segment_3)
# segment 4 is the rear of the fan, which is a circular cross-section with diameter of the fan
segment_4 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_4.width = diameter/diameter_scale * 3
segment_4.percent_x_location = 3.9/length_scale
propulsor_geometry.segments.append(segment_4)
# segment 5 is the rear of the fan, which is a circular cross-section of the compressor entrance
segment_5 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_5.width = diameter/diameter_scale * 1.5
segment_5.percent_x_location = 4/length_scale
propulsor_geometry.segments.append(segment_5)
# segment 6 is the rear of the fan, which is a circular cross-section of the compressor entrance
segment_6 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_6.width = diameter/diameter_scale * 1.5
segment_6.percent_x_location = 4.7/length_scale
propulsor_geometry.segments.append(segment_6)
# segment 7 is the rear of the fan, which is a circular cross-section of the combustor entrance
segment_7 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_7.width = diameter/diameter_scale * 1.2
segment_7.percent_x_location = 5.7/length_scale
propulsor_geometry.segments.append(segment_7)
# segment 8 is the rear of the fan, which is a circular cross-section of the turbine entrance
segment_8 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_8.width = diameter/diameter_scale * 1.5
segment_8.percent_x_location = 7.3/length_scale
propulsor_geometry.segments.append(segment_8)
# segment 9 is the rear of the fan, which is a circular cross-section of the turbine entrance
segment_9 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_9.width = diameter/diameter_scale * 1.9
segment_9.percent_x_location = 8.7/length_scale
propulsor_geometry.segments.append(segment_9)
# segment 10 is the rear of the fan, which is a circular cross-section of the turbine exit and nozzle entrance
segment_10 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_10.width = diameter/diameter_scale * 1.9
segment_10.percent_x_location = 9.5/length_scale
propulsor_geometry.segments.append(segment_10)
# segment 11 is the rear of the fan, which is a circular cross-section of the turbine exit and nozzle entrance
segment_11 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_11.width = diameter/diameter_scale * 0.7
segment_11.percent_x_location = 10.5/length_scale
propulsor_geometry.segments.append(segment_11)
# segment 12 is the rear of the fan, which is a circular cross-section of the turbine exit and nozzle entrance
segment_12 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_12.width = diameter/diameter_scale * 0.3
segment_12.percent_x_location = 10.6/length_scale
propulsor_geometry.segments.append(segment_12)
# segment 12 is the rear of the fan, which is a circular cross-section of the turbine exit and nozzle entrance
segment_12 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_12.width = 0
segment_12.percent_x_location = 1
propulsor_geometry.segments.append(segment_12)
return propulsor_geometry
[docs]
def generate_turbojet_geometry(propulsor):
"""
Generates a geometry data structure for a turbojet propulsor based on its parameters.
Parameters
----------
propulsor : Turbojet
RCAIDE turbojet propulsor data structure containing geometry information
Returns
-------
geometry : Data
Data structure containing geometric segments and properties of the turbojet
Notes
-----
The geometry is constructed by defining segments for the fan, core, and nacelle based on the propulsor's dimensions and locations.
**Major Assumptions**
* Segments are defined as super-elliptical cross-sections
* The origin is at the front of the fan
* The geometry is symmetric about the centerline
See Also
--------
generate_3d_propulsor_points : Function to generate 3D points from the geometry
"""
propulsor_geometry = RCAIDE.Library.Components.Booms.Boom() # use boom as a generic geometry container for the propulsor segments
propulsor_geometry.origin = propulsor.origin
propulsor_geometry.lengths.total = propulsor.length
# create generate segments for the fan, core, and nacelle based on the propulsor's dimensions and locations
# segments are defined as circular cross-sections with width
length_scale = 12
diameter_scale = 1.8
diameter = propulsor.diameter
# segment 1 is the front of the fan, which is a small circular cross-section
segment_1 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_1.width = 0
segment_1.percent_x_location = 0
propulsor_geometry.segments.append(segment_1)
# segment 2 is the rear of the fan, which is a circular cross-section with diameter of the cone of the fan blades
segment_2 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_2.width = diameter/diameter_scale * 0.4
segment_2.percent_x_location = 0.475/length_scale
propulsor_geometry.segments.append(segment_2)
# segment 3 is the rear of the fan, which is a circular cross-section with diameter of the fan
segment_3 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_3.width = diameter/diameter_scale * 1.8
segment_3.percent_x_location = 0.45/length_scale
propulsor_geometry.segments.append(segment_3)
# segment 4 is the rear of the fan, which is a circular cross-section with diameter of the fan
segment_4 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_4.width = diameter/diameter_scale * 1.8
segment_4.percent_x_location = 2.36/length_scale
propulsor_geometry.segments.append(segment_4)
# segment 5 is the rear of the fan, which is a circular cross-section of the compressor entrance
segment_5 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_5.width = diameter/diameter_scale * 1.6
segment_5.percent_x_location = 3/length_scale
propulsor_geometry.segments.append(segment_5)
# segment 6 is the rear of the fan, which is a circular cross-section of the compressor entrance
segment_6 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_6.width = diameter/diameter_scale * 1.3
segment_6.percent_x_location = 7.3/length_scale
propulsor_geometry.segments.append(segment_6)
# segment 7 is the rear of the fan, which is a circular cross-section of the combustor entrance
segment_7 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_7.width = diameter/diameter_scale * 1.8
segment_7.percent_x_location = 8.4/length_scale
propulsor_geometry.segments.append(segment_7)
# segment 8 is the rear of the fan, which is a circular cross-section of the turbine entrance
segment_8 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_8.width = diameter/diameter_scale * 1.8
segment_8.percent_x_location = 10.3/length_scale
propulsor_geometry.segments.append(segment_8)
# segment 9 is the rear of the fan, which is a circular cross-section of the turbine entrance
segment_9 = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment_9.width = diameter/diameter_scale * 1
segment_9.percent_x_location = 1
propulsor_geometry.segments.append(segment_9)
return propulsor_geometry
[docs]
def generate_turboprop_geometry(propulsor):
"""Generates a geometry data structure for a turboprop propulsor."""
propulsor_geometry = RCAIDE.Library.Components.Booms.Boom()
propulsor_geometry.origin = propulsor.origin
propulsor_geometry.lengths.total = propulsor.length
length_scale = 10
diameter_scale = 2.0
diameter = propulsor.diameter
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = 0
segment.percent_x_location = 0
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 0.6
segment.percent_x_location = 0.5 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 2.0
segment.percent_x_location = 1.0 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 2.0
segment.percent_x_location = 3.0 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 1.6
segment.percent_x_location = 4.0 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 1.3
segment.percent_x_location = 6.0 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 1.5
segment.percent_x_location = 8.0 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = diameter / diameter_scale * 0.8
segment.percent_x_location = 9.5 / length_scale
propulsor_geometry.segments.append(segment)
segment = RCAIDE.Library.Components.Booms.Segments.Circle_Segment()
segment.width = 0
segment.percent_x_location = 1.0
propulsor_geometry.segments.append(segment)
return propulsor_geometry