newton.C 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // (c) Daniel Llorens - 2016
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. // After Chaitin1986, p. 14. Attempt at straight translation from APL.
  7. // Newton -- Orbits
  8. #include <iostream>
  9. #include <chrono>
  10. #include <thread>
  11. #include "ra/io.H"
  12. #include "ra/operators.H"
  13. #include "ra/format.H"
  14. using real = double;
  15. using real3 = ra::Small<real, 3>;
  16. using int3 = ra::Small<int, 3>;
  17. template <class T, int rank> using array = ra::Big<T, rank>;
  18. int main()
  19. {
  20. constexpr real G = 6.674e-11;
  21. real delta = 50;
  22. int bodies = 2;
  23. array<real, 1> m = { 6.e24, 10. };
  24. array<char, 1> c = { 'E', '*' };
  25. array<real, 2> x({bodies, 3}, { 0, 0, 0, 1e7, 0, 0 });
  26. array<real, 2> v({bodies, 3}, { 0, 0, 0, 0, 6e3, 0 });
  27. auto force = [&m, &x](int i, int j) -> real3
  28. {
  29. if (i==j) {
  30. return 0.;
  31. } else {
  32. real3 deltax = x(j)-x(i);
  33. return deltax*(G*m(i)*m(j) / pow(sum(deltax*deltax), 3/2.));
  34. }
  35. };
  36. array<char, 2> orbit({50, 50}, ' ');
  37. auto draw = [&orbit, &c](auto && x, auto && t)
  38. {
  39. auto mapc = [](real x) { return max(0, min(49, int(round(25+x/5e5)))); };
  40. // 1. TODO we still can't use iter<1> on an ET.
  41. array<int, 2> xi = map(mapc, x);
  42. at(orbit, iter<1>(xi(ra::all, ra::iota(2)))) = c;
  43. // 2. alternative w/o temps
  44. for_each([&orbit, &mapc] (auto && x, auto && c) { orbit(mapc(x(0)), mapc(x(1))) = c; },
  45. iter<1>(x), c);
  46. std::cout << "TIME IN HOURS " << (t/3600.) << " " << format_array(orbit, true, "") << "\n";
  47. };
  48. real t = 0;
  49. array<real, 3> F({bodies, bodies, 3}, 0.);
  50. array<real, 2> a({bodies, 3}, 0.);
  51. for (int step=1; step<(12*15); ++step, t+=delta) {
  52. // RHS is rank 2 so we need to match on LHS. Either of these works, but the second needs a compact last axis.
  53. // TODO ideally [F = from(force, ra::iota(2), ra::iota(2));] would work #nestedarrays
  54. // for_each([](auto && x, auto && y) { x = y; }, iter<1>(F), from(force, ra::iota(2), ra::iota(2)));
  55. ra::explode<real3>(F) = from(force, ra::iota(bodies), ra::iota(bodies));
  56. // match axes a[0, 1] with F[0, 2]; accumulate on F[1]. TODO proper reductions.
  57. a = 0.;
  58. a += transpose<0, 2, 1>(F) / m;
  59. v += a*delta;
  60. x += v*delta;
  61. draw(x, t);
  62. std::this_thread::sleep_for(std::chrono::milliseconds(5));
  63. }
  64. return 0;
  65. }