laplace2d.C 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // (c) Daniel Llorens - 2017
  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. /// @file laplace2d.C
  7. /// @brief Solve Poisson equation in a rectangle, with linear elements.
  8. // Adapted from lsolver/laplace2d.C by Christian Badura, 1998/05.
  9. // FIXME mult() benchmarks well against the Cish original, but cghs dominates
  10. // the computation and we do much worse against BLAS. Clearly I need to
  11. // benchmark the basic stuff against BLAS.
  12. #include "ra/operators.H"
  13. #include "ra/io.H"
  14. #include "ra/test.H"
  15. #include "examples/cghs.H"
  16. #include "ra/bench.H"
  17. using std::cout; using std::endl; using ra::PI;
  18. Benchmark::clock::duration tmul(0);
  19. struct StiffMat { double h; };
  20. template <class V, class W>
  21. void mult(StiffMat const & A, V const & v, W & w)
  22. {
  23. auto t0 = Benchmark::clock::now();
  24. auto i = ra::iota(v.size(0)-2, 1);
  25. auto j = ra::iota(v.size(1)-2, 1);
  26. w(i, j) = 4*v(i, j) -v(i-1, j) -v(i, j-1) -v(i+1, j) -v(i, j+1);
  27. tmul += (Benchmark::clock::now()-t0);
  28. }
  29. struct MassMat { double h; };
  30. template <class V, class W>
  31. void mult(MassMat const & M, V const & v, W & w)
  32. {
  33. auto t0 = Benchmark::clock::now();
  34. auto i = ra::iota(v.size(0)-2, 1);
  35. auto j = ra::iota(v.size(1)-2, 1);
  36. w(i, j) = sqrm(M.h) * (v(i, j)/2. + (v(i-1, j) + v(i, j-1) + v(i+1, j) + v(i, j+1) + v(i+1, j+1) + v(i-1, j-1))/12.);
  37. tmul += Benchmark::clock::now()-t0;
  38. }
  39. // problem: -laplace u=f, with solution g
  40. inline double f(double x, double y)
  41. {
  42. return 8.*PI*PI*sin(2.*PI*x)*sin(2.*PI*y);
  43. }
  44. inline double g(double x, double y)
  45. {
  46. return sin(2.*PI*x)*sin(2.*PI*y);
  47. }
  48. int main(int argc, char *argv[])
  49. {
  50. TestRecorder tr(std::cout);
  51. auto t0 = Benchmark::clock::now();
  52. int N = 50;
  53. double EPS = 1e-5;
  54. double h = 1./N;
  55. ra::Big<double, 2> v({N+1, N+1}, 0.), u({N+1, N+1}, 0.), w({N+1, N+1}, 0.), b({N+1, N+1}, 0.);
  56. auto i = ra::iota(N-1, 1);
  57. auto j = ra::iota(N-1, 1);
  58. auto ih = ra::iota(N-1, h, h);
  59. auto jh = ra::iota(N-1, h, h);
  60. v(i, j) = from(g, ih, jh);
  61. w(i, j) = from(f, ih, jh);
  62. StiffMat sm { h };
  63. MassMat mm { h };
  64. mult(mm, w, b);
  65. ra::Big<double, 3> work({3, N+1, N+1}, ra::unspecified);
  66. int its = cghs(sm, b, u, work, EPS);
  67. double max = amax(abs(u-v));
  68. auto ttot = Benchmark::clock::now()-t0;
  69. cout << "total time " << Benchmark::toseconds(ttot)/1e-3 << " " << "ms" << endl;
  70. cout << "mul time " << Benchmark::toseconds(ttot)/1e-3 << " " << "ms" << endl;
  71. tr.info("max ", max).test_le(max, 0.00463);
  72. tr.info("its ", its).test_le(its, 67);
  73. return tr.summary();
  74. }