nbody.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "Common.h"
  5. #define pi 3.141592653589793
  6. #define solar_mass (4 * pi * pi)
  7. #define days_per_year 365.24
  8. struct planet {
  9. double x, y, z;
  10. double vx, vy, vz;
  11. double mass;
  12. };
  13. void advance(int nbodies, struct planet * bodies, double dt)
  14. {
  15. int i, j;
  16. for (i = 0; i < nbodies; i++) {
  17. struct planet * b = &(bodies[i]);
  18. for (j = i + 1; j < nbodies; j++) {
  19. struct planet * b2 = &(bodies[j]);
  20. double dx = b->x - b2->x;
  21. double dy = b->y - b2->y;
  22. double dz = b->z - b2->z;
  23. double distance = sqrt(dx * dx + dy * dy + dz * dz);
  24. double mag = dt / (distance * distance * distance);
  25. b->vx -= dx * b2->mass * mag;
  26. b->vy -= dy * b2->mass * mag;
  27. b->vz -= dz * b2->mass * mag;
  28. b2->vx += dx * b->mass * mag;
  29. b2->vy += dy * b->mass * mag;
  30. b2->vz += dz * b->mass * mag;
  31. }
  32. }
  33. for (i = 0; i < nbodies; i++) {
  34. struct planet * b = &(bodies[i]);
  35. b->x += dt * b->vx;
  36. b->y += dt * b->vy;
  37. b->z += dt * b->vz;
  38. }
  39. }
  40. double energy(int nbodies, struct planet * bodies)
  41. {
  42. double e;
  43. int i, j;
  44. e = 0.0;
  45. for (i = 0; i < nbodies; i++) {
  46. struct planet * b = &(bodies[i]);
  47. e += 0.5 * b->mass * (b->vx * b->vx + b->vy * b->vy + b->vz * b->vz);
  48. for (j = i + 1; j < nbodies; j++) {
  49. struct planet * b2 = &(bodies[j]);
  50. double dx = b->x - b2->x;
  51. double dy = b->y - b2->y;
  52. double dz = b->z - b2->z;
  53. double distance = sqrt(dx * dx + dy * dy + dz * dz);
  54. e -= (b->mass * b2->mass) / distance;
  55. }
  56. }
  57. return e;
  58. }
  59. void offset_momentum(int nbodies, struct planet * bodies)
  60. {
  61. double px = 0.0, py = 0.0, pz = 0.0;
  62. int i;
  63. for (i = 0; i < nbodies; i++) {
  64. px += bodies[i].vx * bodies[i].mass;
  65. py += bodies[i].vy * bodies[i].mass;
  66. pz += bodies[i].vz * bodies[i].mass;
  67. }
  68. bodies[0].vx = -px / solar_mass;
  69. bodies[0].vy = -py / solar_mass;
  70. bodies[0].vz = -pz / solar_mass;
  71. }
  72. #define NBODIES 5
  73. struct planet orig_bodies[NBODIES] = {
  74. { /* sun */
  75. 0, 0, 0, 0, 0, 0, solar_mass
  76. },
  77. { /* jupiter */
  78. 4.84143144246472090e+00,
  79. -1.16032004402742839e+00,
  80. -1.03622044471123109e-01,
  81. 1.66007664274403694e-03 * days_per_year,
  82. 7.69901118419740425e-03 * days_per_year,
  83. -6.90460016972063023e-05 * days_per_year,
  84. 9.54791938424326609e-04 * solar_mass
  85. },
  86. { /* saturn */
  87. 8.34336671824457987e+00,
  88. 4.12479856412430479e+00,
  89. -4.03523417114321381e-01,
  90. -2.76742510726862411e-03 * days_per_year,
  91. 4.99852801234917238e-03 * days_per_year,
  92. 2.30417297573763929e-05 * days_per_year,
  93. 2.85885980666130812e-04 * solar_mass
  94. },
  95. { /* uranus */
  96. 1.28943695621391310e+01,
  97. -1.51111514016986312e+01,
  98. -2.23307578892655734e-01,
  99. 2.96460137564761618e-03 * days_per_year,
  100. 2.37847173959480950e-03 * days_per_year,
  101. -2.96589568540237556e-05 * days_per_year,
  102. 4.36624404335156298e-05 * solar_mass
  103. },
  104. { /* neptune */
  105. 1.53796971148509165e+01,
  106. -2.59193146099879641e+01,
  107. 1.79258772950371181e-01,
  108. 2.68067772490389322e-03 * days_per_year,
  109. 1.62824170038242295e-03 * days_per_year,
  110. -9.51592254519715870e-05 * days_per_year,
  111. 5.15138902046611451e-05 * solar_mass
  112. }
  113. };
  114. struct planet bodies[NBODIES];
  115. void NBody(int n)
  116. {
  117. int i;
  118. memcpy(bodies, orig_bodies, sizeof(orig_bodies));
  119. offset_momentum(NBODIES, bodies);
  120. printf("%.9f\n", energy(NBODIES, bodies));
  121. for (i = 1; i <= n; i++)
  122. advance(NBODIES, bodies, 0.01);
  123. printf("%.9f\n", energy(NBODIES, bodies));
  124. }