newton.cc 2.6 KB

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