deriv.C 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Daniel Llorens - 2015
  2. // Adapted from blitz++/examples/deriv.cpp
  3. #include "ra/operators.H"
  4. #include "ra/io.H"
  5. using std::cout; using std::endl; using std::flush;
  6. using Array1D = ra::Big<double, 1>;
  7. // "index placeholder" which represents the array index for the first axis in a multidimensional expression.
  8. constexpr auto i = ra::_0;
  9. int main()
  10. {
  11. // In this example, the function cos(x)^2 and its second derivative
  12. // 2 (sin(x)^2 - cos(x)^2) are sampled over the range [0,1).
  13. // The second derivative is approximated numerically using a
  14. // [ 1 -2 1 ] mask, and the approximation error is computed.
  15. const int numSamples = 100; // Number of samples
  16. double delta = 1. / numSamples; // Spacing of samples
  17. ra::Iota<int> R(numSamples); // Index set of the vector
  18. // Sample the function y = cos(x)^2 over [0,1)
  19. //
  20. // The initialization for y (below) will be translated via expression
  21. // templates into something of the flavour
  22. //
  23. // for (unsigned i=0; i < 99; ++i)
  24. // {
  25. // double _t1 = cos(i * delta);
  26. // y[i] = _t1 * _t1;
  27. // }
  28. // [ra] You need to give a size at construction because 'i' doesn't provide one; you could do instead
  29. // Array1D y = sqr(cos(R * delta));
  30. // since R does have a defined size.
  31. Array1D y({numSamples}, sqr(cos(i * delta)));
  32. // Sample the exact second derivative
  33. Array1D y2exact({numSamples}, 2.0 * (sqr(sin(i * delta)) - sqr(cos(i * delta))));
  34. // Approximate the 2nd derivative using a [ 1 -2 1 ] mask
  35. // We can only apply this mask to the elements 1 .. 98, since
  36. // we need one element on either side to apply the mask.
  37. // I-1 etc. are beatable if RA_OPTIMIZE is true.
  38. ra::Iota<int> I(numSamples-2, 1);
  39. Array1D y2({numSamples}, ra::unspecified);
  40. y2(I) = (y(I-1) - 2 * y(I) + y(I+1)) / (delta*delta);
  41. // The above difference equation will be transformed into
  42. // something along the lines of
  43. //
  44. // double _t2 = delta*delta;
  45. // for (int i=1; i < 99; ++i)
  46. // y2[i] = (y[i-1] - 2 * y[i] + y[i+1]) / _t2;
  47. // Now calculate the root mean square approximation error:
  48. // [ra] TODO don't have mean() yet
  49. double error = sqrt(sum(sqr(y2(I) - y2exact(I)))/I.size());
  50. // Display a few elements from the vectors.
  51. // This range constructor means elements 1 to 91 in increments
  52. // of 15.
  53. ra::Iota<int> displayRange(7, 1, 15);
  54. cout << "Exact derivative:" << y2exact(displayRange) << endl
  55. << "Approximation: " << y2(displayRange) << endl
  56. << "RMS Error: " << error << endl;
  57. return 0;
  58. }