Gobelijn API documentation  - generated for commit a0cbea7
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros Pages
AdaptiveQuadrature.h
Go to the documentation of this file.
1 #pragma once
2 
9 #include "AQ_Util.h"
10 #include "CellCountViolation.h"
11 #include "Convergence.h"
12 
13 #include <cmath>
14 #include <exception>
15 #include <iostream>
16 #include <stack>
17 #include <tuple>
18 
19 namespace UA_CoMP {
20 namespace Num {
21 
23 template <typename T>
24 class AQRule1 : public T
25 {
26 };
27 
29 template <typename T>
30 class AQRule2 : public T
31 {
32 };
33 
40 template <typename Rule>
41 class Bisector : public Rule
42 {
43 public:
45  template <typename Ftor>
46  static typename Ftor::result_type sum(typename Ftor::argument_type l, typename Ftor::argument_type d,
47  Ftor const& f)
48  {
50 
51  Arg const h = static_cast<Arg>(0.5) * d;
52  Arg const m = l + h;
53  return Rule::sum(l, h, f) + Rule::sum(m, h, f);
54  }
55 };
56 
123 template <typename QuadRule1, typename QuadRule2 = Bisector<QuadRule1>, typename ConvergencePolicy = ComboDifference,
124  typename CellCountPolicy = OnViolationThrow>
125 class AdaptiveQuadrature : public AQRule1<QuadRule1>,
126  public AQRule2<QuadRule2>,
127  public ConvergencePolicy,
128  public CellCountPolicy
129 {
130 public:
133 
137  AdaptiveQuadrature(double convergenceTolerance, unsigned int initialCellCount, unsigned int cellCountLimit)
138  : fConvergenceTolerance(convergenceTolerance), fInitialCellCount(initialCellCount),
139  fCellCountLimit(cellCountLimit)
140  {
141  }
142 
143  // The implicit essential operators are fine for now.
144 
150  AQRule1<QuadRule1>& rule1() { return *this; }
151 
157  AQRule2<QuadRule2>& rule2() { return *this; }
158 
159  // Defined below.
160  template <typename Integrand>
161  std::tuple<bool, typename Integrand::result_type, typename Integrand::result_type, unsigned int> evaluate(
162  typename Integrand::argument_type l, typename Integrand::argument_type r, Integrand ftor) const;
163 
164  // Defined below
165  template <typename Integrand>
166  typename Integrand::result_type operator()(typename Integrand::argument_type l,
167  typename Integrand::argument_type r, Integrand ftor) const;
168 
171 
173  unsigned int getInitialCellCount() const { return fInitialCellCount; }
174 
176  unsigned int getCellCountLimit() const { return fCellCountLimit; }
177 
180 
182  void setInitialCellCount(unsigned int i) { fInitialCellCount = i; }
183 
185  void setCellCountLimit(unsigned int i) { fCellCountLimit = i; }
186 
187 private:
189  unsigned int fInitialCellCount;
190  unsigned int fCellCountLimit;
191 };
192 
202 template <typename QuadRule1, typename QuadRule2, typename ConvergencePolicy, typename CellCountPolicy>
203 template <typename Integrand>
204 std::tuple<bool, typename Integrand::result_type, typename Integrand::result_type, unsigned int>
206  typename Integrand::argument_type l, typename Integrand::argument_type r, Integrand ftor) const
207 {
208  using std::make_pair;
209  using std::pair;
210  using std::stack;
211 
214 
215  // Stack of integration cells with each cell (left endpoint, size)
216  stack<pair<Arg, Arg>> divStack;
217  Res cumulateSum1;
218  Res cumulateSum2;
219  unsigned int cellCounter;
220  bool NoMoreCells = false;
221 
222  // Initialize with the required number of cells on the stack,
223  // set the cumulative sums (of rule1 and rule2) to zero and
224  // initialize the cell count.
225  {
226  Arg const d = (r - l) / static_cast<Arg>(fInitialCellCount);
227  for (Arg b = l; b < r - 0.5 * d; b += d) {
228  divStack.push(make_pair(b, d));
229  }
230  cumulateSum1 = 0.0;
231  cumulateSum2 = 0.0;
232  cellCounter = fInitialCellCount;
233  }
234 
235  // Work that stack until it is empty.
236  while (!divStack.empty()) {
237  // Look at the top cell and determine sums for it.
238  Arg const b = divStack.top().first;
239  Arg const d = divStack.top().second;
240  Res const sum1 = first_rule::sum(b, d, ftor);
241  Res const sum2 = second_rule::sum(b, d, ftor);
242  // If the use of the nested types does not work, then:
243  // Res const sum1 = Rule1<QuadRule1>::sum(b, d, ftor);
244  // Res const sum2 = Rule2<QuadRule2>::sum(b, d, ftor);
245 
246  // If the sums for both rules agree, or if we are not allowed to
247  // create new cells, we are done with this cell. Add its contribution
248  // to the cumulatve sums. If allowed (cell count violation does not
249  // throw exception) we continue summing on the existing cells to obtain
250  // at least a rough estimate of the integral.
251  if ((ConvergencePolicy::evaluate(sum1, sum2) < fConvergenceTolerance) || NoMoreCells) {
252  cumulateSum1 += sum1;
253  cumulateSum2 += sum2;
254  divStack.pop();
255  } else {
256  // Executing this block increases the cellCount; check that against the
257  // policy.
258  // Not executing leaves the current cell on stack to be processed, as
259  // should be.
260  NoMoreCells = !CellCountPolicy::check(cellCounter + 1 <= fCellCountLimit);
261  if (!NoMoreCells) {
262  divStack.pop();
263  Arg const dN = 0.5 * d;
264  divStack.push(make_pair(b + dN, dN));
265  divStack.push(make_pair(b, dN));
266  ++cellCounter;
267  }
268  }
269  }
270 
271  bool const status = (ConvergencePolicy::evaluate(cumulateSum1, cumulateSum2) < fConvergenceTolerance);
272  return std::make_tuple(status, cumulateSum1, cumulateSum2, cellCounter);
273 }
274 
284 template <typename QuadRule1, typename QuadRule2, typename ConvergencePolicy, typename ErrorPolicy>
285 template <typename Integrand>
287 operator()(typename Integrand::argument_type l, typename Integrand::argument_type r, Integrand ftor) const
288 {
289  return std::get<2>(evaluate(l, r, ftor));
290 }
291 
292 } // namespace Num
293 } // namespace UA_CoMP
The AdaptiveQuadrature is a host class with policy classes QuadRule1, QuadRule2, ErrorPolicy and Conv...
void setCellCountLimit(unsigned int i)
Set cell count limit.
Used to disambiguate rules in AdaptiveQuadrature.
double getConvergenceTolerance() const
Return the convergence tolerance.
Used to disambiguate rules in AdaptiveQuadrature.
Given a quadrature rule, a new rule is generated that consists of applying the original rule on both ...
AQRule1< QuadRule1 > & rule1()
Return a reference to the first sum rule subobject.
void setConvergenceTolerance(double x)
Set the convergence tolerance.
Predefined policies for handling a cell count violation.
Template parameter provides policy for managing convergence criterion in AdaptiveQuadrature.
Utilities for the implementation of the Adaptive Quadrature.
void setInitialCellCount(unsigned int i)
Set initial cell count.
Integrand::result_type operator()(typename Integrand::argument_type l, typename Integrand::argument_type r, Integrand ftor) const
Simplified version of the evaluate member function, returns only second sum value.
static Ftor::result_type sum(typename Ftor::argument_type l, typename Ftor::argument_type d, Ftor const &f)
Execute the rule on the bisected cell.
unsigned int getCellCountLimit() const
Return the cell count limit.
unsigned int getInitialCellCount() const
Return the initial cell count.
typename std::remove_cv< typename std::remove_reference< T >::type >::type type
Definition: AQ_Util.h:18
Template parameter provides policy for managing cell count in AdaptiveQuadrature. ...
C::value_type sum(C const &c)
Definition: sum1.cpp:26
AdaptiveQuadrature(double convergenceTolerance, unsigned int initialCellCount, unsigned int cellCountLimit)
Constructor initializes everything.
Predefined convergence policies for the AdaptiveQuadrature template.
AQRule2< QuadRule2 > & rule2()
Return a reference to the second sum rule subobject.
std::tuple< bool, typename Integrand::result_type, typename Integrand::result_type, unsigned int > evaluate(typename Integrand::argument_type l, typename Integrand::argument_type r, Integrand ftor) const
Evaluates the quadrature for a functor based on comparing two sum rules.