SPH
Functional.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "math/rng/Rng.h"
11 
13 
17 template <typename TFunctor>
18 INLINE Float integrate(const Interval range, const TFunctor& functor) {
19  const Size N = 1000;
20  const Float h = range.size() / N;
21  double result = functor((Float)range.lower()) + functor((Float)range.upper());
22  for (Size j = 1; j < N; ++j) {
23  const Float x = (Float)range.lower() + j * h;
24  if (j % 2 == 0) {
25  result += 2._f * functor(x);
26  } else {
27  result += 4._f * functor(x);
28  }
29  }
30  return Float(result * h / 3._f);
31 }
32 
33 
35 template <typename TRng = UniformRng, typename TInternal = double>
36 class Integrator : public Noncopyable {
37 private:
38  const IDomain& domain;
39  TRng rng;
40 
41  static constexpr uint chunk = 100;
42 
43 public:
45  Integrator(const IDomain& domain)
46  : domain(domain) {}
47 
48  Integrator(IDomain&& domain) = delete;
49 
53  template <typename TFunctor>
54  Float integrate(TFunctor&& f, const Float targetError = 0.001_f) {
55  double sum = 0.;
56  double sumSqr = 0.;
57  double errorSqr = sqr(targetError);
58  Size n = 0;
60  Array<Size> inside;
61  Box box = domain.getBoundingBox();
62  while (true) {
63  for (Size i = 0; i < chunk; ++i) {
64  // dimensionless vector
65  const Vector q(rng(0), rng(1), rng(2));
66  // vector properly scaled and moved
67  const Vector v = box.lower() + q * box.size();
68  buffer[i] = v;
69  }
70  inside.clear();
71  domain.getSubset(buffer, inside, SubsetType::INSIDE);
72  for (Size i : inside) {
73  const double x = (double)f(buffer[i]);
74  sum += x;
75  sumSqr += x * x;
76  n++;
77  }
78  const double m = double(n);
79  if (m * sumSqr - sum * sum < m * m * errorSqr * sumSqr) {
80  return Float(sum / m) * domain.getVolume();
81  }
82  }
83  }
84 };
85 
90 template <typename TFunctor>
91 INLINE Optional<Float> getRoot(const Interval& range, const Float eps, const TFunctor& functor) {
92  Interval r = range;
93  if (functor(r.lower()) * functor(r.upper()) > 0._f) { // same sign
94  return NOTHING;
95  }
96  while (r.size() > eps * range.size()) {
97  Float x = r.center();
98  if (functor(x) * functor(r.upper()) > 0._f) {
99  r = Interval(r.lower(), x);
100  } else {
101  r = Interval(x, r.upper());
102  }
103  }
104  return r.center();
105 }
106 
110 template <typename TFunctor>
111 INLINE bool isContinuous(const Interval& range, const Float delta, const Float eps, const TFunctor& functor) {
112  Float y1 = functor(range.lower());
113  for (Float x = range.lower(); x <= range.upper(); x += delta) {
114  const Float y2 = functor(x);
115  if (abs(y1 - y2) > eps) {
116  return false;
117  }
118  y1 = y2;
119  }
120  return true;
121 }
122 
Simplified implementation of std::unique_ptr, using only default deleter.
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Object defining computational domain.
@ INSIDE
Marks all vectors inside of the domain.
INLINE Optional< Float > getRoot(const Interval &range, const Float eps, const TFunctor &functor)
Returns a root of a R->R function on given range.
Definition: Functional.h:91
INLINE bool isContinuous(const Interval &range, const Float delta, const Float eps, const TFunctor &functor)
Checks if the given R->R function is continuous in given interval.
Definition: Functional.h:111
NAMESPACE_SPH_BEGIN INLINE Float integrate(const Interval range, const TFunctor &functor)
Integrates a one-dimensional function using Simpson's rule.
Definition: Functional.h:18
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
INLINE auto abs(const T &f)
Definition: MathUtils.h:276
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
const NothingType NOTHING
Definition: Optional.h:16
Random number generators.
constexpr int N
void clear()
Removes all elements from the array, but does NOT release the memory.
Definition: Array.h:434
Helper object defining three-dimensional interval (box).
Definition: Box.h:17
INLINE const Vector & lower() const
Returns lower bounds of the box.
Definition: Box.h:82
INLINE Vector size() const
Returns box dimensions.
Definition: Box.h:106
Base class for computational domains.
Definition: Domain.h:29
virtual void getSubset(ArrayView< const Vector > vs, Array< Size > &output, const SubsetType type) const =0
Returns an array of indices, marking vectors with given property by their index.
virtual Box getBoundingBox() const =0
Returns the bounding box of the domain.
virtual Float getVolume() const =0
Returns the total volume of the domain.
Object for integrating a generic three-dimensional scalar function.
Definition: Functional.h:36
Integrator(const IDomain &domain)
Constructs an integrator given the domain of integration.
Definition: Functional.h:45
Float integrate(TFunctor &&f, const Float targetError=0.001_f)
Integrates a function.
Definition: Functional.h:54
Integrator(IDomain &&domain)=delete
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
INLINE Float lower() const
Returns lower bound of the interval.
Definition: Interval.h:74
INLINE Float upper() const
Returns upper bound of the interval.
Definition: Interval.h:79
INLINE Float center() const
Returns the center of the interval.
Definition: Interval.h:84
INLINE Float size() const
Returns the size of the interval.
Definition: Interval.h:89
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
constexpr Size sum()
Definition: Multipole.h:31
Object with deleted copy constructor and copy operator.
Definition: Object.h:54