@@ -200,155 +200,11 @@ function InitialCondition{NDIMS}(coordinates, velocity, mass, density,
200200 masses = mass_fun .(coordinates_svector)
201201 end
202202
203- velocities_ = ELTYPE .(velocities)
204-
205- return InitialCondition (particle_spacing, coordinates, velocities_,
203+ return InitialCondition (particle_spacing, coordinates, ELTYPE .(velocities),
206204 ELTYPE .(masses), ELTYPE .(densities), ELTYPE .(pressures))
207205end
208206
209- @inline function convert_initial_angular_velocity (:: Nothing , :: Val{NDIMS} ,
210- ELTYPE) where {NDIMS}
211- if NDIMS == 3
212- return zero (SVector{3 , ELTYPE})
213- end
214-
215- return zero (ELTYPE)
216- end
217-
218- @inline function convert_initial_angular_velocity (angular_velocity:: Number , :: Val{2} ,
219- ELTYPE)
220- return convert (ELTYPE, angular_velocity)
221- end
222-
223- function convert_initial_angular_velocity (angular_velocity:: Union{Tuple, AbstractArray} ,
224- :: Val{2} , ELTYPE)
225- if length (angular_velocity) == 1
226- return convert (ELTYPE, first (angular_velocity))
227- end
228-
229- throw (ArgumentError (" `angular_velocity` must be a scalar for a 2D problem" ))
230- end
231-
232- function convert_initial_angular_velocity (:: Number , :: Val{3} , ELTYPE)
233- throw (ArgumentError (" `angular_velocity` must be of length 3 for a 3D problem" ))
234- end
235-
236- function convert_initial_angular_velocity (angular_velocity:: Union{Tuple, AbstractArray} ,
237- :: Val{3} , ELTYPE)
238- angular_velocity_ = SVector (angular_velocity... )
239- if length (angular_velocity_) != 3
240- throw (ArgumentError (" `angular_velocity` must be of length 3 for a 3D problem" ))
241- end
242-
243- return SVector {3, ELTYPE} (angular_velocity_)
244- end
245-
246- @inline function convert_initial_angular_velocity (angular_velocity:: Number ,
247- :: Val{NDIMS} ,
248- ELTYPE) where {NDIMS}
249- return convert (ELTYPE, angular_velocity)
250- end
251-
252- function convert_initial_angular_velocity (angular_velocity, :: Val{NDIMS} ,
253- ELTYPE) where {NDIMS}
254- throw (ArgumentError (" `angular_velocity` must be a scalar for a $(NDIMS) D problem" ))
255- end
256-
257- function center_of_mass_from_mass (coordinates, mass, :: Val{NDIMS} , ELTYPE) where {NDIMS}
258- weighted_center_of_mass = zero (SVector{NDIMS, ELTYPE})
259- total_mass = zero (ELTYPE)
260-
261- for particle in eachindex (mass)
262- particle_mass = convert (ELTYPE, mass[particle])
263- total_mass += particle_mass
264- weighted_center_of_mass += particle_mass *
265- extract_svector (coordinates, Val (NDIMS), particle)
266- end
267-
268- if total_mass > eps (ELTYPE)
269- return weighted_center_of_mass / total_mass
270- end
271-
272- center_of_mass = zero (SVector{NDIMS, ELTYPE})
273- n_particles = size (coordinates, 2 )
274- n_particles == 0 && return center_of_mass
275-
276- for particle in axes (coordinates, 2 )
277- center_of_mass += extract_svector (coordinates, Val (NDIMS), particle)
278- end
279-
280- return center_of_mass / n_particles
281- end
282-
283- @inline function add_initial_angular_velocity! (velocities, coordinates, mass,
284- angular_velocity, :: Val{NDIMS} ,
285- ELTYPE) where {NDIMS}
286- return velocities
287- end
288-
289- function add_initial_angular_velocity! (velocities, coordinates, mass,
290- angular_velocity, :: Val{2} , ELTYPE)
291- iszero (angular_velocity) && return velocities
292- center_of_mass = center_of_mass_from_mass (coordinates, mass, Val (2 ), ELTYPE)
293-
294- for particle in axes (velocities, 2 )
295- x = coordinates[1 , particle] - center_of_mass[1 ]
296- y = coordinates[2 , particle] - center_of_mass[2 ]
297- velocities[1 , particle] += - angular_velocity * y
298- velocities[2 , particle] += angular_velocity * x
299- end
300-
301- return velocities
302- end
303-
304- function add_initial_angular_velocity! (velocities, coordinates, mass,
305- angular_velocity, :: Val{3} , ELTYPE)
306- iszero (angular_velocity) && return velocities
307- center_of_mass = center_of_mass_from_mass (coordinates, mass, Val (3 ), ELTYPE)
308-
309- wx = angular_velocity[1 ]
310- wy = angular_velocity[2 ]
311- wz = angular_velocity[3 ]
312-
313- for particle in axes (velocities, 2 )
314- x = coordinates[1 , particle] - center_of_mass[1 ]
315- y = coordinates[2 , particle] - center_of_mass[2 ]
316- z = coordinates[3 , particle] - center_of_mass[3 ]
317-
318- velocities[1 , particle] += wy * z - wz * y
319- velocities[2 , particle] += wz * x - wx * z
320- velocities[3 , particle] += wx * y - wy * x
321- end
322-
323- return velocities
324- end
325-
326- @doc raw """
327- apply_angular_velocity(initial_condition::InitialCondition, angular_velocity)
328-
329- Return a new [`InitialCondition`](@ref) whose velocity includes the rotational
330- contribution `v = ω × r` around the center of mass of `initial_condition`.
331-
332- In 2D, pass a scalar angular speed in rad/s.
333- In 3D, pass a vector of length 3 whose direction gives the rotation axis
334- (right-hand rule) and whose norm `|ω|` gives the angular speed in rad/s.
335- """
336- function apply_angular_velocity (initial_condition:: InitialCondition , angular_velocity)
337- NDIMS = ndims (initial_condition)
338- ELTYPE = eltype (initial_condition)
339- angular_velocity_ = convert_initial_angular_velocity (angular_velocity, Val (NDIMS),
340- ELTYPE)
341- velocity = copy (initial_condition. velocity)
342-
343- add_initial_angular_velocity! (velocity, initial_condition. coordinates,
344- initial_condition. mass, angular_velocity_,
345- Val (NDIMS), ELTYPE)
346207
347- return InitialCondition (initial_condition. particle_spacing,
348- initial_condition. coordinates, velocity,
349- initial_condition. mass, initial_condition. density,
350- initial_condition. pressure)
351- end
352208
353209function Base. show (io:: IO , ic:: InitialCondition )
354210 @nospecialize ic # reduce precompilation time
@@ -610,3 +466,147 @@ function move_particles_to_end!(a::AbstractVector, particle_ids_to_move)
610466end
611467
612468move_particles_to_end! (a:: Real , particle_ids_to_move) = a
469+
470+ @inline function convert_initial_angular_velocity (:: Nothing , :: Val{NDIMS} ,
471+ ELTYPE) where {NDIMS}
472+ if NDIMS == 3
473+ return zero (SVector{3 , ELTYPE})
474+ end
475+
476+ return zero (ELTYPE)
477+ end
478+
479+ @inline function convert_initial_angular_velocity (angular_velocity:: Number , :: Val{2} ,
480+ ELTYPE)
481+ return convert (ELTYPE, angular_velocity)
482+ end
483+
484+ function convert_initial_angular_velocity (angular_velocity:: Union{Tuple, AbstractArray} ,
485+ :: Val{2} , ELTYPE)
486+ if length (angular_velocity) == 1
487+ return convert (ELTYPE, first (angular_velocity))
488+ end
489+
490+ throw (ArgumentError (" `angular_velocity` must be a scalar for a 2D problem" ))
491+ end
492+
493+ function convert_initial_angular_velocity (:: Number , :: Val{3} , ELTYPE)
494+ throw (ArgumentError (" `angular_velocity` must be of length 3 for a 3D problem" ))
495+ end
496+
497+ function convert_initial_angular_velocity (angular_velocity:: Union{Tuple, AbstractArray} ,
498+ :: Val{3} , ELTYPE)
499+ angular_velocity_ = SVector (angular_velocity... )
500+ if length (angular_velocity_) != 3
501+ throw (ArgumentError (" `angular_velocity` must be of length 3 for a 3D problem" ))
502+ end
503+
504+ return SVector {3, ELTYPE} (angular_velocity_)
505+ end
506+
507+ @inline function convert_initial_angular_velocity (angular_velocity:: Number ,
508+ :: Val{NDIMS} ,
509+ ELTYPE) where {NDIMS}
510+ return convert (ELTYPE, angular_velocity)
511+ end
512+
513+ function convert_initial_angular_velocity (angular_velocity, :: Val{NDIMS} ,
514+ ELTYPE) where {NDIMS}
515+ throw (ArgumentError (" `angular_velocity` must be a scalar for a $(NDIMS) D problem" ))
516+ end
517+
518+ function center_of_mass_from_mass (coordinates, mass, :: Val{NDIMS} , ELTYPE) where {NDIMS}
519+ weighted_center_of_mass = zero (SVector{NDIMS, ELTYPE})
520+ total_mass = zero (ELTYPE)
521+
522+ for particle in eachindex (mass)
523+ particle_mass = convert (ELTYPE, mass[particle])
524+ total_mass += particle_mass
525+ weighted_center_of_mass += particle_mass *
526+ extract_svector (coordinates, Val (NDIMS), particle)
527+ end
528+
529+ if total_mass > eps (ELTYPE)
530+ return weighted_center_of_mass / total_mass
531+ end
532+
533+ center_of_mass = zero (SVector{NDIMS, ELTYPE})
534+ n_particles = size (coordinates, 2 )
535+ n_particles == 0 && return center_of_mass
536+
537+ for particle in axes (coordinates, 2 )
538+ center_of_mass += extract_svector (coordinates, Val (NDIMS), particle)
539+ end
540+
541+ return center_of_mass / n_particles
542+ end
543+
544+ @inline function add_initial_angular_velocity! (velocities, coordinates, mass,
545+ angular_velocity, :: Val{NDIMS} ,
546+ ELTYPE) where {NDIMS}
547+ return velocities
548+ end
549+
550+ function add_initial_angular_velocity! (velocities, coordinates, mass,
551+ angular_velocity, :: Val{2} , ELTYPE)
552+ iszero (angular_velocity) && return velocities
553+ center_of_mass = center_of_mass_from_mass (coordinates, mass, Val (2 ), ELTYPE)
554+
555+ for particle in axes (velocities, 2 )
556+ x = coordinates[1 , particle] - center_of_mass[1 ]
557+ y = coordinates[2 , particle] - center_of_mass[2 ]
558+ velocities[1 , particle] += - angular_velocity * y
559+ velocities[2 , particle] += angular_velocity * x
560+ end
561+
562+ return velocities
563+ end
564+
565+ function add_initial_angular_velocity! (velocities, coordinates, mass,
566+ angular_velocity, :: Val{3} , ELTYPE)
567+ iszero (angular_velocity) && return velocities
568+ center_of_mass = center_of_mass_from_mass (coordinates, mass, Val (3 ), ELTYPE)
569+
570+ wx = angular_velocity[1 ]
571+ wy = angular_velocity[2 ]
572+ wz = angular_velocity[3 ]
573+
574+ for particle in axes (velocities, 2 )
575+ x = coordinates[1 , particle] - center_of_mass[1 ]
576+ y = coordinates[2 , particle] - center_of_mass[2 ]
577+ z = coordinates[3 , particle] - center_of_mass[3 ]
578+
579+ velocities[1 , particle] += wy * z - wz * y
580+ velocities[2 , particle] += wz * x - wx * z
581+ velocities[3 , particle] += wx * y - wy * x
582+ end
583+
584+ return velocities
585+ end
586+
587+ @doc raw """
588+ apply_angular_velocity(initial_condition::InitialCondition, angular_velocity)
589+
590+ Return a new [`InitialCondition`](@ref) whose velocity includes the rotational
591+ contribution `v = ω × r` around the center of mass of `initial_condition`.
592+
593+ In 2D, pass a scalar angular speed in rad/s.
594+ In 3D, pass a vector of length 3 whose direction gives the rotation axis
595+ (right-hand rule) and whose norm `|ω|` gives the angular speed in rad/s.
596+ """
597+ function apply_angular_velocity (initial_condition:: InitialCondition , angular_velocity)
598+ NDIMS = ndims (initial_condition)
599+ ELTYPE = eltype (initial_condition)
600+ angular_velocity_ = convert_initial_angular_velocity (angular_velocity, Val (NDIMS),
601+ ELTYPE)
602+ velocity = copy (initial_condition. velocity)
603+
604+ add_initial_angular_velocity! (velocity, initial_condition. coordinates,
605+ initial_condition. mass, angular_velocity_,
606+ Val (NDIMS), ELTYPE)
607+
608+ return InitialCondition (initial_condition. particle_spacing,
609+ initial_condition. coordinates, velocity,
610+ initial_condition. mass, initial_condition. density,
611+ initial_condition. pressure)
612+ end
0 commit comments