Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 9 additions & 3 deletions src/vlm/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# Ensure local module import
import sys
sys.path.append('../')
from lib.vlm import VLM, plot_distribution_all, plot_wing_heatmap, plot_wing_heatmap_2d, plot_coefficient_vs_alpha, plot_distribution, plot_CL_CD
from lib.vlm import VLM, plot_distribution_all, plot_wing_heatmap, plot_wing_heatmap_2d, plot_coefficient_vs_alpha, plot_distribution, plot_CL_CD, plot_CLCD_vs_alpha
from lib.naca import plot_naca_airfoil, naca_csv
from lib.geometry import plot_wing_geometry, plot_wing_geometry_2d, plot_wing_discretization_2d, plot_wing_discretization_3d

Expand Down Expand Up @@ -216,6 +216,7 @@ def plane():
if data.getlist("horizontal_toggled[]") == ["1"]:
plane["horizontal_stabilizer"] = {
"x_translate": float(data.get("x_translate", 0.0)),
"z_translate": float(data.get("z_translate", 0.0)),
"NACA_root": data.get("NACA_root", ""),
"NACA_tip": data.get("NACA_tip", ""),
"chord_root": float(data.get("chord_root", 0.0)),
Expand All @@ -228,6 +229,7 @@ def plane():
if data.getlist("vertical_toggled[]") == ["1"]:
plane["vertical_stabilizer"] = {
"x_translate": float(data.get("x_translate_v", 0.0)),
"z_translate": float(data.get("z_translate_v", 0.0)),
"NACA_root": data.get("NACA_root_v", ""),
"NACA_tip": data.get("NACA_tip_v", ""),
"chord_root": float(data.get("chord_root_v", 0.0)),
Expand Down Expand Up @@ -618,6 +620,10 @@ def compute(vlm):
if vlm.results is None or 'CD' not in vlm.results:
return jsonify({"status": "error", "message": "Please calculate coefficients first"}), 400
fig = plot_coefficient_vs_alpha(fig, vlm, coefficient='CD')
elif plot_type == 'CL-CD-alpha':
if vlm.results is None or 'CD' not in vlm.results or 'CL' not in vlm.results:
return jsonify({"status": "error", "message": "Please calculate coefficients first"}), 400
fig = plot_CLCD_vs_alpha(fig, vlm, title=None)
elif plot_type == 'LiftSection':
if 'n_section' in data:
try:
Expand Down Expand Up @@ -646,7 +652,7 @@ def compute(vlm):
if __name__ == "__main__":
optimize_resources()
try:
app.run(host='0.0.0.0', port=5000, debug=True, threaded=True)
# ui.run()
app.run(host='0.0.0.0', port=5001, debug=True, threaded=True)
Comment thread Dismissed
#ui.run()
finally:
thread_pool.shutdown(wait=True)
2 changes: 2 additions & 0 deletions src/vlm/default_plane.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
],
"horizontal_stabilizer": {
"x_translate": 2,
"z_translate":0,
"NACA_root": "3215",
"NACA_tip": "3215",
"chord_root": 0.5,
Expand All @@ -28,6 +29,7 @@
},
"vertical_stabilizer": {
"x_translate": 2,
"z_translate":0,
"NACA_root": "3215",
"NACA_tip": "3215",
"chord_root": 0.5,
Expand Down
13 changes: 9 additions & 4 deletions src/vlm/lib/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def calculate_geometry(self):
- surface_geometry: Dictionary with coordinates of leading edge, trailing edge, and quarter chord
"""
plane = self.plane
def calculate_section_geometry(sections, alpha, is_symmetric, x_translate):
def calculate_section_geometry(sections, alpha, is_symmetric, x_translate, z_translate=0):
print(f"alpha: {alpha}")
# Initialize coordinate arrays for one side
x_leading_edge = []
Expand Down Expand Up @@ -120,6 +120,11 @@ def calculate_section_geometry(sections, alpha, is_symmetric, x_translate):
x_trailing_edge += x_translate
x_quarter_chord += x_translate

# Apply y-translation
z_leading_edge += z_translate
z_trailing_edge += z_translate
z_quarter_chord += z_translate

# If symmetric, mirror across the x-z plane (y=0)
if is_symmetric:
x_leading_edge = np.concatenate((x_leading_edge[::-1], x_leading_edge))
Expand All @@ -146,15 +151,15 @@ def calculate_section_geometry(sections, alpha, is_symmetric, x_translate):
vs_geometry = 0
if 'wing_sections' in plane:
# Calculate geometry for wing sections
wing_geometry = calculate_section_geometry(plane['wing_sections'], self.alpha, is_symmetric=True, x_translate=0)
wing_geometry = calculate_section_geometry(plane['wing_sections'], self.alpha, is_symmetric=True, x_translate=0, z_translate=0)
if 'horizontal_stabilizer' in plane:
# Calculate geometry for horizontal stabilizer
hs = plane['horizontal_stabilizer']
hs_geometry = calculate_section_geometry([hs], hs['alpha'], True, hs['x_translate'])
hs_geometry = calculate_section_geometry([hs], hs['alpha'], True, hs['x_translate'], hs['z_translate'])
if 'vertical_stabilizer' in plane:
# Calculate geometry for vertical stabilizer
vs = plane['vertical_stabilizer']
vs_geometry = calculate_section_geometry([vs], vs['alpha'], False, vs['x_translate'])
vs_geometry = calculate_section_geometry([vs], vs['alpha'], False, vs['x_translate'], vs['z_translate'])

return wing_geometry, hs_geometry, vs_geometry

Expand Down
50 changes: 46 additions & 4 deletions src/vlm/lib/vlm.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,11 +419,11 @@ def plane(self):
num_wing_panels = n * m
num_hs_panels = n_hs * m_hs
num_vs_panels = n_vs * m_vs

# Áreas por sub-superficie
A_wing = panel_areas[:num_wing_panels]
A_hs = panel_areas[num_wing_panels:num_wing_panels + num_hs_panels]
A_vs = panel_areas[num_wing_panels + num_vs_panels:]
A_vs = panel_areas[num_wing_panels + num_hs_panels:num_wing_panels + num_hs_panels + num_vs_panels]

# 5. Calcular lift y drag elementales por panel
lift_per_panel = rho * u * gammas * panel_lengths
Expand Down Expand Up @@ -493,7 +493,7 @@ def coefs(forces, areas, n_sub, m_sub):
# 13. VS: drag
if n_vs != 0:
drag_vs_vec = drag_per_panel[num_wing_panels + num_hs_panels:]
drag_sum_vs, drag_tot_vs, _ = coefs(drag_vs_vec, np.array(A_vs), n_hs, m_hs)
drag_sum_vs, drag_tot_vs, _ = coefs(drag_vs_vec, np.array(A_vs), n_vs, m_vs)
else:
drag_vs_vec = np.zeros(num_vs_panels)
drag_sum_vs = np.zeros(n_vs)
Expand All @@ -514,7 +514,7 @@ def coefs(forces, areas, n_sub, m_sub):
else:
CD_locals_hs = np.zeros(n_hs)
if n_vs != 0:
_, _, CD_locals_vs = coefs(drag_vs_vec, np.array(A_vs), n_hs, m_hs)
_, _, CD_locals_vs = coefs(drag_vs_vec, np.array(A_vs), n_vs, m_vs)
else:
CD_locals_vs = np.zeros(n_vs)
CD_locals_dict = {
Expand Down Expand Up @@ -1027,6 +1027,48 @@ def plot_coefficient_vs_alpha(fig, self, coefficient='CL', title=None):

return fig

def plot_CLCD_vs_alpha(fig, self, title=None):
"""
Plot CL or CD vs angle of attack using precomputed results.
Calculates and displays the slope (pendiente) of the line (in radians).

Parameters:
- coefficient: 'CL' or 'CD'
- title: Optional title for the plot

Returns:
- fig: Plotly Figure object
"""

x_deg = np.array(self.results['angles_deg'])
y1 = np.array(self.results['CL'])
y2 = np.array(self.results['CD'])
x_rad = np.radians(x_deg)


if title is None:
title = "CL/CD vs Angle of Attack"

fig.add_trace(go.Scatter(
x=y2,
y=y1,
mode='lines+markers',
name='CL/CD',
line=dict(color='blue'),
marker=dict(size=8)
))


fig.update_layout(
title=title,
xaxis_title='Angle of Attack (degrees)',
yaxis_title='CL/CD',
autosize=True,
showlegend=True
)

return fig

def plot_distribution(vlm, n_section, quantity='lift'):
"""
Plot the distribution (lift or drag) along the chord for a given spanwise section.
Expand Down
1 change: 1 addition & 0 deletions src/vlm/templates/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ <h2>Analis for different angles of attack</h2>
<div class="button-group">
<button type="button" class="action-button" onclick="plotData('/plot/CL-alpha', 'CL-alpha')">CL vs alpha</button>
<button type="button" class="action-button" onclick="plotData('/plot/CD-alpha', 'CD-alpha')">CD vs alpha</button>
<button type="button" class="action-button" onclick="plotData('/plot/CL-CD-alpha', 'CL-CD-alpha')">CL/CD vs alpha</button>
<button type="button" class="action-button" id="calculate-button" onclick="CalculateAngles()">Calculate</button>
<button type="submit" class="action-button primary">Save</button>
<div id="calculate-spinner" class="spinner" style="display: none;"></div>
Expand Down
10 changes: 10 additions & 0 deletions src/vlm/templates/wing.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ <h3>Horizontal Stabilizer</h3>
<label for="horizontal-stabilizer-x-translate">X Translate (m):</label>
<input type="number" id="horizontal-stabilizer-x-translate" name="x_translate" value="{{ default_plane.horizontal_stabilizer.x_translate }}" step="any">
</div>
<div class="input-group">
<label for="horizontal-stabilizer-x-translate">Z Translate (m):</label>
<input type="number" id="horizontal-stabilizer-z-translate" name="z_translate" value="{{ default_plane.horizontal_stabilizer.z_translate }}" step="any">
</div>
<div class="input-group">
<label for="horizontal-stabilizer-naca-root">NACA Root:</label>
<input type="text" id="horizontal-stabilizer-naca-root" name="NACA_root" value="{{ default_plane.horizontal_stabilizer.NACA_root }}">
Expand Down Expand Up @@ -100,6 +104,10 @@ <h3>Vertical Stabilizer</h3>
<label for="vertical-stabilizer-x-translate">X Translate (m):</label>
<input type="number" id="vertical-stabilizer-x-translate" name="x_translate_v" value="{{ default_plane.vertical_stabilizer.x_translate }}" step="any">
</div>
<div class="input-group">
<label for="vertical-stabilizer-x-translate">Z Translate (m):</label>
<input type="number" id="vertical-stabilizer-z-translate" name="z_translate_v" value="{{ default_plane.vertical_stabilizer.z_translate }}" step="any">
</div>
<div class="input-group">
<label for="vertical-stabilizer-naca-root">NACA Root:</label>
<input type="text" id="vertical-stabilizer-naca-root" name="NACA_root_v" value="{{ default_plane.vertical_stabilizer.NACA_root }}">
Expand Down Expand Up @@ -343,6 +351,7 @@ <h3>Discretization</h3>
}
const h = p.horizontal_stabilizer;
document.getElementById('horizontal-stabilizer-x-translate').value = h.x_translate ?? '';
document.getElementById('horizontal-stabilizer-y-translate').value = h.z_translate ?? '';
document.getElementById('horizontal-stabilizer-naca-root').value = h.NACA_root ?? '';
document.getElementById('horizontal-stabilizer-naca-tip').value = h.NACA_tip ?? '';
document.getElementById('horizontal-stabilizer-chord-root').value = h.chord_root ?? '';
Expand All @@ -360,6 +369,7 @@ <h3>Discretization</h3>
}
const v = p.vertical_stabilizer;
document.getElementById('vertical-stabilizer-x-translate').value = v.x_translate ?? '';
document.getElementById('vertical-stabilizer-y-translate').value = v.z_translate ?? '';
document.getElementById('vertical-stabilizer-naca-root').value = v.NACA_root ?? '';
document.getElementById('vertical-stabilizer-naca-tip').value = v.NACA_tip ?? '';
document.getElementById('vertical-stabilizer-chord-root').value = v.chord_root ?? '';
Expand Down