1- import random
2- import math
3-
4- _particles = []
5-
6- def particleAdd ( x , y , z , vx , vy , vz , m ) :
7- _particles . append (( x , y , z , vx , vy , vz , m ) )
8-
9- def save ( filename ):
10- with open ( filename , "w" ) as f :
11- for p in _particles :
12-
13- f . write ( " " . join ( str ( v ) for v in p ) + " \n " )
14-
15- def coldPlummer ( N , scale = 1.0 , mass = 1.0 ):
16- for _ in range ( N ):
17- r = scale / math .sqrt ( random . random () ** ( - 2 / 3 ) - 1 )
18- theta = math .acos ( 2 * random . random () - 1 )
19- phi = 2 * math .pi * random . random ( )
20-
21- x = r * math . sin ( theta ) * math . cos ( phi )
22- y = r * math . sin ( theta ) * math . sin ( phi )
23- z = r * math . cos ( theta )
24-
25- particleAdd ( x , y , z , 0 , 0 , 0 , mass / N )
26-
27- def disk ( N , radius = 10.0 , mass = 1.0 , thickness = 0.1 ):
28- """
29- Generates a simple equilibrium-ish exponential disk galaxy.
30- - N: number of particles
31- - radius: scale length of the disk
32- - mass: total mass of the disk
33- - thickness: vertical Gaussian thickness
34- """
35-
36- M = mass
37- for _ in range ( N ):
38- # Sample radius from exponential disk: p(r) ~ r * exp(-r/R)
39- u = random . random ( )
40- r = - radius * math . log ( 1 - u ) # inverse CDF
41-
42- # Random angle
43- phi = 2 * math . pi * random . random ()
44-
45- # Position in the plane
46- x = r * math . cos ( phi )
47- y = r * math .sin (phi )
48-
49- # Vertical position (Gaussian)
50- z = random . gauss ( 0 , thickness )
51-
52- # Circular velocity: v = sqrt(GM(r)/r)
53- # Here G = 1 in your units, and M(r) ~ M * (1 - exp(-r/R)*(1+r/R))
54- # This is a rough approximation but stable enough for NEXT.
55- enclosed = M * ( 1 - math .exp ( - r / radius ) * ( 1 + r / radius ))
56- v = math . sqrt ( enclosed / ( r + 1e-6 ))
57-
58- # Tangential velocity
59- vx = - v * math .sin (phi )
60- vy = v * math . cos ( phi )
61-
62- # Small vertical velocity dispersion
63- vz = random . gauss ( 0 , 0.05 * v )
64-
65- particleAdd ( x , y , z , vx , vy , vz , mass / N )
66-
1+ import random
2+ import math
3+
4+ def save ( filename , particles ):
5+ with open ( filename , "w" ) as f :
6+ for p in particles :
7+ f . write ( " " . join ( str ( v ) for v in p ) + " \n " )
8+
9+
10+ def coldPlummer ( N , scale = 1.0 , mass = 1.0 ) :
11+ particles = []
12+ for _ in range ( N ):
13+ r = scale / math . sqrt ( random . random () ** ( - 2 / 3 ) - 1 )
14+ theta = math . acos ( 2 * random . random () - 1 )
15+ phi = 2 * math . pi * random . random ()
16+
17+ x = r * math .sin ( theta ) * math . cos ( phi )
18+ y = r * math .sin ( theta ) * math . sin ( phi )
19+ z = r * math .cos ( theta )
20+
21+ particles . append (( x , y , z , 0 , 0 , 0 , mass / N ) )
22+
23+ return particles
24+
25+
26+ def disk ( N , radius = 10.0 , mass = 1.0 , thickness = 0.1 ):
27+ """
28+ Generates a simple equilibrium-ish exponential disk galaxy.
29+ - N: number of particles
30+ - radius: scale length of the disk
31+ - mass: total mass of the disk
32+ - thickness: vertical Gaussian thickness
33+ """
34+
35+ particles = []
36+ M = mass
37+
38+ for _ in range ( N ):
39+ # Sample radius from exponential disk: p(r) ~ r * exp(-r/R )
40+ u = random . random ()
41+ r = - radius * math . log ( 1 - u )
42+
43+ # Random angle
44+ phi = 2 * math . pi * random . random ()
45+
46+ # Position in the plane
47+ x = r * math .cos (phi )
48+ y = r * math . sin ( phi )
49+
50+ # Vertical position (Gaussian )
51+ z = random . gauss ( 0 , thickness )
52+
53+ # Circular velocity
54+ enclosed = M * ( 1 - math . exp ( - r / radius ) * ( 1 + r / radius ))
55+ v = math .sqrt ( enclosed / ( r + 1e-6 ))
56+
57+ # Tangential velocity
58+ vx = - v * math . sin ( phi )
59+ vy = v * math .cos (phi )
60+
61+ # Small vertical velocity dispersion
62+ vz = random . gauss ( 0 , 0.05 * v )
63+
64+ particles . append (( x , y , z , vx , vy , vz , mass / N ))
65+
66+ return particles
0 commit comments