libMesh
quadrature_gauss_3D.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local includes
21 #include "libmesh/quadrature_gauss.h"
22 #include "libmesh/quadrature_conical.h"
23 #include "libmesh/quadrature_gm.h"
24 #include "libmesh/enum_to_string.h"
25 
26 namespace libMesh
27 {
28 
29 void QGauss::init_3D(const ElemType, unsigned int)
30 {
31 #if LIBMESH_DIM == 3
32 
33  //-----------------------------------------------------------------------
34  // 3D quadrature rules
35  switch (_type)
36  {
37  //---------------------------------------------
38  // Hex quadrature rules
39  case HEX8:
40  case HEX20:
41  case HEX27:
42  {
43  // We compute the 3D quadrature rule as a tensor
44  // product of the 1D quadrature rule.
45  QGauss q1D(1, _order);
46  q1D.init(EDGE2, _p_level);
47  tensor_product_hex( q1D );
48  return;
49  }
50 
51 
52 
53  //---------------------------------------------
54  // Tetrahedral quadrature rules
55  case TET4:
56  case TET10:
57  case TET14:
58  {
59  switch(get_order())
60  {
61  // Taken from pg. 222 of "The finite element method," vol. 1
62  // ed. 5 by Zienkiewicz & Taylor
63  case CONSTANT:
64  case FIRST:
65  {
66  // Exact for linears
67  _points.resize(1);
68  _weights.resize(1);
69 
70 
71  _points[0](0) = .25;
72  _points[0](1) = .25;
73  _points[0](2) = .25;
74 
75  _weights[0] = Real(1)/6;
76 
77  return;
78  }
79  case SECOND:
80  {
81  // Exact for quadratics
82  _points.resize(4);
83  _weights.resize(4);
84 
85 
86  const Real a = .585410196624969;
87  const Real b = .138196601125011;
88 
89  _points[0](0) = a;
90  _points[0](1) = b;
91  _points[0](2) = b;
92 
93  _points[1](0) = b;
94  _points[1](1) = a;
95  _points[1](2) = b;
96 
97  _points[2](0) = b;
98  _points[2](1) = b;
99  _points[2](2) = a;
100 
101  _points[3](0) = b;
102  _points[3](1) = b;
103  _points[3](2) = b;
104 
105 
106 
107  _weights[0] = Real(1)/24;
108  _weights[1] = _weights[0];
109  _weights[2] = _weights[0];
110  _weights[3] = _weights[0];
111 
112  return;
113  }
114 
115 
116 
117  // Can be found in the class notes
118  // http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps
119  // by Flaherty.
120  //
121  // Caution: this rule has a negative weight and may be
122  // unsuitable for some problems.
123  // Exact for cubics.
124  //
125  // Note: Keast (see ref. elsewhere in this file) also gives
126  // a third-order rule with positive weights, but it contains points
127  // on the ref. elt. boundary, making it less suitable for FEM calculations.
128  case THIRD:
129  {
131  {
132  _points.resize(5);
133  _weights.resize(5);
134 
135 
136  _points[0](0) = .25;
137  _points[0](1) = .25;
138  _points[0](2) = .25;
139 
140  _points[1](0) = .5;
141  _points[1](1) = Real(1)/6;
142  _points[1](2) = Real(1)/6;
143 
144  _points[2](0) = Real(1)/6;
145  _points[2](1) = .5;
146  _points[2](2) = Real(1)/6;
147 
148  _points[3](0) = Real(1)/6;
149  _points[3](1) = Real(1)/6;
150  _points[3](2) = .5;
151 
152  _points[4](0) = Real(1)/6;
153  _points[4](1) = Real(1)/6;
154  _points[4](2) = Real(1)/6;
155 
156 
157  _weights[0] = Real(-2)/15;
158  _weights[1] = .075;
159  _weights[2] = _weights[1];
160  _weights[3] = _weights[1];
161  _weights[4] = _weights[1];
162 
163  return;
164  } // end if (allow_rules_with_negative_weights)
165  else
166  {
167  // If a rule with positive weights is required, the 2x2x2 conical
168  // product rule is third-order accurate and has less points than
169  // the next-available positive-weight rule at FIFTH order.
170  QConical conical_rule(3, _order);
171  conical_rule.init(_type, _p_level);
172 
173  // Swap points and weights with the about-to-be destroyed rule.
174  _points.swap (conical_rule.get_points() );
175  _weights.swap(conical_rule.get_weights());
176 
177  return;
178  }
179  // Note: if !allow_rules_with_negative_weights, fall through to next case.
180  }
181 
182 
183 
184  // Originally a Keast rule,
185  // Patrick Keast,
186  // Moderate Degree Tetrahedral Quadrature Formulas,
187  // Computer Methods in Applied Mechanics and Engineering,
188  // Volume 55, Number 3, May 1986, pages 339-348.
189  //
190  // Can also be found the class notes
191  // http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps
192  // by Flaherty.
193  //
194  // Caution: this rule has a negative weight and may be
195  // unsuitable for some problems.
196  case FOURTH:
197  {
199  {
200  _points.resize(11);
201  _weights.resize(11);
202 
203  // The raw data for the quadrature rule.
204  const Real rule_data[3][4] = {
205  {0.250000000000000000e+00, 0., 0., -0.131555555555555556e-01}, // 1
206  {0.785714285714285714e+00, 0.714285714285714285e-01, 0., 0.762222222222222222e-02}, // 4
207  {0.399403576166799219e+00, 0., 0.100596423833200785e+00, 0.248888888888888889e-01} // 6
208  };
209 
210 
211  // Now call the keast routine to generate _points and _weights
212  keast_rule(rule_data, 3);
213 
214  return;
215  } // end if (allow_rules_with_negative_weights)
216  // Note: if !allow_rules_with_negative_weights, fall through to next case.
217  }
218 
219  libmesh_fallthrough();
220 
221 
222  // Walkington's fifth-order 14-point rule from
223  // "Quadrature on Simplices of Arbitrary Dimension"
224  //
225  // We originally had a Keast rule here, but this rule had
226  // more points than an equivalent rule by Walkington and
227  // also contained points on the boundary of the ref. elt,
228  // making it less suitable for FEM calculations.
229  case FIFTH:
230  {
231  _points.resize(14);
232  _weights.resize(14);
233 
234  // permutations of these points and suitably-modified versions of
235  // these points are the quadrature point locations
236  const Real a[3] = {0.31088591926330060980, // a1 from the paper
237  0.092735250310891226402, // a2 from the paper
238  0.045503704125649649492}; // a3 from the paper
239 
240  // weights. a[] and wt[] are the only floating-point inputs required
241  // for this rule.
242  const Real wt[3] = {0.018781320953002641800, // w1 from the paper
243  0.012248840519393658257, // w2 from the paper
244  0.0070910034628469110730}; // w3 from the paper
245 
246  // The first two sets of 4 points are formed in a similar manner
247  for (unsigned int i=0; i<2; ++i)
248  {
249  // Where we will insert values into _points and _weights
250  const unsigned int offset=4*i;
251 
252  // Stuff points and weights values into their arrays
253  const Real b = 1. - 3.*a[i];
254 
255  // Here are the permutations. Order of these is not important,
256  // all have the same weight
257  _points[offset + 0] = Point(a[i], a[i], a[i]);
258  _points[offset + 1] = Point(a[i], b, a[i]);
259  _points[offset + 2] = Point( b, a[i], a[i]);
260  _points[offset + 3] = Point(a[i], a[i], b);
261 
262  // These 4 points all have the same weights
263  for (unsigned int j=0; j<4; ++j)
264  _weights[offset + j] = wt[i];
265  } // end for
266 
267 
268  {
269  // The third set contains 6 points and is formed a little differently
270  const unsigned int offset = 8;
271  const Real b = 0.5*(1. - 2.*a[2]);
272 
273  // Here are the permutations. Order of these is not important,
274  // all have the same weight
275  _points[offset + 0] = Point(b , b, a[2]);
276  _points[offset + 1] = Point(b , a[2], a[2]);
277  _points[offset + 2] = Point(a[2], a[2], b);
278  _points[offset + 3] = Point(a[2], b, a[2]);
279  _points[offset + 4] = Point( b, a[2], b);
280  _points[offset + 5] = Point(a[2], b, b);
281 
282  // These 6 points all have the same weights
283  for (unsigned int j=0; j<6; ++j)
284  _weights[offset + j] = wt[2];
285  }
286 
287 
288  // Original rule by Keast, unsuitable because it has points on the
289  // reference element boundary!
290  // _points.resize(15);
291  // _weights.resize(15);
292 
293  // _points[0](0) = 0.25;
294  // _points[0](1) = 0.25;
295  // _points[0](2) = 0.25;
296 
297  // {
298  // const Real a = 0.;
299  // const Real b = Real(1)/3;
300 
301  // _points[1](0) = a;
302  // _points[1](1) = b;
303  // _points[1](2) = b;
304 
305  // _points[2](0) = b;
306  // _points[2](1) = a;
307  // _points[2](2) = b;
308 
309  // _points[3](0) = b;
310  // _points[3](1) = b;
311  // _points[3](2) = a;
312 
313  // _points[4](0) = b;
314  // _points[4](1) = b;
315  // _points[4](2) = b;
316  // }
317  // {
318  // const Real a = Real(8)/11;
319  // const Real b = Real(1)/11;
320 
321  // _points[5](0) = a;
322  // _points[5](1) = b;
323  // _points[5](2) = b;
324 
325  // _points[6](0) = b;
326  // _points[6](1) = a;
327  // _points[6](2) = b;
328 
329  // _points[7](0) = b;
330  // _points[7](1) = b;
331  // _points[7](2) = a;
332 
333  // _points[8](0) = b;
334  // _points[8](1) = b;
335  // _points[8](2) = b;
336  // }
337  // {
338  // const Real a = 0.066550153573664;
339  // const Real b = 0.433449846426336;
340 
341  // _points[9](0) = b;
342  // _points[9](1) = a;
343  // _points[9](2) = a;
344 
345  // _points[10](0) = a;
346  // _points[10](1) = a;
347  // _points[10](2) = b;
348 
349  // _points[11](0) = a;
350  // _points[11](1) = b;
351  // _points[11](2) = b;
352 
353  // _points[12](0) = b;
354  // _points[12](1) = a;
355  // _points[12](2) = b;
356 
357  // _points[13](0) = b;
358  // _points[13](1) = b;
359  // _points[13](2) = a;
360 
361  // _points[14](0) = a;
362  // _points[14](1) = b;
363  // _points[14](2) = a;
364  // }
365 
366  // _weights[0] = 0.030283678097089;
367  // _weights[1] = 0.006026785714286;
368  // _weights[2] = _weights[1];
369  // _weights[3] = _weights[1];
370  // _weights[4] = _weights[1];
371  // _weights[5] = 0.011645249086029;
372  // _weights[6] = _weights[5];
373  // _weights[7] = _weights[5];
374  // _weights[8] = _weights[5];
375  // _weights[9] = 0.010949141561386;
376  // _weights[10] = _weights[9];
377  // _weights[11] = _weights[9];
378  // _weights[12] = _weights[9];
379  // _weights[13] = _weights[9];
380  // _weights[14] = _weights[9];
381 
382  return;
383  }
384 
385 
386 
387 
388  // This rule is originally from Keast:
389  // Patrick Keast,
390  // Moderate Degree Tetrahedral Quadrature Formulas,
391  // Computer Methods in Applied Mechanics and Engineering,
392  // Volume 55, Number 3, May 1986, pages 339-348.
393  //
394  // It is accurate on 6th-degree polynomials and has 24 points
395  // vs. 64 for the comparable conical product rule.
396  //
397  // Values copied 24th June 2008 from:
398  // http://people.scs.fsu.edu/~burkardt/f_src/keast/keast.f90
399  case SIXTH:
400  {
401  _points.resize (24);
402  _weights.resize(24);
403 
404  // The raw data for the quadrature rule.
405  const Real rule_data[4][4] = {
406  {0.356191386222544953e+00 , 0.214602871259151684e+00 , 0., 0.00665379170969464506e+00}, // 4
407  {0.877978124396165982e+00 , 0.0406739585346113397e+00, 0., 0.00167953517588677620e+00}, // 4
408  {0.0329863295731730594e+00, 0.322337890142275646e+00 , 0., 0.00922619692394239843e+00}, // 4
409  {0.0636610018750175299e+00, 0.269672331458315867e+00 , 0.603005664791649076e+00, 0.00803571428571428248e+00} // 12
410  };
411 
412 
413  // Now call the keast routine to generate _points and _weights
414  keast_rule(rule_data, 4);
415 
416  return;
417  }
418 
419 
420  // Keast's 31 point, 7th-order rule contains points on the reference
421  // element boundary, so we've decided not to include it here.
422  //
423  // Keast's 8th-order rule has 45 points. and a negative
424  // weight, so if you've explicitly disallowed such rules
425  // you will fall through to the conical product rules
426  // below.
427  case SEVENTH:
428  case EIGHTH:
429  {
431  {
432  _points.resize (45);
433  _weights.resize(45);
434 
435  // The raw data for the quadrature rule.
436  const Real rule_data[7][4] = {
437  {0.250000000000000000e+00, 0., 0., -0.393270066412926145e-01}, // 1
438  {0.617587190300082967e+00, 0.127470936566639015e+00, 0., 0.408131605934270525e-02}, // 4
439  {0.903763508822103123e+00, 0.320788303926322960e-01, 0., 0.658086773304341943e-03}, // 4
440  {0.497770956432810185e-01, 0., 0.450222904356718978e+00, 0.438425882512284693e-02}, // 6
441  {0.183730447398549945e+00, 0., 0.316269552601450060e+00, 0.138300638425098166e-01}, // 6
442  {0.231901089397150906e+00, 0.229177878448171174e-01, 0.513280033360881072e+00, 0.424043742468372453e-02}, // 12
443  {0.379700484718286102e-01, 0.730313427807538396e+00, 0.193746475248804382e+00, 0.223873973961420164e-02} // 12
444  };
445 
446 
447  // Now call the keast routine to generate _points and _weights
448  keast_rule(rule_data, 7);
449 
450  return;
451  } // end if (allow_rules_with_negative_weights)
452  // Note: if !allow_rules_with_negative_weights, fall through to next case.
453  }
454 
455  libmesh_fallthrough();
456 
457 
458  // Fall back on Grundmann-Moller or Conical Product rules at high orders.
459  default:
460  {
462  {
463  // The Grundmann-Moller rules are defined to arbitrary order and
464  // can have significantly fewer evaluation points than conical product
465  // rules. If you allow rules with negative weights, the GM rules
466  // will be more efficient for degree up to 33 (for degree 34 and
467  // higher, CP is more efficient!) but may be more susceptible
468  // to round-off error. Safest is to disallow rules with negative
469  // weights, but this decision should be made on a case-by-case basis.
470  QGrundmann_Moller gm_rule(3, _order);
471  gm_rule.init(_type, _p_level);
472 
473  // Swap points and weights with the about-to-be destroyed rule.
474  _points.swap (gm_rule.get_points() );
475  _weights.swap(gm_rule.get_weights());
476 
477  return;
478  }
479 
480  else
481  {
482  // The following quadrature rules are generated as
483  // conical products. These tend to be non-optimal
484  // (use too many points, cluster points in certain
485  // regions of the domain) but they are quite easy to
486  // automatically generate using a 1D Gauss rule on
487  // [0,1] and two 1D Jacobi-Gauss rules on [0,1].
488  QConical conical_rule(3, _order);
489  conical_rule.init(_type, _p_level);
490 
491  // Swap points and weights with the about-to-be destroyed rule.
492  _points.swap (conical_rule.get_points() );
493  _weights.swap(conical_rule.get_weights());
494 
495  return;
496  }
497  }
498  }
499  } // end case TET
500 
501 
502 
503  //---------------------------------------------
504  // Prism quadrature rules
505  case PRISM6:
506  case PRISM15:
507  case PRISM18:
508  case PRISM20:
509  case PRISM21:
510  {
511  // We compute the 3D quadrature rule as a tensor
512  // product of the 1D quadrature rule and a 2D
513  // triangle quadrature rule
514 
515  QGauss q1D(1,_order);
516  QGauss q2D(2,_order);
517 
518  // Initialize
519  q1D.init(EDGE2, _p_level);
520  q2D.init(TRI3, _p_level);
521 
522  tensor_product_prism(q1D, q2D);
523 
524  return;
525  }
526 
527 
528 
529  //---------------------------------------------
530  // Pyramid
531  case PYRAMID5:
532  case PYRAMID13:
533  case PYRAMID14:
534  case PYRAMID18:
535  {
536  // We compute the Pyramid rule as a conical product of a
537  // Jacobi rule with alpha==2 on the interval [0,1] two 1D
538  // Gauss rules with suitably modified points. The idea comes
539  // from: Stroud, A.H. "Approximate Calculation of Multiple
540  // Integrals."
541  QConical conical_rule(3, _order);
542  conical_rule.init(_type, _p_level);
543 
544  // Swap points and weights with the about-to-be destroyed rule.
545  _points.swap (conical_rule.get_points() );
546  _weights.swap(conical_rule.get_weights());
547 
548  return;
549 
550  }
551 
552 
553 
554  //---------------------------------------------
555  // Unsupported type
556  default:
557  libmesh_error_msg("ERROR: Unsupported type: " << Utility::enum_to_string(_type));
558  }
559 #endif
560 }
561 
562 } // namespace libMesh
virtual void init(const ElemType type=INVALID_ELEM, unsigned int p_level=0)
Initializes the data structures for a quadrature rule for an element of type type.
Definition: quadrature.C:64
ElemType
Defines an enum for geometric element types.
virtual void init_3D(const ElemType, unsigned int) override
Initializes the 3D quadrature rule by filling the points and weights vectors with the appropriate val...
bool allow_rules_with_negative_weights
Flag (default true) controlling the use of quadrature rules with negative weights.
Definition: quadrature.h:261
ElemType _type
The type of element for which the current values have been computed.
Definition: quadrature.h:371
const std::vector< Real > & get_weights() const
Definition: quadrature.h:160
The libMesh namespace provides an interface to certain functionality in the library.
std::vector< Point > _points
The locations of the quadrature points in reference element space.
Definition: quadrature.h:383
std::vector< Real > _weights
The quadrature weights.
Definition: quadrature.h:389
void tensor_product_prism(const QBase &q1D, const QBase &q2D)
Computes the tensor product of a 1D quadrature rule and a 2D quadrature rule.
Definition: quadrature.C:230
unsigned int _p_level
The p-level of the element for which the current values have been computed.
Definition: quadrature.h:377
void tensor_product_hex(const QBase &q1D)
Computes the tensor product quadrature rule [q1D x q1D x q1D] from the 1D rule q1D.
Definition: quadrature.C:203
Order get_order() const
Definition: quadrature.h:218
This class implements the so-called conical product quadrature rules for Tri and Tet elements...
This class implements the Grundmann-Moller quadrature rules for tetrahedra.
Definition: quadrature_gm.h:96
std::string enum_to_string(const T e)
Order _order
The polynomial order which the quadrature rule is capable of integrating exactly. ...
Definition: quadrature.h:365
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void keast_rule(const Real rule_data[][4], const unsigned int n_pts)
The Keast rules are for tets.
const std::vector< Point > & get_points() const
Definition: quadrature.h:148
This class implements specific orders of Gauss quadrature.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39