n_body.pp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. { The Computer Language Shootout
  2. http://shootout.alioth.debian.org
  3. contributed by Ian Osgood,
  4. modified by Florian Klaempfl
  5. modified by Ales Katona
  6. modified by Vincent Snijders
  7. }
  8. {$mode objfpc}
  9. program n_body;
  10. uses Math;
  11. type
  12. Body = record
  13. x, y, z,
  14. vx, vy, vz,
  15. mass : double;
  16. end;
  17. PBody = ^Body;
  18. const pi = 3.141592653589793;
  19. solarMass = 4 * sqr(pi);
  20. daysPerYear = 365.24;
  21. type
  22. tbody = array[1..5] of Body;
  23. const b : tbody = (
  24. { Sun }
  25. ( x:0; y:0; z:0; vx:0; vy:0; vz:0; mass: solarMass ),
  26. { Jupiter }
  27. ( x: 4.84143144246472090e+00;
  28. y: -1.16032004402742839e+00;
  29. z: -1.03622044471123109e-01;
  30. vx: 1.66007664274403694e-03 * daysPerYear;
  31. vy: 7.69901118419740425e-03 * daysPerYear;
  32. vz: -6.90460016972063023e-05 * daysPerYear;
  33. mass: 9.54791938424326609e-04 * solarMass ),
  34. { Saturn }
  35. ( x: 8.34336671824457987e+00;
  36. y: 4.12479856412430479e+00;
  37. z: -4.03523417114321381e-01;
  38. vx: -2.76742510726862411e-03 * daysPerYear;
  39. vy: 4.99852801234917238e-03 * daysPerYear;
  40. vz: 2.30417297573763929e-05 * daysPerYear;
  41. mass: 2.85885980666130812e-04 * solarMass ),
  42. { Uranus }
  43. ( x: 1.28943695621391310e+01;
  44. y: -1.51111514016986312e+01;
  45. z: -2.23307578892655734e-01;
  46. vx: 2.96460137564761618e-03 * daysPerYear;
  47. vy: 2.37847173959480950e-03 * daysPerYear;
  48. vz: -2.96589568540237556e-05 * daysPerYear;
  49. mass: 4.36624404335156298e-05 * solarMass ),
  50. { Neptune }
  51. ( x: 1.53796971148509165e+01;
  52. y: -2.59193146099879641e+01;
  53. z: 1.79258772950371181e-01;
  54. vx: 2.68067772490389322e-03 * daysPerYear;
  55. vy: 1.62824170038242295e-03 * daysPerYear;
  56. vz: -9.51592254519715870e-05 * daysPerYear;
  57. mass: 5.15138902046611451e-05 * solarMass )
  58. );
  59. procedure offsetMomentum;
  60. var px,py,pz : double;
  61. i : integer;
  62. begin
  63. px:=0.0; py:=0.0; pz:=0.0;
  64. for i := low(b)+1 to high(b) do
  65. with b[i] do
  66. begin
  67. px := px - vx * mass;
  68. py := py - vy * mass;
  69. pz := pz - vz * mass;
  70. end;
  71. b[low(b)].vx := px / solarMass;
  72. b[low(b)].vy := py / solarMass;
  73. b[low(b)].vz := pz / solarMass;
  74. end;
  75. function distance(i,j : integer) : double;
  76. begin
  77. distance := sqrt(sqr(b[i].x-b[j].x) + sqr(b[i].y-b[j].y) +
  78. sqr(b[i].z-b[j].z));
  79. end;
  80. function energy : double;
  81. var
  82. i,j : integer;
  83. begin
  84. result := 0.0;
  85. for i := low(b) to high(b) do
  86. with b[i] do
  87. begin
  88. result := result + mass * (sqr(vx) + sqr(vy) + sqr(vz)) / 2;
  89. for j := i+1 to high(b) do
  90. result := result - mass * b[j].mass / distance(i,j);
  91. end;
  92. end;
  93. procedure advance(dt : double);
  94. var i,j : integer;
  95. dx,dy,dz,mag : double;
  96. bi,bj : PBody;
  97. begin
  98. bi:=@b[low(b)];
  99. for i := low(b) to high(b)-1 do begin
  100. bj := bi;
  101. for j := i+1 to high(b) do
  102. begin
  103. inc(bj);
  104. dx := bi^.x - bj^.x;
  105. dy := bi^.y - bj^.y;
  106. dz := bi^.z - bj^.z;
  107. mag := dt / (sqrt(sqr(dx)+sqr(dy)+sqr(dz))*(sqr(dx)+sqr(dy)+sqr(dz)));
  108. bi^.vx := bi^.vx - dx * bj^.mass * mag;
  109. bi^.vy := bi^.vy - dy * bj^.mass * mag;
  110. bi^.vz := bi^.vz - dz * bj^.mass * mag;
  111. bj^.vx := bj^.vx + dx * bi^.mass * mag;
  112. bj^.vy := bj^.vy + dy * bi^.mass * mag;
  113. bj^.vz := bj^.vz + dz * bi^.mass * mag;
  114. end;
  115. inc(bi);
  116. end;
  117. bi:=@b[low(b)];
  118. for i := low(b) to high(b) do begin
  119. with bi^ do
  120. begin
  121. x := x + dt * vx;
  122. y := y + dt * vy;
  123. z := z + dt * vz;
  124. end;
  125. inc(bi);
  126. end;
  127. end;
  128. var i : integer;
  129. n : Integer;
  130. begin
  131. SetPrecisionMode(pmDouble);
  132. offsetMomentum;
  133. writeln(energy:0:9);
  134. Val(ParamStr(1), n, i);
  135. for i := 1 to n do advance(0.01);
  136. writeln(energy:0:9);
  137. end.