Reference documentation for deal.II version 9.0.0
quadrature_lib.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/quadrature_lib.h>
17 #include <deal.II/base/geometry_info.h>
18 #include <deal.II/base/polynomial.h>
19 
20 #include <cmath>
21 #include <limits>
22 #include <algorithm>
23 #include <functional>
24 
25 
26 DEAL_II_NAMESPACE_OPEN
27 
28 
29 // please note: for a given dimension, we need the quadrature formulae
30 // for all lower dimensions as well. That is why in this file the check
31 // is for deal_II_dimension >= any_number and not for ==
32 
33 
34 
35 template <>
36 QGauss<0>::QGauss (const unsigned int)
37  :
38  // there are n_q^dim == 1
39  // points
40  Quadrature<0> (1)
41 {
42  // the single quadrature point gets unit
43  // weight
44  this->weights[0] = 1;
45 }
46 
47 
48 
49 template <>
50 QGaussLobatto<0>::QGaussLobatto (const unsigned int)
51  :
52  // there are n_q^dim == 1
53  // points
54  Quadrature<0> (1)
55 {
56  // the single quadrature point gets unit
57  // weight
58  this->weights[0] = 1;
59 }
60 
61 
62 
63 template <>
64 QGauss<1>::QGauss (const unsigned int n)
65  :
66  Quadrature<1> (n)
67 {
68  if (n == 0)
69  return;
70 
71  std::vector<long double> points
72  = Polynomials::jacobi_polynomial_roots<long double>(n, 0, 0);
73 
74  for (unsigned int i=0; i<(points.size()+1)/2; ++i)
75  {
76  this->quadrature_points[i][0] = points[i];
77  this->quadrature_points[n-i-1][0] = 1.-points[i];
78 
79  // derivative of Jacobi polynomial
80  const long double pp = 0.5*(n + 1)*Polynomials::jacobi_polynomial_value(n-1, 1, 1, points[i]);
81  const long double x = -1. + 2.*points[i];
82  const double w = 1./((1.-x*x)*pp*pp);
83  this->weights[i] = w;
84  this->weights[n-i-1] = w;
85  }
86 }
87 
88 namespace internal
89 {
90  namespace QGaussLobatto
91  {
96  long double gamma(const unsigned int n)
97  {
98  long double result = n - 1;
99  for (int i=n-2; i>1; --i)
100  result *= i;
101  return result;
102  }
103 
104 
105 
113  std::vector<long double>
114  compute_quadrature_weights(const std::vector<long double> &x,
115  const int alpha,
116  const int beta)
117  {
118  const unsigned int q = x.size();
119  std::vector<long double> w(q);
120 
121  const long double factor = std::pow(2., alpha+beta+1) *
122  gamma(alpha+q) *
123  gamma(beta+q) /
124  ((q-1)*gamma(q)*gamma(alpha+beta+q+1));
125  for (unsigned int i=0; i<q; ++i)
126  {
127  const long double s = Polynomials::jacobi_polynomial_value(q-1, alpha, beta, x[i]);
128  w[i] = factor/(s*s);
129  }
130  w[0] *= (beta + 1);
131  w[q-1] *= (alpha + 1);
132 
133  return w;
134  }
135  }
136 }
137 
138 
139 
140 template <>
141 QGaussLobatto<1>::QGaussLobatto (const unsigned int n)
142  :
143  Quadrature<1> (n)
144 {
145  Assert (n >= 2, ExcNotImplemented());
146 
147  std::vector<long double> points
148  = Polynomials::jacobi_polynomial_roots<long double>(n-2, 1, 1);
149  points.insert(points.begin(), 0);
150  points.push_back(1.);
151  std::vector<long double> w
152  = internal::QGaussLobatto::compute_quadrature_weights(points, 0, 0);
153 
154  // scale weights to the interval [0.0, 1.0]:
155  for (unsigned int i=0; i<points.size(); ++i)
156  {
157  this->quadrature_points[i][0] = points[i];
158  this->weights[i] = 0.5*w[i];
159  }
160 }
161 
162 
163 
164 template <>
166  :
167  Quadrature<1>(1)
168 {
169  this->quadrature_points[0] = Point<1>(0.5);
170  this->weights[0] = 1.0;
171 }
172 
173 
174 
175 template <>
177  :
178  Quadrature<1> (2)
179 {
180  static const double xpts[] = { 0.0, 1.0 };
181  static const double wts[] = { 0.5, 0.5 };
182 
183  for (unsigned int i=0; i<this->size(); ++i)
184  {
185  this->quadrature_points[i] = Point<1>(xpts[i]);
186  this->weights[i] = wts[i];
187  };
188 }
189 
190 
191 
192 template <>
194  :
195  Quadrature<1> (3)
196 {
197  static const double xpts[] = { 0.0, 0.5, 1.0 };
198  static const double wts[] = { 1./6., 2./3., 1./6. };
199 
200  for (unsigned int i=0; i<this->size(); ++i)
201  {
202  this->quadrature_points[i] = Point<1>(xpts[i]);
203  this->weights[i] = wts[i];
204  };
205 }
206 
207 
208 
209 template <>
211  :
212  Quadrature<1> (5)
213 {
214  static const double xpts[] = { 0.0, .25, .5, .75, 1.0 };
215  static const double wts[] = { 7./90., 32./90., 12./90., 32./90., 7./90. };
216 
217  for (unsigned int i=0; i<this->size(); ++i)
218  {
219  this->quadrature_points[i] = Point<1>(xpts[i]);
220  this->weights[i] = wts[i];
221  };
222 }
223 
224 
225 
226 template <>
228  :
229  Quadrature<1> (7)
230 {
231  static const double xpts[] = { 0.0, 1./6., 1./3., .5, 2./3., 5./6., 1.0 };
232  static const double wts[] = { 41./840., 216./840., 27./840., 272./840.,
233  27./840., 216./840., 41./840.
234  };
235 
236  for (unsigned int i=0; i<this->size(); ++i)
237  {
238  this->quadrature_points[i] = Point<1>(xpts[i]);
239  this->weights[i] = wts[i];
240  };
241 }
242 
243 
244 template <>
245 QGaussLog<1>::QGaussLog(const unsigned int n,
246  const bool revert)
247  :
248  Quadrature<1> (n)
249 {
250  std::vector<double> p = get_quadrature_points(n);
251  std::vector<double> w = get_quadrature_weights(n);
252 
253  for (unsigned int i=0; i<this->size(); ++i)
254  {
255  // Using the change of variables x=1-t, it's possible to show
256  // that int f(x)ln|1-x| = int f(1-t) ln|t|, which implies that
257  // we can use this quadrature formula also with weight ln|1-x|.
258  this->quadrature_points[i] = revert ? Point<1>(1-p[n-1-i]) : Point<1>(p[i]);
259  this->weights[i] = revert ? w[n-1-i] : w[i];
260  }
261 }
262 
263 template <>
264 std::vector<double>
265 QGaussLog<1>::get_quadrature_points(const unsigned int n)
266 {
267  std::vector<double> q_points(n);
268 
269  switch (n)
270  {
271  case 1:
272  q_points[0] = 0.3333333333333333;
273  break;
274 
275  case 2:
276  q_points[0] = 0.1120088061669761;
277  q_points[1] = 0.6022769081187381;
278  break;
279 
280  case 3:
281  q_points[0] = 0.06389079308732544;
282  q_points[1] = 0.3689970637156184;
283  q_points[2] = 0.766880303938942;
284  break;
285 
286  case 4:
287  q_points[0] = 0.04144848019938324;
288  q_points[1] = 0.2452749143206022;
289  q_points[2] = 0.5561654535602751;
290  q_points[3] = 0.848982394532986;
291  break;
292 
293  case 5:
294  q_points[0] = 0.02913447215197205;
295  q_points[1] = 0.1739772133208974;
296  q_points[2] = 0.4117025202849029;
297  q_points[3] = 0.6773141745828183;
298  q_points[4] = 0.89477136103101;
299  break;
300 
301  case 6:
302  q_points[0] = 0.02163400584411693;
303  q_points[1] = 0.1295833911549506;
304  q_points[2] = 0.3140204499147661;
305  q_points[3] = 0.5386572173517997;
306  q_points[4] = 0.7569153373774084;
307  q_points[5] = 0.922668851372116;
308  break;
309 
310 
311  case 7:
312  q_points[0] = 0.0167193554082585;
313  q_points[1] = 0.100185677915675;
314  q_points[2] = 0.2462942462079286;
315  q_points[3] = 0.4334634932570557;
316  q_points[4] = 0.6323509880476823;
317  q_points[5] = 0.81111862674023;
318  q_points[6] = 0.940848166743287;
319  break;
320 
321  case 8:
322  q_points[0] = 0.01332024416089244;
323  q_points[1] = 0.07975042901389491;
324  q_points[2] = 0.1978710293261864;
325  q_points[3] = 0.354153994351925;
326  q_points[4] = 0.5294585752348643;
327  q_points[5] = 0.7018145299391673;
328  q_points[6] = 0.849379320441094;
329  q_points[7] = 0.953326450056343;
330  break;
331 
332  case 9:
333  q_points[0] = 0.01086933608417545;
334  q_points[1] = 0.06498366633800794;
335  q_points[2] = 0.1622293980238825;
336  q_points[3] = 0.2937499039716641;
337  q_points[4] = 0.4466318819056009;
338  q_points[5] = 0.6054816627755208;
339  q_points[6] = 0.7541101371585467;
340  q_points[7] = 0.877265828834263;
341  q_points[8] = 0.96225055941096;
342  break;
343 
344  case 10:
345  q_points[0] = 0.00904263096219963;
346  q_points[1] = 0.05397126622250072;
347  q_points[2] = 0.1353118246392511;
348  q_points[3] = 0.2470524162871565;
349  q_points[4] = 0.3802125396092744;
350  q_points[5] = 0.5237923179723384;
351  q_points[6] = 0.6657752055148032;
352  q_points[7] = 0.7941904160147613;
353  q_points[8] = 0.898161091216429;
354  q_points[9] = 0.9688479887196;
355  break;
356 
357 
358  case 11:
359  q_points[0] = 0.007643941174637681;
360  q_points[1] = 0.04554182825657903;
361  q_points[2] = 0.1145222974551244;
362  q_points[3] = 0.2103785812270227;
363  q_points[4] = 0.3266955532217897;
364  q_points[5] = 0.4554532469286375;
365  q_points[6] = 0.5876483563573721;
366  q_points[7] = 0.7139638500230458;
367  q_points[8] = 0.825453217777127;
368  q_points[9] = 0.914193921640008;
369  q_points[10] = 0.973860256264123;
370  break;
371 
372  case 12:
373  q_points[0] = 0.006548722279080035;
374  q_points[1] = 0.03894680956045022;
375  q_points[2] = 0.0981502631060046;
376  q_points[3] = 0.1811385815906331;
377  q_points[4] = 0.2832200676673157;
378  q_points[5] = 0.398434435164983;
379  q_points[6] = 0.5199526267791299;
380  q_points[7] = 0.6405109167754819;
381  q_points[8] = 0.7528650118926111;
382  q_points[9] = 0.850240024421055;
383  q_points[10] = 0.926749682988251;
384  q_points[11] = 0.977756129778486;
385  break;
386 
387  default:
388  Assert(false, ExcNotImplemented());
389  break;
390  }
391 
392  return q_points;
393 }
394 
395 
396 template <>
397 std::vector<double>
398 QGaussLog<1>::get_quadrature_weights(const unsigned int n)
399 {
400  std::vector<double> quadrature_weights(n);
401 
402  switch (n)
403  {
404  case 1:
405  quadrature_weights[0] = -1.0;
406  break;
407  case 2:
408  quadrature_weights[0] = -0.7185393190303845;
409  quadrature_weights[1] = -0.2814606809696154;
410  break;
411 
412  case 3:
413  quadrature_weights[0] = -0.5134045522323634;
414  quadrature_weights[1] = -0.3919800412014877;
415  quadrature_weights[2] = -0.0946154065661483;
416  break;
417 
418  case 4:
419  quadrature_weights[0] =-0.3834640681451353;
420  quadrature_weights[1] =-0.3868753177747627;
421  quadrature_weights[2] =-0.1904351269501432;
422  quadrature_weights[3] =-0.03922548712995894;
423  break;
424 
425  case 5:
426  quadrature_weights[0] =-0.2978934717828955;
427  quadrature_weights[1] =-0.3497762265132236;
428  quadrature_weights[2] =-0.234488290044052;
429  quadrature_weights[3] =-0.0989304595166356;
430  quadrature_weights[4] =-0.01891155214319462;
431  break;
432 
433  case 6:
434  quadrature_weights[0] = -0.2387636625785478;
435  quadrature_weights[1] = -0.3082865732739458;
436  quadrature_weights[2] = -0.2453174265632108;
437  quadrature_weights[3] = -0.1420087565664786;
438  quadrature_weights[4] = -0.05545462232488041;
439  quadrature_weights[5] = -0.01016895869293513;
440  break;
441 
442 
443  case 7:
444  quadrature_weights[0] = -0.1961693894252476;
445  quadrature_weights[1] = -0.2703026442472726;
446  quadrature_weights[2] = -0.239681873007687;
447  quadrature_weights[3] = -0.1657757748104267;
448  quadrature_weights[4] = -0.0889432271377365;
449  quadrature_weights[5] = -0.03319430435645653;
450  quadrature_weights[6] = -0.005932787015162054;
451  break;
452 
453  case 8:
454  quadrature_weights[0] = -0.164416604728002;
455  quadrature_weights[1] = -0.2375256100233057;
456  quadrature_weights[2] = -0.2268419844319134;
457  quadrature_weights[3] = -0.1757540790060772;
458  quadrature_weights[4] = -0.1129240302467932;
459  quadrature_weights[5] = -0.05787221071771947;
460  quadrature_weights[6] = -0.02097907374214317;
461  quadrature_weights[7] = -0.003686407104036044;
462  break;
463 
464  case 9:
465  quadrature_weights[0] = -0.1400684387481339;
466  quadrature_weights[1] = -0.2097722052010308;
467  quadrature_weights[2] = -0.211427149896601;
468  quadrature_weights[3] = -0.1771562339380667;
469  quadrature_weights[4] = -0.1277992280331758;
470  quadrature_weights[5] = -0.07847890261203835;
471  quadrature_weights[6] = -0.0390225049841783;
472  quadrature_weights[7] = -0.01386729555074604;
473  quadrature_weights[8] = -0.002408041036090773;
474  break;
475 
476  case 10:
477  quadrature_weights[0] = -0.12095513195457;
478  quadrature_weights[1] = -0.1863635425640733;
479  quadrature_weights[2] = -0.1956608732777627;
480  quadrature_weights[3] = -0.1735771421828997;
481  quadrature_weights[4] = -0.135695672995467;
482  quadrature_weights[5] = -0.0936467585378491;
483  quadrature_weights[6] = -0.05578772735275126;
484  quadrature_weights[7] = -0.02715981089692378;
485  quadrature_weights[8] = -0.00951518260454442;
486  quadrature_weights[9] = -0.001638157633217673;
487  break;
488 
489 
490  case 11:
491  quadrature_weights[0] = -0.1056522560990997;
492  quadrature_weights[1] = -0.1665716806006314;
493  quadrature_weights[2] = -0.1805632182877528;
494  quadrature_weights[3] = -0.1672787367737502;
495  quadrature_weights[4] = -0.1386970574017174;
496  quadrature_weights[5] = -0.1038334333650771;
497  quadrature_weights[6] = -0.06953669788988512;
498  quadrature_weights[7] = -0.04054160079499477;
499  quadrature_weights[8] = -0.01943540249522013;
500  quadrature_weights[9] = -0.006737429326043388;
501  quadrature_weights[10] = -0.001152486965101561;
502  break;
503 
504  case 12:
505  quadrature_weights[0] = -0.09319269144393;
506  quadrature_weights[1] = -0.1497518275763289;
507  quadrature_weights[2] = -0.166557454364573;
508  quadrature_weights[3] = -0.1596335594369941;
509  quadrature_weights[4] = -0.1384248318647479;
510  quadrature_weights[5] = -0.1100165706360573;
511  quadrature_weights[6] = -0.07996182177673273;
512  quadrature_weights[7] = -0.0524069547809709;
513  quadrature_weights[8] = -0.03007108900074863;
514  quadrature_weights[9] = -0.01424924540252916;
515  quadrature_weights[10] = -0.004899924710875609;
516  quadrature_weights[11] = -0.000834029009809656;
517  break;
518 
519  default:
520  Assert(false, ExcNotImplemented());
521  break;
522  }
523 
524  return quadrature_weights;
525 }
526 
527 
528 template <>
529 QGaussLogR<1>::QGaussLogR(const unsigned int n,
530  const Point<1> origin,
531  const double alpha,
532  const bool factor_out_singularity) :
533  Quadrature<1>( ( (origin[0] == 0) || (origin[0] == 1) ) ?
534  (alpha == 1 ? n : 2*n ) : 4*n ),
535  fraction( ( (origin[0] == 0) || (origin[0] == 1.) ) ? 1. : origin[0] )
536 {
537  // The three quadrature formulas that make this one up. There are
538  // at most two when the origin is one of the extremes, and there is
539  // only one if the origin is one of the extremes and alpha is
540  // equal to one.
541  //
542  // If alpha is different from one, then we need a correction which
543  // is performed with a standard Gauss quadrature rule on each
544  // segment. This is not needed in the standard case where alpha is
545  // equal to one and the origin is on one of the extremes. We
546  // integrate with weight ln|(x-o)/alpha|. In the easy cases, we
547  // only need n quadrature points. In the most difficult one, we
548  // need 2*n points for the first segment, and 2*n points for the
549  // second segment.
550  QGaussLog<1> quad1(n, origin[0] != 0);
551  QGaussLog<1> quad2(n);
552  QGauss<1> quad(n);
553 
554  // Check that the origin is inside 0,1
555  Assert( (fraction >= 0) && (fraction <= 1),
556  ExcMessage("Origin is outside [0,1]."));
557 
558  // Non singular offset. This is the start of non singular quad
559  // points.
560  unsigned int ns_offset = (fraction == 1) ? n : 2*n;
561 
562  for (unsigned int i=0, j=ns_offset; i<n; ++i, ++j)
563  {
564  // The first i quadrature points are the same as quad1, and
565  // are by default singular.
566  this->quadrature_points[i] = quad1.point(i)*fraction;
567  this->weights[i] = quad1.weight(i)*fraction;
568 
569  // We need to scale with -log|fraction*alpha|
570  if ( (alpha != 1) || (fraction != 1) )
571  {
572  this->quadrature_points[j] = quad.point(i)*fraction;
573  this->weights[j] = -std::log(alpha/fraction)*quad.weight(i)*fraction;
574  }
575  // In case we need the second quadrature as well, do it now.
576  if (fraction != 1)
577  {
578  this->quadrature_points[i+n] = quad2.point(i)*(1-fraction)+Point<1>(fraction);
579  this->weights[i+n] = quad2.weight(i)*(1-fraction);
580 
581  // We need to scale with -log|fraction*alpha|
582  this->quadrature_points[j+n] = quad.point(i)*(1-fraction)+Point<1>(fraction);
583  this->weights[j+n] = -std::log(alpha/(1-fraction))*quad.weight(i)*(1-fraction);
584  }
585  }
586  if (factor_out_singularity == true)
587  for (unsigned int i=0; i<size(); ++i)
588  {
589  Assert( this->quadrature_points[i] != origin,
590  ExcMessage("The singularity cannot be on a Gauss point of the same order!") );
591  double denominator = std::log(std::abs( (this->quadrature_points[i]-origin)[0] )/alpha);
592  Assert( denominator != 0.0,
593  ExcMessage("The quadrature formula you are using does not allow to "
594  "factor out the singularity, which is zero at one point."));
595  this->weights[i] /= denominator;
596  }
597 }
598 
599 
600 template <>
601 unsigned int QGaussOneOverR<2>::quad_size(const Point<2> singularity,
602  const unsigned int n)
603 {
604  double eps=1e-8;
605  bool on_edge=false;
606  bool on_vertex=false;
607  for (unsigned int i=0; i<2; ++i)
608  if ( ( std::abs(singularity[i] ) < eps ) ||
609  ( std::abs(singularity[i]-1) < eps ) )
610  on_edge = true;
611  if (on_edge && (std::abs( (singularity-Point<2>(.5, .5)).norm_square()-.5)
612  < eps) )
613  on_vertex = true;
614  if (on_vertex) return (2*n*n);
615  if (on_edge) return (4*n*n);
616  return (8*n*n);
617 }
618 
619 template <>
620 QGaussOneOverR<2>::QGaussOneOverR(const unsigned int n,
621  const Point<2> singularity,
622  const bool factor_out_singularity) :
623  Quadrature<2>(quad_size(singularity, n))
624 {
625  // We treat all the cases in the
626  // same way. Split the element in 4
627  // pieces, measure the area, if
628  // it's relevant, add the
629  // quadrature connected to that
630  // singularity.
631  std::vector<QGaussOneOverR<2> > quads;
632  std::vector<Point<2> > origins;
633  // Id of the corner with a
634  // singularity
635  quads.emplace_back(n, 3, factor_out_singularity);
636  quads.emplace_back(n, 2, factor_out_singularity);
637  quads.emplace_back(n, 1, factor_out_singularity);
638  quads.emplace_back(n, 0, factor_out_singularity);
639 
640  origins.emplace_back(0., 0.);
641  origins.emplace_back(singularity[0], 0.);
642  origins.emplace_back(0., singularity[1]);
643  origins.push_back(singularity);
644 
645  // Lexicographical ordering.
646 
647  double eps = 1e-8;
648  unsigned int q_id = 0; // Current quad point index.
649  Tensor<1,2> dist;
650 
651  for (unsigned int box=0; box<4; ++box)
652  {
653  dist = (singularity-GeometryInfo<2>::unit_cell_vertex(box));
654  dist = Point<2>(std::abs(dist[0]), std::abs(dist[1]));
655  double area = dist[0]*dist[1];
656  if (area > eps)
657  for (unsigned int q=0; q<quads[box].size(); ++q, ++q_id)
658  {
659  const Point<2> &qp = quads[box].point(q);
660  this->quadrature_points[q_id] =
661  origins[box]+
662  Point<2>(dist[0]*qp[0], dist[1]*qp[1]);
663  this->weights[q_id] = quads[box].weight(q)*area;
664  }
665  }
666 }
667 
668 
669 template <>
670 QGaussOneOverR<2>::QGaussOneOverR(const unsigned int n,
671  const unsigned int vertex_index,
672  const bool factor_out_singularity) :
673  Quadrature<2>(2*n *n)
674 {
675  // This version of the constructor
676  // works only for the 4
677  // vertices. If you need a more
678  // general one, you should use the
679  // one with the Point<2> in the
680  // constructor.
681  Assert(vertex_index <4, ExcIndexRange(vertex_index, 0, 4));
682 
683  // Start with the gauss quadrature formula on the (u,v) reference
684  // element.
685  QGauss<2> gauss(n);
686 
687  Assert(gauss.size() == n*n, ExcInternalError());
688 
689  // For the moment we only implemented this for the vertices of a
690  // quadrilateral. We are planning to do this also for the support
691  // points of arbitrary FE_Q elements, to allow the use of this
692  // class in boundary element programs with higher order mappings.
693  Assert(vertex_index < 4, ExcIndexRange(vertex_index, 0, 4));
694 
695  // We create only the first one. All other pieces are rotation of
696  // this one.
697  // In this case the transformation is
698  //
699  // (x,y) = (u, u tan(pi/4 v))
700  //
701  // with Jacobian
702  //
703  // J = pi/4 R / cos(pi/4 v)
704  //
705  // And we get rid of R to take into account the singularity,
706  // unless specified differently in the constructor.
707  std::vector<Point<2> > &ps = this->quadrature_points;
708  std::vector<double> &ws = this->weights;
709  double pi4 = numbers::PI/4;
710 
711  for (unsigned int q=0; q<gauss.size(); ++q)
712  {
713  const Point<2> &gp = gauss.point(q);
714  ps[q][0] = gp[0];
715  ps[q][1] = gp[0] * std::tan(pi4*gp[1]);
716  ws[q] = gauss.weight(q)*pi4/std::cos(pi4 *gp[1]);
717  if (factor_out_singularity)
718  ws[q] *= (ps[q]-GeometryInfo<2>::unit_cell_vertex(0)).norm();
719  // The other half of the quadrilateral is symmetric with
720  // respect to xy plane.
721  ws[gauss.size()+q] = ws[q];
722  ps[gauss.size()+q][0] = ps[q][1];
723  ps[gauss.size()+q][1] = ps[q][0];
724  }
725 
726  // Now we distribute these vertices in the correct manner
727  double theta = 0;
728  switch (vertex_index)
729  {
730  case 0:
731  theta = 0;
732  break;
733  case 1:
734  //
735  theta = numbers::PI/2;
736  break;
737  case 2:
738  theta = -numbers::PI/2;
739  break;
740  case 3:
741  theta = numbers::PI;
742  break;
743  }
744 
745  double R00 = std::cos(theta), R01 = -std::sin(theta);
746  double R10 = std::sin(theta), R11 = std::cos(theta);
747 
748  if (vertex_index != 0)
749  for (unsigned int q=0; q<size(); ++q)
750  {
751  double x = ps[q][0]-.5, y = ps[q][1]-.5;
752 
753  ps[q][0] = R00*x + R01*y + .5;
754  ps[q][1] = R10*x + R11*y + .5;
755  }
756 }
757 
758 
759 template <int dim>
761  Quadrature<dim>(quad)
762 {
763  std::vector<unsigned int> permutation(quad.size());
764  for (unsigned int i=0; i<quad.size(); ++i)
765  permutation[i] = i;
766 
767  std::sort(permutation.begin(),
768  permutation.end(),
770  std::ref(*this),
771  std::placeholders::_1,
772  std::placeholders::_2));
773 
774  // At this point, the variable is_tensor_product_flag is set
775  // to the respective value of the given Quadrature in the base
776  // class copy constructor.
777  // We only call a quadrature formula 'tensor product'
778  // if the quadrature points are also sorted lexicographically.
779  // In particular, any reordering destroys that property
780  // and we might need to modify the variable accordingly.
781  for (unsigned int i=0; i<quad.size(); ++i)
782  {
783  this->weights[i] = quad.weight(permutation[i]);
784  this->quadrature_points[i] = quad.point(permutation[i]);
785  if (permutation[i] != i)
786  this->is_tensor_product_flag = false;
787  }
788 }
789 
790 
791 template <int dim>
792 bool QSorted<dim>::compare_weights(const unsigned int a,
793  const unsigned int b) const
794 {
795  return (this->weights[a] < this->weights[b]);
796 }
797 
798 
799 // construct the quadrature formulae in higher dimensions by
800 // tensor product of lower dimensions
801 
802 template <int dim>
803 QGauss<dim>::QGauss (const unsigned int n)
804  : Quadrature<dim> (QGauss<dim-1>(n), QGauss<1>(n))
805 {}
806 
807 
808 
809 template <int dim>
810 QGaussLobatto<dim>::QGaussLobatto (const unsigned int n)
811  : Quadrature<dim> (QGaussLobatto<dim-1>(n), QGaussLobatto<1>(n))
812 {}
813 
814 
815 
816 template <int dim>
818  :
819  Quadrature<dim> (QMidpoint<dim-1>(), QMidpoint<1>())
820 {}
821 
822 
823 
824 template <int dim>
826  :
827  Quadrature<dim> (QTrapez<dim-1>(), QTrapez<1>())
828 {}
829 
830 
831 
832 template <int dim>
834  :
835  Quadrature<dim> (QSimpson<dim-1>(), QSimpson<1>())
836 {}
837 
838 
839 
840 template <int dim>
842  :
843  Quadrature<dim> (QMilne<dim-1>(), QMilne<1>())
844 {}
845 
846 
847 template <int dim>
849  :
850  Quadrature<dim> (QWeddle<dim-1>(), QWeddle<1>())
851 {}
852 
853 template <int dim>
855  const Quadrature<1> &base_quad, const Point<dim> &singularity)
856  :
857  // We need the explicit implementation if dim == 1. If dim > 1 we use the
858  // former implementation and apply a tensorial product to obtain the higher
859  // dimensions.
860  Quadrature<dim>(
861  dim == 2 ?
862  QAnisotropic<dim>(
863  QTelles<1>(base_quad, Point<1>(singularity[0])),
864  QTelles<1>(base_quad, Point<1>(singularity[1]))) :
865  dim == 3 ?
866  QAnisotropic<dim>(
867  QTelles<1>(base_quad, Point<1>(singularity[0])),
868  QTelles<1>(base_quad, Point<1>(singularity[1])),
869  QTelles<1>(base_quad, Point<1>(singularity[2]))) :
870  Quadrature<dim>())
871 {
872 }
873 
874 template <int dim>
876  const unsigned int n, const Point<dim> &singularity)
877  :
878  // In this case we map the standard Gauss Legendre formula using the given
879  // singularity point coordinates.
880  Quadrature<dim>(QTelles<dim>(QGauss<1>(n), singularity))
881 {}
882 
883 
884 
885 template <>
887  const Quadrature<1> &base_quad, const Point<1> &singularity)
888  :
889  // We explicitly implement the Telles' variable change if dim == 1.
890  Quadrature<1>(base_quad)
891 {
892  // We define all the constants to be used in the implementation of
893  // Telles' rule
894  const double eta_bar = singularity[0] * 2. - 1.;
895  const double eta_star = eta_bar * eta_bar - 1.;
896  double gamma_bar;
897 
898  std::vector<Point<1> > quadrature_points_dummy(quadrature_points.size());
899  std::vector<double> weights_dummy(weights.size());
900  unsigned int cont = 0;
901  const double tol = 1e-10;
902  for (unsigned int d = 0; d < quadrature_points.size(); ++d)
903  {
904  if (std::abs(quadrature_points[d][0] - singularity[0]) > tol)
905  {
906  quadrature_points_dummy[d-cont] = quadrature_points[d];
907  weights_dummy[d-cont] = weights[d];
908  }
909  else
910  {
911  // We need to remove the singularity point from the quadrature point
912  // list. To do so we use the variable cont.
913  cont = 1;
914  }
915 
916  }
917  if (cont == 1)
918  {
919  quadrature_points.resize(quadrature_points_dummy.size()-1);
920  weights.resize(weights_dummy.size()-1);
921  for (unsigned int d = 0; d < quadrature_points.size(); ++d)
922  {
923  quadrature_points[d] = quadrature_points_dummy[d];
924  weights[d] = weights_dummy[d];
925  }
926  }
927  // We need to check if the singularity is at the boundary of the interval.
928  if (std::abs(eta_star) <= tol)
929  {
930  gamma_bar = std::pow((eta_bar * eta_star + std::abs(eta_star)),1.0 / 3.0)
931  + std::pow((eta_bar * eta_star - std::abs(eta_star)), 1.0 / 3.0)
932  + eta_bar;
933  }
934  else
935  {
936  gamma_bar = (eta_bar * eta_star + std::abs(eta_star))/std::abs(eta_bar * eta_star + std::abs(eta_star))*
937  std::pow(std::abs(eta_bar * eta_star + std::abs(eta_star)),1.0 / 3.0)
938  + (eta_bar * eta_star - std::abs(eta_star))/std::abs(eta_bar * eta_star - std::abs(eta_star))*
939  std::pow(std::abs(eta_bar * eta_star - std::abs(eta_star)), 1.0 / 3.0)
940  + eta_bar;
941  }
942  for (unsigned int q = 0; q < quadrature_points.size(); ++q)
943  {
944  double gamma = quadrature_points[q][0] * 2 - 1;
945  double eta = (std::pow(gamma - gamma_bar, 3.0)
946  + gamma_bar * (gamma_bar * gamma_bar + 3))
947  / (1 + 3 * gamma_bar * gamma_bar);
948 
949  double J = 3 * ((gamma - gamma_bar) *(gamma - gamma_bar))
950  / (1 + 3 * gamma_bar * gamma_bar);
951 
952  quadrature_points[q][0] = (eta + 1) / 2.0;
953  weights[q] = J * weights[q];
954 
955  }
956 }
957 
958 namespace internal
959 {
960  namespace QGaussChebyshev
961  {
965  std::vector<double>
966  get_quadrature_points(const unsigned int n)
967  {
968 
969  std::vector<double> points(n);
970  // n point quadrature: index from 0 to n-1
971  for (unsigned short i=0; i<n; ++i)
972  // would be cos((2i+1)Pi/(2N+2))
973  // put + Pi so we start from the smallest point
974  // then map from [-1,1] to [0,1]
975  points[i] = 1./2.*(1.+std::cos(numbers::PI*(1.+double(2*i+1)/double(2*(n-1)+2))));
976 
977  return points;
978  }
979 
980 
981 
985  std::vector<double>
986  get_quadrature_weights(const unsigned int n)
987  {
988 
989  std::vector<double> weights(n);
990 
991  for (unsigned short i=0; i<n; ++i)
992  {
993  // same weights as on [-1,1]
994  weights[i] = numbers::PI/double(n);
995  }
996 
997  return weights;
998 
999  }
1000  }
1001 }
1002 
1003 
1004 template <>
1005 QGaussChebyshev<1>::QGaussChebyshev(const unsigned int n)
1006  :
1007  Quadrature<1> (n)
1008 {
1009 
1010  Assert(n>0,ExcMessage("Need at least one point for the quadrature rule"));
1011  std::vector<double> p=internal::QGaussChebyshev::get_quadrature_points(n);
1012  std::vector<double> w=internal::QGaussChebyshev::get_quadrature_weights(n);
1013 
1014  for (unsigned int i=0; i<this->size(); ++i)
1015  {
1016  this->quadrature_points[i] = Point<1>(p[i]);
1017  this->weights[i] = w[i];
1018  }
1019 }
1020 
1021 
1022 template <int dim>
1024  :
1025  Quadrature<dim> (QGaussChebyshev<1>(n))
1026 {}
1027 
1028 
1029 namespace internal
1030 {
1031  namespace QGaussRadauChebyshev
1032  {
1033  // Computes the points of the quadrature formula.
1034  std::vector<double>
1035  get_quadrature_points(const unsigned int n,
1037  {
1038 
1039  std::vector<double> points(n);
1040  // n point quadrature: index from 0 to n-1
1041  for (unsigned short i=0; i<n; ++i)
1042  // would be -cos(2i Pi/(2N+1))
1043  // put + Pi so we start from the smallest point
1044  // then map from [-1,1] to [0,1]
1045  switch (ep)
1046  {
1047  case ::QGaussRadauChebyshev<1>::left:
1048  {
1049  points[i] = 1./2.*(1.-std::cos(numbers::PI*(1+2*double(i)/(2*double(n-1)+1.))));
1050  break;
1051  }
1052 
1053  case ::QGaussRadauChebyshev<1>::right:
1054  {
1055  points[i] = 1./2.*(1.-std::cos(numbers::PI*(2*double(n-1-i)/(2*double(n-1)+1.))));
1056  break;
1057  }
1058 
1059  default:
1060  Assert (false, ExcMessage ("This constructor can only be called with either "
1061  "QGaussRadauChebyshev::left or QGaussRadauChebyshev::right as "
1062  "second argument."));
1063  }
1064 
1065  return points;
1066  }
1067 
1068 
1069 
1070  // Computes the weights of the quadrature formula.
1071  std::vector<double>
1072  get_quadrature_weights(const unsigned int n,
1074  {
1075 
1076  std::vector<double> weights(n);
1077 
1078  for (unsigned short i=0; i<n; ++i)
1079  {
1080  // same weights as on [-1,1]
1081  weights[i] = 2.*numbers::PI/double(2*(n-1)+1.);
1082  if (ep==::QGaussRadauChebyshev<1>::left && i==0)
1083  weights[i] /= 2.;
1084  else if (ep==::QGaussRadauChebyshev<1>::right && i==(n-1))
1085  weights[i] /= 2.;
1086  }
1087 
1088  return weights;
1089  }
1090  }
1091 }
1092 
1093 
1094 template <>
1096  EndPoint ep)
1097  :
1098  Quadrature<1> (n),
1099  ep (ep)
1100 {
1101 
1102  Assert(n>0,ExcMessage("Need at least one point for quadrature rules"));
1103  std::vector<double> p=internal::QGaussRadauChebyshev::get_quadrature_points(n,ep);
1104  std::vector<double> w=internal::QGaussRadauChebyshev::get_quadrature_weights(n,ep);
1105 
1106  for (unsigned int i=0; i<this->size(); ++i)
1107  {
1108  this->quadrature_points[i] = Point<1>(p[i]);
1109  this->weights[i] = w[i];
1110  }
1111 }
1112 
1113 
1114 template <int dim>
1116  EndPoint ep)
1117  :
1118  Quadrature<dim> (QGaussRadauChebyshev<1>(n,static_cast<QGaussRadauChebyshev<1>::EndPoint>(ep))),
1119  ep (ep)
1120 {}
1121 
1122 
1123 
1124 namespace internal
1125 {
1126  namespace QGaussLobattoChebyshev
1127  {
1128  // Computes the points of the quadrature formula.
1129  std::vector<double>
1130  get_quadrature_points(const unsigned int n)
1131  {
1132 
1133  std::vector<double> points(n);
1134  // n point quadrature: index from 0 to n-1
1135  for (unsigned short i=0; i<n; ++i)
1136  // would be cos(i Pi/N)
1137  // put + Pi so we start from the smallest point
1138  // then map from [-1,1] to [0,1]
1139  points[i] = 1./2.*(1.+std::cos(numbers::PI*(1+double(i)/double(n-1))));
1140 
1141  return points;
1142  }
1143 
1144  // Computes the weights of the quadrature formula.
1145  std::vector<double>
1146  get_quadrature_weights(const unsigned int n)
1147  {
1148 
1149  std::vector<double> weights(n);
1150 
1151  for (unsigned short i=0; i<n; ++i)
1152  {
1153  // same weights as on [-1,1]
1154  weights[i] = numbers::PI/double((n-1));
1155  if (i==0 || i==(n-1))
1156  weights[i] /= 2.;
1157  }
1158 
1159  return weights;
1160  }
1161  }
1162 }
1163 
1164 
1165 
1166 template <>
1168  :
1169  Quadrature<1> (n)
1170 {
1171 
1172  Assert(n>1,ExcMessage("Need at least two points for Gauss-Lobatto quadrature rule"));
1173  std::vector<double> p=internal::QGaussLobattoChebyshev::get_quadrature_points(n);
1174  std::vector<double> w=internal::QGaussLobattoChebyshev::get_quadrature_weights(n);
1175 
1176  for (unsigned int i=0; i<this->size(); ++i)
1177  {
1178  this->quadrature_points[i] = Point<1>(p[i]);
1179  this->weights[i] = w[i];
1180  }
1181 }
1182 
1183 
1184 template <int dim>
1186  :
1187  Quadrature<dim> (QGaussLobattoChebyshev<1>(n))
1188 {}
1189 
1190 
1191 
1192 template<int dim>
1194 {
1195  std::vector<Point<dim> > qpoints;
1196  std::vector<double > weights;
1197 
1198  for (unsigned int i=0; i<quad.size(); ++i)
1199  {
1200  double r=0;
1201  for (unsigned int d=0; d<dim; ++d)
1202  r += quad.point(i)[d];
1203  if (r <= 1+1e-10)
1204  {
1205  this->quadrature_points.push_back(quad.point(i));
1206  this->weights.push_back(quad.weight(i));
1207  }
1208  }
1209 }
1210 
1211 
1212 
1213 template<int dim>
1215 QSimplex<dim>::compute_affine_transformation(const std::array<Point<dim>, dim+1>& vertices) const
1216 {
1217  Tensor<2,dim> B;
1218  for (unsigned int d=0; d<dim; ++d)
1219  B[d] = vertices[d+1]-vertices[0];
1220 
1221  B = transpose(B);
1222  const double J = std::abs(determinant(B));
1223 
1224  // if the determinant is zero, we return an empty quadrature
1225  if (J < 1e-12)
1226  return Quadrature<dim>();
1227 
1228  std::vector<Point<dim> > qp(this->size());
1229  std::vector<double> w(this->size());
1230 
1231  for (unsigned int i=0; i<this->size(); ++i)
1232  {
1233  qp[i] = Point<dim>(vertices[0]+B*this->point(i));
1234  w[i] = J*this->weight(i);
1235  }
1236 
1237  return Quadrature<dim>(qp, w);
1238 }
1239 
1240 
1241 
1243  const Quadrature<1> &angular_quadrature) :
1244  QSimplex<2>(Quadrature<2>())
1245 {
1246  const QAnisotropic<2> base(radial_quadrature, angular_quadrature);
1247  this->quadrature_points.resize(base.size());
1248  this->weights.resize(base.size());
1249  for (unsigned int i=0; i<base.size(); ++i)
1250  {
1251  const auto q = base.point(i);
1252  const auto w = base.weight(i);
1253 
1254  const auto xhat = q[0];
1255  const auto yhat = q[1];
1256 
1257  const double t = numbers::PI_2*yhat;
1258  const double pi = numbers::PI;
1259  const double st = std::sin(t);
1260  const double ct = std::cos(t);
1261  const double r = xhat/(st+ct);
1262 
1263  const double J = pi*xhat/(2*(std::sin(pi*yhat) + 1));
1264 
1265  this->quadrature_points[i] = Point<2>(r*ct, r*st);
1266  this->weights[i] = w*J;
1267  }
1268 }
1269 
1270 
1271 
1272 QTrianglePolar::QTrianglePolar(const unsigned int &n)
1273  :QTrianglePolar(QGauss<1>(n),QGauss<1>(n))
1274 {}
1275 
1276 
1277 
1278 QDuffy::QDuffy(const Quadrature<1> &radial_quadrature,
1279  const Quadrature<1> &angular_quadrature,
1280  const double beta) :
1281  QSimplex<2>(Quadrature<2>())
1282 {
1283  const QAnisotropic<2> base(radial_quadrature, angular_quadrature);
1284  this->quadrature_points.resize(base.size());
1285  this->weights.resize(base.size());
1286  for (unsigned int i=0; i<base.size(); ++i)
1287  {
1288  const auto q = base.point(i);
1289  const auto w = base.weight(i);
1290 
1291  const auto xhat = q[0];
1292  const auto yhat = q[1];
1293 
1294  const double x = std::pow(xhat, beta)*(1-yhat);
1295  const double y = std::pow(xhat, beta)*yhat;
1296 
1297  const double J = beta * std::pow(xhat, 2.*beta-1.);
1298 
1299  this->quadrature_points[i] = Point<2>(x,y);
1300  this->weights[i] = w*J;
1301  }
1302 }
1303 
1304 
1305 
1306 QDuffy::QDuffy(const unsigned int n, const double beta)
1307  :QDuffy(QGauss<1>(n), QGauss<1>(n), beta)
1308 {}
1309 
1310 
1311 
1312 template<int dim>
1314  const Point<dim> &split_point)
1315 {
1317  ExcMessage("The split point should be inside the unit reference cell."));
1318 
1319  std::array<Point<dim>, dim+1> vertices;
1320  vertices[0] = split_point;
1321 
1322  // Make a simplex from the split_point and the first dim vertices of each
1323  // face. In dimension three, we need to split the face in two triangles, so
1324  // we use once the first dim vertices of each face, and the second time the
1325  // the dim vertices of each face starting from 1.
1326  for (unsigned int f=0; f< GeometryInfo<dim>::faces_per_cell; ++f)
1327  for (unsigned int start=0; start < (dim >2 ? 2 : 1); ++start)
1328  {
1329  for (unsigned int i=0; i<dim; ++i)
1330  vertices[i+1] =
1333  );
1334  const auto quad = base.compute_affine_transformation(vertices);
1335  if (quad.size())
1336  {
1337  this->quadrature_points.insert(
1338  this->quadrature_points.end(),
1339  quad.get_points().begin(),
1340  quad.get_points().end());
1341  this->weights.insert(
1342  this->weights.end(),
1343  quad.get_weights().begin(),
1344  quad.get_weights().end());
1345  }
1346  }
1347 }
1348 
1349 
1350 
1351 // explicit specialization
1352 // note that 1d formulae are specialized by implementation above
1353 template class QGauss<2>;
1354 template class QGaussLobatto<2>;
1355 template class QMidpoint<2>;
1356 template class QTrapez<2>;
1357 template class QSimpson<2>;
1358 template class QMilne<2>;
1359 template class QWeddle<2>;
1360 
1361 template class QGauss<3>;
1362 template class QGaussLobatto<3>;
1363 template class QMidpoint<3>;
1364 template class QTrapez<3>;
1365 template class QSimpson<3>;
1366 template class QMilne<3>;
1367 template class QWeddle<3>;
1368 
1369 template class QSorted<1>;
1370 template class QSorted<2>;
1371 template class QSorted<3>;
1372 
1373 template class QTelles<1> ;
1374 template class QTelles<2> ;
1375 template class QTelles<3> ;
1376 
1377 template class QGaussChebyshev<1>;
1378 template class QGaussChebyshev<2>;
1379 template class QGaussChebyshev<3>;
1380 
1381 template class QGaussRadauChebyshev<1>;
1382 template class QGaussRadauChebyshev<2>;
1383 template class QGaussRadauChebyshev<3>;
1384 
1385 template class QGaussLobattoChebyshev<1>;
1386 template class QGaussLobattoChebyshev<2>;
1387 template class QGaussLobattoChebyshev<3>;
1388 
1389 template class QSimplex<1>;
1390 template class QSimplex<2>;
1391 template class QSimplex<3>;
1392 
1393 template class QSplit<1>;
1394 template class QSplit<2>;
1395 template class QSplit<3>;
1396 
1397 DEAL_II_NAMESPACE_CLOSE
QGaussLog(const unsigned int n, const bool revert=false)
std::vector< double > weights
Definition: quadrature.h:258
QGaussOneOverR(const unsigned int n, const Point< dim > singularity, const bool factor_out_singular_weight=false)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
QGaussChebyshev(const unsigned int n)
Generate a formula with n quadrature points.
const Point< dim > & point(const unsigned int i) const
static std::vector< double > get_quadrature_points(const unsigned int n)
QSimplex(const Quadrature< dim > &quad)
static Point< dim > unit_cell_vertex(const unsigned int vertex)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
QGauss(const unsigned int n)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
Definition: point.h:104
static const double PI
Definition: numbers.h:127
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
static std::vector< double > get_quadrature_weights(const unsigned int n)
QGaussRadauChebyshev(const unsigned int n, EndPoint ep=QGaussRadauChebyshev::left)
Generate a formula with n quadrature points.
QDuffy(const Quadrature< 1 > &radial_quadrature, const Quadrature< 1 > &angular_quadrature, const double beta=1.0)
bool compare_weights(const unsigned int a, const unsigned int b) const
QGaussLobatto(const unsigned int n)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
bool is_tensor_product_flag
Definition: quadrature.h:267
std::vector< Point< dim > > quadrature_points
Definition: quadrature.h:252
unsigned int size() const
QTelles(const Quadrature< 1 > &base_quad, const Point< dim > &singularity)
Tensor< 2, dim, Number > w(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
double norm(const FEValuesBase< dim > &fe, const VectorSlice< const std::vector< std::vector< Tensor< 1, dim > > > > &Du)
Definition: divergence.h:534
Number determinant(const SymmetricTensor< 2, dim, Number > &t)
Definition: mpi.h:53
static const double PI_2
Definition: numbers.h:132
QGaussLobattoChebyshev(const unsigned int n)
Generate a formula with n quadrature points.
static ::ExceptionBase & ExcNotImplemented()
QSorted(const Quadrature< dim > &quad)
QGaussLogR(const unsigned int n, const Point< dim > x0=Point< dim >(), const double alpha=1, const bool factor_out_singular_weight=false)
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
QSplit(const QSimplex< dim > &base, const Point< dim > &split_point)
Quadrature< dim > compute_affine_transformation(const std::array< Point< dim >, dim+1 > &vertices) const
double weight(const unsigned int i) const
static unsigned int quad_size(const Point< dim > singularity, const unsigned int n)
static ::ExceptionBase & ExcInternalError()
QTrianglePolar(const Quadrature< 1 > &radial_quadrature, const Quadrature< 1 > &angular_quadrature)