1+ """
2+ $(TYPEDEF)
3+ $(TYPEDFIELDS)
4+
5+ `mass_shell` support two types:
6+ - `Dict` or `DataFrames`: discrete radii `:r` and shell masses `:m`
7+ - `function`: a radial function of shell mass
8+ """
9+ struct SphericalSystem{I} <: InitialConditionConfig
10+ collection:: Collection
11+ NumSamples:: I
12+
13+ mass_shell
14+ end
15+
16+ function Base. show (io:: IO , config:: SphericalSystem )
17+ print (io,
18+ " Config of spherical system Initial Conditions:" ,
19+ " \n Particle Collection: " , config. collection,
20+ " \n Number of Samples: " , config. NumSamples,
21+ )
22+ end
23+
24+ """
25+ $(TYPEDSIGNATURES)
26+
27+ """
28+ function generate (config:: SphericalSystem , units = uAstro;
29+ MaxRadius = 0.0 u " kpc" ,
30+ )
31+ uLen = getuLength (units)
32+ uMass = getuMass (units)
33+ uVel = getuVel (units)
34+ NumSamples = config. NumSamples
35+
36+ if iszero (MaxRadius)
37+ error (" Keyword `MaxRadius` should not be zero" )
38+ end
39+
40+ if config. mass_shell isa Function
41+ R = rejection_sampling (config. mass_shell, MaxRadius, NumSamples)
42+ elseif config. mass_shell isa Dict
43+ if haskey (config. mass_shell, " r" ) && haskey (config. mass_shell, " m" )
44+ R = rejection_sampling (config. mass_shell[" r" ], config. mass_shell[" m" ], MaxRadius, NumSamples)
45+ else
46+ error (" `mass_shell` of `SphericalSystem` must be `Dict` or `DataFrame` (with fields `:r`, `:m`) or `Function`" )
47+ end
48+ elseif config. mass_shell isa DataFrame
49+ if hasproperty (config. mass_shell, :r ) && hasproperty (config. mass_shell, :m )
50+ R = rejection_sampling (config. mass_shell. r, config. mass_shell. m, MaxRadius, NumSamples)
51+ else
52+ error (" `mass_shell` of `SphericalSystem` must be `Dict` or `DataFrame` (with fields `:r`, `:m`) or `Function`" )
53+ end
54+ else
55+ error (" `mass_shell` of `SphericalSystem` must be `Dict` or `DataFrame` (with fields `:r`, `:m`) or `Function`" )
56+ end
57+
58+ # Compute total mass
59+ x = collect (LinRange (MaxRadius/ 10000 , MaxRadius, 10000 ))
60+ dx = x[2 ] - x[1 ]
61+ if config. mass_shell isa Function
62+ shell_masses = config. mass_shell .(x)
63+ TotalMass = PhysicalParticles. NumericalIntegration. integrate (x, shell_masses) * ustrip (uLen, dx)
64+ elseif config. mass_shell isa Dict || config. mass_shell isa DataFrame
65+ spl = Spline1D (ustrip .(uLen, config. mass_shell[" r" ]), ustrip .(uMass/ uLen, config. mass_shell[" m" ]))
66+ TotalMass = PhysicalParticles. NumericalIntegration. integrate (x, spl (ustrip .(uLen, x))* uMass/ uLen) * ustrip (uLen, dx)
67+ end
68+
69+ pos = rand_pos_3d .(R)
70+
71+ # TODO : vel
72+ vel = [PVector (uVel) for i in 1 : NumSamples]
73+
74+ # Packing
75+ particles = StructArray (Star (units, id = i) for i in 1 : NumSamples)
76+ assign_particles (particles, :Pos , pos)
77+ assign_particles (particles, :Vel , vel)
78+
79+ Mmean = TotalMass / NumSamples
80+ assign_particles (particles, :Mass , Mmean)
81+
82+ return particles
83+ end
0 commit comments