Skip to content

Commit db03d14

Browse files
authored
Refactor Section, use @with_kw; refactor Wing (#82)
* export MVec3 * Refactor Section * Add comment * Both versions of Section now documented. * cleanup * document init! * refactoring * use outer constructor and document it (for Wing) * Change inner to outer construcctor for KiteWing * Add/ update docstrings for KiteWing * update docstring * Update docstring * improve script build_docu.jl --------- Co-authored-by: Uwe Fechner <[email protected]>
1 parent db67c4f commit db03d14

File tree

6 files changed

+148
-98
lines changed

6 files changed

+148
-98
lines changed

docs/src/private_functions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ CurrentModule = VortexStepMethod
55
## Private Functions
66
```@docs
77
calculate_AIC_matrices!
8+
init!
89
```

docs/src/types.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,25 @@ InitialGammaDistribution
1111

1212
## Basic Vectors
1313
```@docs
14-
MVec3
15-
PosVector
16-
VelVector
14+
MVec3
15+
PosVector
16+
VelVector
1717
```
1818

1919
## Wing Geometry, Panel and Aerodynamics
2020
A body is constructed of one or more abstract wings. An abstract wing can be a Wing or a KiteWing.
2121
A Wing/ KiteWing has one or more sections.
2222
```@docs
23-
Section
24-
Wing
25-
KiteWing
26-
BodyAerodynamics
23+
Section
24+
Section(LE_point::Vector{Float64}, TE_point::Vector{Float64}, aero_model=nothing, aero_data=nothing)
25+
Wing
26+
Wing(n_panels::Int; spanwise_panel_distribution::PanelDistribution=LINEAR,
27+
spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]))
28+
KiteWing
29+
KiteWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
30+
n_panels=54, n_sections=n_panels+1, spanwise_panel_distribution=UNCHANGED,
31+
spanwise_direction=[0.0, 1.0, 0.0])
32+
BodyAerodynamics
2733
```
2834

2935
## The Solver

scripts/build_docu.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# build and display the html documentation locally
22
# you must have installed the package LiveServer in your global environment
33

4-
using TestEnv; TestEnv.activate()
4+
using Pkg
5+
if !("Documenter" keys(Pkg.project().dependencies))
6+
using TestEnv
7+
TestEnv.activate()
8+
end
59
using LiveServer; servedocs(launch_browser=true)

src/VortexStepMethod.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export Solver, solve
2222
export calculate_results, solve_circulation_distribution
2323
export add_section!, set_va!
2424
export calculate_span, calculate_projected_area
25-
export menu
25+
export menu, MVec3
2626
export Model, VSM, LLT
2727
export AeroModel, LEI_AIRFOIL_BREUKELS, POLAR_DATA, INVISCID
2828
export PanelDistribution, LINEAR, COSINE, COSINE_VAN_GARREL, SPLIT_PROVIDED, UNCHANGED

src/kite_geometry.jl

Lines changed: 81 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -209,70 +209,93 @@ mutable struct KiteWing <: AbstractWing
209209
te_interp::Extrapolation
210210
area_interp::Extrapolation
211211

212-
function KiteWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
213-
n_panels=54, n_sections=n_panels+1, spanwise_panel_distribution=UNCHANGED, spanwise_direction=[0.0, 1.0, 0.0])
214-
215-
!isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && @error "Spanwise direction has to be [0.0, 1.0, 0.0]"
216-
217-
# Load or create polars
218-
(!endswith(dat_path, ".dat")) && (dat_path *= ".dat")
219-
(!isfile(dat_path)) && error("DAT file not found: $dat_path")
220-
polar_path = dat_path[1:end-4] * "_polar.bin"
221-
222-
(!endswith(obj_path, ".obj")) && (obj_path *= ".obj")
223-
(!isfile(obj_path)) && error("OBJ file not found: $obj_path")
224-
info_path = obj_path[1:end-4] * "_info.bin"
225-
226-
if !ispath(polar_path) || !ispath(info_path)
227-
@info "Reading $obj_path"
228-
vertices, faces = read_faces(obj_path)
229-
center_of_mass = calculate_com(vertices, faces)
230-
!(abs(center_of_mass[2]) < 0.01) && @error "Center of mass $center_of_mass has to lie on x-axis."
231-
inertia_tensor = calculate_inertia_tensor(vertices, faces, mass, center_of_mass)
232-
233-
circle_center_z, radius, gamma_tip = find_circle_center_and_radius(vertices)
234-
le_interp, te_interp, area_interp = create_interpolations(vertices, circle_center_z, radius, gamma_tip)
235-
@info "Writing $info_path"
236-
serialize(info_path, (center_of_mass, inertia_tensor, circle_center_z, radius, gamma_tip,
237-
le_interp, te_interp, area_interp))
238-
239-
width = 2gamma_tip * radius
240-
area = area_interp(gamma_tip)
241-
@eval Main begin
242-
foil_path, polar_path, v_wind, area, width, x_turn =
243-
$dat_path, $polar_path, $wind_vel, $gamma_tip, $width, $crease_frac
244-
include("../scripts/polars.jl")
245-
end
246-
end
212+
end
247213

248-
@info "Loading polars and kite info from $polar_path and $info_path"
249-
(alpha_range, beta_range, cl_matrix::Matrix, cd_matrix::Matrix, cm_matrix::Matrix) = deserialize(polar_path)
250-
251-
(center_of_mass, inertia_tensor, circle_center_z, radius, gamma_tip,
252-
le_interp, te_interp, area_interp) = deserialize(info_path)
253-
254-
# Create sections
255-
sections = Section[]
256-
for gamma in range(-gamma_tip, gamma_tip, n_sections)
257-
aero_data = (collect(alpha_range), collect(beta_range), cl_matrix, cd_matrix, cm_matrix)
258-
LE_point = [0.0, 0.0, circle_center_z] .+ [le_interp(gamma), sin(gamma) * radius, cos(gamma) * radius]
259-
if !isapprox(alpha, 0.0)
260-
local_y_vec = [0.0, sin(-gamma), cos(gamma)] × [1.0, 0.0, 0.0]
261-
TE_point = LE_point .+ rotate_v_around_k([te_interp(gamma) - le_interp(gamma), 0.0, 0.0], local_y_vec, alpha)
262-
else
263-
TE_point = LE_point .+ [te_interp(gamma) - le_interp(gamma), 0.0, 0.0]
264-
end
265-
push!(sections, Section(LE_point, TE_point, POLAR_DATA, aero_data))
214+
"""
215+
KiteWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
216+
n_panels=54, n_sections=n_panels+1, spanwise_panel_distribution=UNCHANGED,
217+
spanwise_direction=[0.0, 1.0, 0.0])
218+
219+
Constructor for a [KiteWing](@ref) that allows to use an `.obj` and a `.dat` file as input.
220+
221+
# Parameters
222+
- obj_path: Path to the `.obj` file used for creating the geometry
223+
- dat_path: Path to the `.dat` file, a standard format for 2d foil geometry
224+
225+
# Keyword Parameters
226+
- alpha=0.0: Angle of attack of each segment relative to the x axis [rad]
227+
- crease_frac=0.75: The x coordinate around which the trailing edge rotates on a normalized 2d foil,
228+
used in the xfoil polar generation
229+
- wind_vel=10.0: Apparent wind speed in m/s, used in the xfoil polar generation
230+
- mass=1.0: Mass of the wing in kg, used for the inertia calculations
231+
- `n_panels`=54: Number of panels.
232+
- `n_sections`=n_panels+1: Number of sections (there is a section on each side of each panel.)
233+
- `spanwise_panel_distribution`=UNCHANGED: see: [PanelDistribution](@ref)
234+
- `spanwise_direction`=[0.0, 1.0, 0.0]
235+
"""
236+
function KiteWing(obj_path, dat_path; alpha=0.0, crease_frac=0.75, wind_vel=10., mass=1.0,
237+
n_panels=54, n_sections=n_panels+1, spanwise_panel_distribution=UNCHANGED,
238+
spanwise_direction=[0.0, 1.0, 0.0])
239+
240+
!isapprox(spanwise_direction, [0.0, 1.0, 0.0]) && @error "Spanwise direction has to be [0.0, 1.0, 0.0]"
241+
242+
# Load or create polars
243+
(!endswith(dat_path, ".dat")) && (dat_path *= ".dat")
244+
(!isfile(dat_path)) && error("DAT file not found: $dat_path")
245+
polar_path = dat_path[1:end-4] * "_polar.bin"
246+
247+
(!endswith(obj_path, ".obj")) && (obj_path *= ".obj")
248+
(!isfile(obj_path)) && error("OBJ file not found: $obj_path")
249+
info_path = obj_path[1:end-4] * "_info.bin"
250+
251+
if !ispath(polar_path) || !ispath(info_path)
252+
@info "Reading $obj_path"
253+
vertices, faces = read_faces(obj_path)
254+
center_of_mass = calculate_com(vertices, faces)
255+
!(abs(center_of_mass[2]) < 0.01) && @error "Center of mass $center_of_mass has to lie on x-axis."
256+
inertia_tensor = calculate_inertia_tensor(vertices, faces, mass, center_of_mass)
257+
258+
circle_center_z, radius, gamma_tip = find_circle_center_and_radius(vertices)
259+
le_interp, te_interp, area_interp = create_interpolations(vertices, circle_center_z, radius, gamma_tip)
260+
@info "Writing $info_path"
261+
serialize(info_path, (center_of_mass, inertia_tensor, circle_center_z, radius, gamma_tip,
262+
le_interp, te_interp, area_interp))
263+
264+
width = 2gamma_tip * radius
265+
area = area_interp(gamma_tip)
266+
@eval Main begin
267+
foil_path, polar_path, v_wind, area, width, x_turn =
268+
$dat_path, $polar_path, $wind_vel, $gamma_tip, $width, $crease_frac
269+
include("../scripts/polars.jl")
266270
end
271+
end
272+
273+
@info "Loading polars and kite info from $polar_path and $info_path"
274+
(alpha_range, beta_range, cl_matrix::Matrix, cd_matrix::Matrix, cm_matrix::Matrix) = deserialize(polar_path)
275+
276+
(center_of_mass, inertia_tensor, circle_center_z, radius, gamma_tip,
277+
le_interp, te_interp, area_interp) = deserialize(info_path)
267278

268-
new(
269-
n_panels, spanwise_panel_distribution, spanwise_direction, sections, sections,
270-
mass, center_of_mass, circle_center_z, gamma_tip, inertia_tensor, radius,
271-
le_interp, te_interp, area_interp
272-
)
279+
# Create sections
280+
sections = Section[]
281+
for gamma in range(-gamma_tip, gamma_tip, n_sections)
282+
aero_data = (collect(alpha_range), collect(beta_range), cl_matrix, cd_matrix, cm_matrix)
283+
LE_point = [0.0, 0.0, circle_center_z] .+ [le_interp(gamma), sin(gamma) * radius, cos(gamma) * radius]
284+
if !isapprox(alpha, 0.0)
285+
local_y_vec = [0.0, sin(-gamma), cos(gamma)] × [1.0, 0.0, 0.0]
286+
TE_point = LE_point .+ rotate_v_around_k([te_interp(gamma) - le_interp(gamma), 0.0, 0.0], local_y_vec, alpha)
287+
else
288+
TE_point = LE_point .+ [te_interp(gamma) - le_interp(gamma), 0.0, 0.0]
289+
end
290+
push!(sections, Section(LE_point, TE_point, POLAR_DATA, aero_data))
273291
end
292+
293+
KiteWing(n_panels, spanwise_panel_distribution, spanwise_direction, sections, sections,
294+
mass, center_of_mass, circle_center_z, gamma_tip, inertia_tensor, radius,
295+
le_interp, te_interp, area_interp)
274296
end
275297

298+
276299
function rotate_v_around_k(v, k, θ)
277300
k = normalize(k)
278301
v_rot = v * cos(θ) + (k × v) * sin(θ) + k * (k v) * (1 - cos(θ))

src/wing_geometry.jl

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
11

22
"""
3-
Section
3+
mutable struct Section
44
55
Represents a wing section with leading edge, trailing edge, and aerodynamic properties.
66
77
# Fields
8-
- `LE_point::MVec3`: Leading edge point coordinates
9-
- `TE_point::MVec3`: Trailing edge point coordinates
10-
- `aero_model`::AeroModel: [AeroModel](@ref)
11-
- `aero_data`: Can be:
8+
- `LE_point::MVec3` = zeros(MVec3): Leading edge point coordinates
9+
- `TE_point::MVec3` = zeros(MVec3): Trailing edge point coordinates
10+
- `aero_model`::AeroModel = INVISCID: [AeroModel](@ref)
11+
- `aero_data` = nothing: Can be:
1212
- nothing for INVISCID
1313
- (`tube_diameter`, camber) for `LEI_AIRFOIL_BREUKELS`
1414
- (`alpha_range`, `cl_vector`, `cd_vector`, `cm_vector`) for `POLAR_DATA`
1515
- (`alpha_range`, `beta_range`, `cl_matrix`, `cd_matrix`, `cm_matrix`) for `POLAR_DATA`
1616
"""
17-
mutable struct Section
18-
LE_point::MVec3
19-
TE_point::MVec3
20-
aero_model::AeroModel
17+
@with_kw mutable struct Section
18+
LE_point::MVec3 = zeros(MVec3)
19+
TE_point::MVec3 = zeros(MVec3)
20+
aero_model::AeroModel = INVISCID
2121
aero_data::Union{
2222
Nothing,
2323
NTuple{2, Float64},
2424
Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}, Vector{Float64}},
2525
Tuple{Vector{Float64}, Vector{Float64}, Matrix{Float64}, Matrix{Float64}, Matrix{Float64}}
26-
}
27-
function Section(
28-
LE_point::PosVector = zeros(MVec3),
29-
TE_point::PosVector = zeros(MVec3),
30-
aero_model::AeroModel = INVISCID,
31-
aero_data = nothing
32-
)
33-
new(LE_point, TE_point, aero_model, aero_data)
34-
end
26+
} = nothing
27+
end
28+
"""
29+
Section(LE_point::Vector{Float64}, TE_point::Vector{Float64},
30+
aero_model=INVISCID, aero_data=nothing)
31+
32+
Constructor for [Section](@ref) that allows to pass Vectors of Float64 as point coordinates.
33+
"""
34+
function Section(LE_point::Vector{Float64}, TE_point::Vector{Float64}, aero_model=INVISCID, aero_data=nothing)
35+
Section(MVec3(LE_point), MVec3(TE_point), aero_model, aero_data)
3536
end
3637

38+
"""
39+
init!(section::Section, LE_point, TE_point, aero_model=nothing, aero_data=nothing)
40+
41+
Function to update a [Section](@ref) in place.
42+
"""
3743
function init!(section::Section, LE_point, TE_point, aero_model=nothing, aero_data=nothing)
3844
section.LE_point .= LE_point
3945
section.TE_point .= TE_point
@@ -69,26 +75,36 @@ Represents a wing composed of multiple sections with aerodynamic properties.
6975
# Fields
7076
- `n_panels::Int64`: Number of panels in aerodynamic mesh
7177
- `spanwise_panel_distribution`::PanelDistribution: [PanelDistribution](@ref)
72-
- `spanwise_direction::Vector{Float64}`: Wing span direction vector
73-
- `sections::Vector{Section}`: List of wing sections, see: [Section](@ref)
78+
- `spanwise_direction::MVec3`: Wing span direction vector
79+
- `sections::Vector{Section}`: Vector of wing sections, see: [Section](@ref)
80+
- `refined_sections::Vector{Section}`: Vector of refined wing sections, see: [Section](@ref)
7481
7582
"""
7683
mutable struct Wing <: AbstractWing
7784
n_panels::Int64
7885
spanwise_panel_distribution::PanelDistribution
79-
spanwise_direction::PosVector
86+
spanwise_direction::MVec3
8087
sections::Vector{Section}
8188
refined_sections::Vector{Section}
82-
83-
function Wing(n_panels::Int;
84-
spanwise_panel_distribution::PanelDistribution=LINEAR,
85-
spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]))
86-
new(n_panels,
87-
spanwise_panel_distribution,
88-
spanwise_direction,
89-
Section[],
90-
Section[])
91-
end
89+
end
90+
91+
"""
92+
Wing(n_panels::Int;
93+
spanwise_panel_distribution::PanelDistribution=LINEAR,
94+
spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]))
95+
96+
Constructor for a [Wing](@ref) struct with default values that initializes the sections
97+
and refined sections as empty arrays.
98+
99+
# Parameters
100+
- `n_panels::Int64`: Number of panels in aerodynamic mesh
101+
- `spanwise_panel_distribution`::PanelDistribution = LINEAR: [PanelDistribution](@ref)
102+
- `spanwise_direction::MVec3` = MVec3([0.0, 1.0, 0.0]): Wing span direction vector
103+
"""
104+
function Wing(n_panels::Int;
105+
spanwise_panel_distribution::PanelDistribution=LINEAR,
106+
spanwise_direction::PosVector=MVec3([0.0, 1.0, 0.0]))
107+
Wing(n_panels, spanwise_panel_distribution, spanwise_direction, Section[], Section[])
92108
end
93109

94110
function init!(wing::AbstractWing; aero_center_location::Float64=0.25, control_point_location::Float64=0.75)

0 commit comments

Comments
 (0)