deriv.C 2.7 KB

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