@@ -39,10 +39,11 @@ function reinit!(filament::BoundFilament{T}, x1, x2, vec=zeros(MVector{3, T})) w
3939end
4040
4141"""
42- velocity_3D_bound_vortex(vel, filament::BoundFilament, XVP,
43- gamma, core_radius_fraction, work_vectors)
42+ velocity_3D_bound_vortex! (vel, filament::BoundFilament, XVP,
43+ gamma, core_radius_fraction, work_vectors)
4444
45- Calculate induced velocity by a bound vortex filament at a point in space.
45+ Calculate induced velocity by a bound vortex filament at a point in space, with a
46+ core radius of `core_radius_fraction` times the filament length.
4647"""
4748function velocity_3D_bound_vortex! (
4849 vel,
@@ -52,87 +53,24 @@ function velocity_3D_bound_vortex!(
5253 core_radius_fraction,
5354 work_vectors
5455)
55- r1, r2, r1Xr2, r1Xr0, r2Xr0, r1r2norm, r1_proj, r2_proj,
56- r1_projXr2_proj, vel_ind_proj = work_vectors
57- r0 = filament. r0
58- nr0 = filament. length
59- r1 .= XVP .- filament. x1
60- r2 .= XVP .- filament. x2
61-
62- epsilon = core_radius_fraction * nr0
63-
64- cross3! (r1Xr0, r1, r0)
65-
66- # Check point location relative to filament
67- nr1Xr0 = norm3 (r1Xr0)
68- if nr1Xr0 / nr0 > epsilon
69- cross3! (r1Xr2, r1, r2)
70- nr1 = norm3 (r1)
71- nr2 = norm3 (r2)
72- @inbounds for k in 1 : 3
73- r1r2norm[k] = r1[k]/ nr1 - r2[k]/ nr2
74- end
75- nr1Xr2 = norm3 (r1Xr2)
76- coeff = (gamma / (4 π)) / (nr1Xr2^ 2 ) * dot3 (r0, r1r2norm)
77- @inbounds for k in 1 : 3
78- vel[k] = coeff * r1Xr2[k]
79- end
80- elseif nr1Xr0 / nr0 < 1e-12 * epsilon
81- vel .= 0.0
82- else
83- @debug " inside core radius"
84- @debug " distance from control point to filament: $(nr1Xr0 / nr0) "
85-
86- nr0sq = nr0 * nr0
87- d_r1_r0 = dot3 (r1, r0)
88- d_r2_r0 = dot3 (r2, r0)
89- r_rad = r1Xr0
90- @inbounds for k in 1 : 3
91- r_rad[k] = r1[k] - d_r1_r0 * r0[k] / nr0sq
92- end
93- nr_rad = norm3 (r_rad)
94- @inbounds for k in 1 : 3
95- r1_proj[k] = d_r1_r0 * r0[k] / nr0sq +
96- epsilon * r_rad[k] / nr_rad
97- r2_proj[k] = d_r2_r0 * r0[k] / nr0sq +
98- epsilon * r_rad[k] / nr_rad
99- end
100- cross3! (r1_projXr2_proj, r1_proj, r2_proj)
101-
102- nr1pXr2p = norm3 (r1_projXr2_proj)
103- nr1_proj = norm3 (r1_proj)
104- nr2_proj = norm3 (r2_proj)
105- d_sum = 0.0
106- @inbounds for k in 1 : 3
107- d_sum += r0[k] * (r1_proj[k]/ nr1_proj -
108- r2_proj[k]/ nr2_proj)
109- end
110- coeff = (gamma / (4 π)) / (nr1pXr2p^ 2 ) * d_sum
111- @inbounds for k in 1 : 3
112- vel_ind_proj[k] = coeff * r1_projXr2_proj[k]
113- end
114-
115- scale = nr1Xr0 / (nr0 * epsilon)
116- @inbounds for k in 1 : 3
117- vel[k] = scale * vel_ind_proj[k]
118- end
119- end
120- nothing
56+ epsilon = core_radius_fraction * filament. length
57+ velocity_3D_vortex_segment! (vel, filament, XVP, gamma, epsilon, work_vectors)
12158end
12259
12360"""
124- velocity_3D_trailing_vortex(vel, filament::BoundFilament,
125- XVP, gamma, va, work_vectors)
61+ velocity_3D_trailing_vortex! (vel, filament::BoundFilament,
62+ XVP, gamma, va, work_vectors)
12663
127- Calculate induced velocity by a trailing vortex filament.
64+ Calculate induced velocity by a trailing vortex filament, with a Lamb–Oseen core
65+ radius grown over the axial distance of `XVP` from the filament start.
12866
12967# Arguments
13068- `XVP`: Control point coordinates
13169- `gamma`: Vortex strength
13270- `va`: Inflow velocity magnitude
13371- work_vectors: preallocated array of intermediate variables
13472
135- Reference: Rick Damiani et al. "A vortex step method for nonlinear airfoil polar data
73+ Reference: Rick Damiani et al. "A vortex step method for nonlinear airfoil polar data
13674as implemented in KiteAeroDyn".
13775"""
13876@inline function velocity_3D_trailing_vortex! (
@@ -143,71 +81,78 @@ as implemented in KiteAeroDyn".
14381 va,
14482 work_vectors
14583)
146- r1 = work_vectors[2 ]
147- r2 = work_vectors[3 ]
148- r_perp = work_vectors[4 ]
149- r1Xr2 = work_vectors[5 ]
150- r1Xr0 = work_vectors[6 ]
151- r2Xr0 = work_vectors[7 ]
152- normr1r2 = work_vectors[8 ]
84+ r1 = work_vectors[1 ]
85+ r1 .= XVP .- filament. x1
86+ axial_distance = abs (dot3 (r1, filament. r0)) / filament. length
87+ epsilon = sqrt (4 * ALPHA0 * NU * axial_distance / va)
88+ velocity_3D_vortex_segment! (vel, filament, XVP, gamma, epsilon, work_vectors)
89+ end
15390
91+ """
92+ velocity_3D_vortex_segment!(vel, filament::BoundFilament, XVP,
93+ gamma, epsilon, work_vectors)
94+
95+ Calculate the Biot–Savart velocity induced by a straight vortex segment at `XVP`.
96+ Inside the core radius `epsilon` the velocity is evaluated on the core boundary and
97+ scaled linearly with the distance to the axis.
98+ """
99+ @inline function velocity_3D_vortex_segment! (
100+ vel,
101+ filament:: BoundFilament ,
102+ XVP,
103+ gamma,
104+ epsilon,
105+ work_vectors
106+ )
107+ r1, r2, r1Xr2, r1Xr0, r1r2norm, r1_proj, r2_proj = work_vectors
154108 r0 = filament. r0
155109 nr0 = filament. length
156110 r1 .= XVP .- filament. x1
157111 r2 .= XVP .- filament. x2
158112
159- nr0sq = nr0 * nr0
160- d_r1_r0 = dot3 (r1, r0)
161-
162- # Cut-off radius. The perpendicular component has length |r1.r0|/|r0|, so the
163- # vector itself is only needed inside the core.
164- epsilon = sqrt (4 * ALPHA0 * NU * abs (d_r1_r0) / nr0 / va)
165-
166113 cross3! (r1Xr0, r1, r0)
167-
168- # Check point location relative to filament
169114 nr1Xr0 = norm3 (r1Xr0)
170115 if nr1Xr0 / nr0 > epsilon
171116 cross3! (r1Xr2, r1, r2)
172117 nr1 = norm3 (r1)
173118 nr2 = norm3 (r2)
174119 @inbounds for k in 1 : 3
175- normr1r2 [k] = r1[k]/ nr1 - r2[k]/ nr2
120+ r1r2norm [k] = r1[k]/ nr1 - r2[k]/ nr2
176121 end
177122 nr1Xr2 = norm3 (r1Xr2)
178- coeff = (gamma / (4 π)) / (nr1Xr2^ 2 ) * dot3 (r0, normr1r2 )
123+ coeff = (gamma / (4 π)) / (nr1Xr2^ 2 ) * dot3 (r0, r1r2norm )
179124 @inbounds for k in 1 : 3
180125 vel[k] = coeff * r1Xr2[k]
181126 end
182127 elseif nr1Xr0 / nr0 < 1e-12 * epsilon
183128 vel .= 0.0
184129 else
185- # Project onto core radius — reuse r_perp, normr1r2
186- r1_proj = r_perp
187- r2_proj = normr1r2
188- cross3! (r2Xr0, r2, r0)
189- nr2Xr0 = norm3 (r2Xr0)
130+ nr0sq = nr0 * nr0
131+ d_r1_r0 = dot3 (r1, r0)
190132 d_r2_r0 = dot3 (r2, r0)
133+ r_rad = r1Xr0
134+ @inbounds for k in 1 : 3
135+ r_rad[k] = r1[k] - d_r1_r0 * r0[k] / nr0sq
136+ end
137+ nr_rad = norm3 (r_rad)
191138 @inbounds for k in 1 : 3
192139 r1_proj[k] = d_r1_r0 * r0[k] / nr0sq +
193- epsilon * r1Xr0 [k] / nr1Xr0
140+ epsilon * r_rad [k] / nr_rad
194141 r2_proj[k] = d_r2_r0 * r0[k] / nr0sq +
195- epsilon * r2Xr0 [k] / nr2Xr0
142+ epsilon * r_rad [k] / nr_rad
196143 end
197-
198144 cross3! (r1Xr2, r1_proj, r2_proj)
199- nr1Xr2_val = norm3 (r1Xr2)
200145 nr1_proj = norm3 (r1_proj)
201146 nr2_proj = norm3 (r2_proj)
202147 d_sum = 0.0
203148 @inbounds for k in 1 : 3
204149 d_sum += r0[k] * (r1_proj[k]/ nr1_proj -
205150 r2_proj[k]/ nr2_proj)
206151 end
207- coeff = (gamma / (4 π)) / (nr1Xr2_val^ 2 ) * d_sum
208152 scale = nr1Xr0 / (nr0 * epsilon)
153+ coeff = scale * (gamma / (4 π)) / (norm3 (r1Xr2)^ 2 ) * d_sum
209154 @inbounds for k in 1 : 3
210- vel[k] = scale * coeff * r1Xr2[k]
155+ vel[k] = coeff * r1Xr2[k]
211156 end
212157 end
213158 nothing
@@ -263,8 +208,7 @@ function velocity_3D_trailing_vortex_semiinfinite!(
263208 GAMMA = - GAMMA * filament. filament_direction
264209 r1 .= XVP .- filament. x1
265210
266- # Core radius. `r_perp` is `(r1.Vf) Vf`, so its length is `|r1.Vf| |Vf|` and
267- # the vector itself is only needed inside the core.
211+ # Core radius, grown with the axial distance of `XVP` along `Vf`.
268212 d_r1_Vf = dot3 (r1, Vf)
269213 nVf = norm3 (Vf)
270214 epsilon = sqrt (4 * ALPHA0 * NU * abs (d_r1_Vf) * nVf / va)
0 commit comments