@@ -133,35 +133,35 @@ end
133133 @testset " Around Core Radius" begin
134134 filament = create_test_filament ()
135135 delta = 1e-5
136-
136+
137137 points = [
138138 [0.5 , core_radius_fraction - delta, 0.0 ],
139139 [0.5 , core_radius_fraction, 0.0 ],
140140 [0.5 , core_radius_fraction + delta, 0.0 ]
141141 ]
142-
142+
143143 velocities = [zeros (3 ) for p in points]
144144 [
145145 velocity_3D_bound_vortex! (velocities[i], filament, p, gamma, core_radius_fraction, work_vectors)
146146 for (i, p) in enumerate (points)
147147 ]
148-
148+
149149 # Check for NaN and finite values
150150 @test all (! any (isnan .(v)) for v in velocities)
151151 @test all (all (isfinite .(v)) for v in velocities)
152-
152+
153153 # Check magnitude is maximum at core radius
154154 @test norm (velocities[2 ]) > norm (velocities[1 ])
155155 @test norm (velocities[2 ]) > norm (velocities[3 ])
156-
156+
157157 # Check continuity around core radius
158158 @test isapprox (velocities[1 ], velocities[2 ], rtol= 1e-2 )
159-
159+
160160 # Check non-zero velocities
161161 @test ! all (isapprox .(velocities[1 ], zeros (3 ), atol= 1e-10 ))
162162 @test ! all (isapprox .(velocities[2 ], zeros (3 ), atol= 1e-10 ))
163163 @test ! all (isapprox .(velocities[3 ], zeros (3 ), atol= 1e-10 ))
164-
164+
165165 # Check symmetry
166166 v_neg = zeros (3 )
167167 velocity_3D_bound_vortex! (
174174 )
175175 @test isapprox (velocities[2 ], - v_neg)
176176 end
177+
178+ @testset " Velocity is azimuthal (perpendicular to axis and radius)" begin
179+ # A real vortex's induced velocity is purely azimuthal:
180+ # perpendicular to BOTH the filament axis r0 AND the radial
181+ # direction from the axis to the field point. The old Branch 3
182+ # projected the field point in the azimuthal direction instead
183+ # of the radial direction, producing a velocity with a nonzero
184+ # radial component. This test catches that.
185+ filament = create_test_filament ()
186+ r0 = [1.0 , 0.0 , 0.0 ]
187+
188+ # Probe at multiple distances spanning both branches (in-core
189+ # and outside-core) and azimuthal positions.
190+ for d in (0.25 , 0.5 , 0.99 , 1.0 , 1.01 , 2.0 ) .* core_radius_fraction
191+ for phi in (0.0 , π/ 4 , π/ 2 , π, - π/ 3 )
192+ p = [0.5 , d * cos (phi), d * sin (phi)]
193+ v = zeros (3 )
194+ velocity_3D_bound_vortex! (
195+ v, filament, p, gamma,
196+ core_radius_fraction, work_vectors)
197+
198+ # Radial direction at p (perpendicular to axis)
199+ r_radial = [0.0 , p[2 ], p[3 ]]
200+
201+ # v must be perpendicular to both axis and radial
202+ @test isapprox (dot (v, r0), 0.0 ; atol= 1e-10 )
203+ @test isapprox (dot (v, r_radial), 0.0 ; atol= 1e-8 )
204+ end
205+ end
206+ end
207+
208+ @testset " Solid-body rotation inside core" begin
209+ # Inside the core, velocity magnitude scales linearly with
210+ # d_perp (Branch 3 = linear ramp from 0 on axis to peak at
211+ # boundary). Direction stays constant along a radial line.
212+ filament = create_test_filament ()
213+
214+ v_half = zeros (3 )
215+ v_quarter = zeros (3 )
216+ velocity_3D_bound_vortex! (
217+ v_half, filament,
218+ [0.5 , 0.5 * core_radius_fraction, 0.0 ],
219+ gamma, core_radius_fraction, work_vectors)
220+ velocity_3D_bound_vortex! (
221+ v_quarter, filament,
222+ [0.5 , 0.25 * core_radius_fraction, 0.0 ],
223+ gamma, core_radius_fraction, work_vectors)
224+
225+ # Magnitudes scale linearly with d_perp
226+ @test isapprox (norm (v_quarter), 0.5 * norm (v_half); rtol= 1e-3 )
227+ # Directions are parallel
228+ @test isapprox (normalize (v_quarter), normalize (v_half); atol= 1e-8 )
229+ end
230+
231+ @testset " Branch 1 / Branch 3 agree at core boundary" begin
232+ # The two branches are designed to be continuous at d_perp =
233+ # epsilon. Probe just inside and just outside the boundary with
234+ # enough delta to clearly land in different branches; results
235+ # must agree in both magnitude AND direction. Old code returned
236+ # orthogonal directions here.
237+ filament = create_test_filament ()
238+ delta = 0.05 * core_radius_fraction # 5% in/out
239+ v_inside = zeros (3 )
240+ v_outside = zeros (3 )
241+ velocity_3D_bound_vortex! (
242+ v_inside, filament,
243+ [0.5 , core_radius_fraction - delta, 0.0 ],
244+ gamma, core_radius_fraction, work_vectors)
245+ velocity_3D_bound_vortex! (
246+ v_outside, filament,
247+ [0.5 , core_radius_fraction + delta, 0.0 ],
248+ gamma, core_radius_fraction, work_vectors)
249+
250+ # Magnitudes within a few % of each other (peak is at boundary)
251+ @test isapprox (norm (v_inside), norm (v_outside); rtol= 0.1 )
252+ # Directions match — would fail with old azimuthal-projection bug
253+ @test isapprox (normalize (v_inside), normalize (v_outside); atol= 1e-2 )
254+ end
177255end
0 commit comments