MFEM  v3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
intrules.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.googlecode.com.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 // Implementation of IntegrationRule(s) classes
13 
14 // Acknowledgment: Some of the high-precision triangular and tetrahedral
15 // quadrature rules below were obtained from the Encyclopaedia of Cubature
16 // Formulas at http://nines.cs.kuleuven.be/research/ecf/ecf.html
17 
18 #include "fem.hpp"
19 #include <cmath>
20 
21 using namespace std;
22 
23 namespace mfem
24 {
25 
26 IntegrationRule::IntegrationRule(IntegrationRule &irx, IntegrationRule &iry)
27 {
28  int i, j, nx, ny;
29 
30  nx = irx.GetNPoints();
31  ny = iry.GetNPoints();
32  SetSize(nx * ny);
33 
34  for (j = 0; j < ny; j++)
35  {
36  IntegrationPoint &ipy = iry.IntPoint(j);
37  for (i = 0; i < nx; i++)
38  {
39  IntegrationPoint &ipx = irx.IntPoint(i);
40  IntegrationPoint &ip = IntPoint(j*nx+i);
41 
42  ip.x = ipx.x;
43  ip.y = ipy.x;
44  ip.weight = ipx.weight * ipy.weight;
45  }
46  }
47 }
48 
49 void IntegrationRule::GaussianRule()
50 {
51  int n = Size();
52  int m = (n+1)/2;
53  int i, j;
54  double p1, p2, p3;
55  double pp, z;
56  for (i = 1; i <= m; i++)
57  {
58  z = cos(M_PI * (i - 0.25) / (n + 0.5));
59 
60  while(1)
61  {
62  p1 = 1;
63  p2 = 0;
64  for (j = 1; j <= n; j++)
65  {
66  p3 = p2;
67  p2 = p1;
68  p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j;
69  }
70  // p1 is Legendre polynomial
71 
72  pp = n * (z*p1-p2) / (z*z - 1);
73 
74  if (fabs(p1/pp) < 2e-16) break;
75 
76  z = z - p1/pp;
77  }
78 
79  z = ((1 - z) + p1/pp)/2;
80 
81  IntPoint(i-1).x = z;
82  IntPoint(n-i).x = 1 - z;
83  IntPoint(i-1).weight =
84  IntPoint(n-i).weight = 1./(4*z*(1 - z)*pp*pp);
85  }
86 }
87 
88 void IntegrationRule::UniformRule()
89 {
90  int i;
91  double h;
92 
93  h = 1.0 / (Size() - 1);
94  for (i = 0; i < Size(); i++)
95  {
96  IntPoint(i).x = double(i) / (Size() - 1);
97  IntPoint(i).weight = h;
98  }
99  IntPoint(0).weight = 0.5 * h;
100  IntPoint(Size()-1).weight = 0.5 * h;
101 }
102 
103 void IntegrationRule::GrundmannMollerSimplexRule(int s, int n)
104 {
105  // for pow on older compilers
106  using std::pow;
107  const int d = 2*s + 1;
108  Vector fact(d + n + 1);
109  Array<int> beta(n), sums(n);
110 
111  fact(0) = 1.;
112  for (int i = 1; i < fact.Size(); i++)
113  fact(i) = fact(i - 1)*i;
114 
115  // number of points is \binom{n + s + 1}{n + 1}
116  int np = 1, f = 1;
117  for (int i = 0; i <= n; i++)
118  np *= (s + i + 1), f *= (i + 1);
119  np /= f;
120  SetSize(np);
121 
122  int pt = 0;
123  for (int i = 0; i <= s; i++)
124  {
125  double weight;
126 
127  weight = pow(2., -2*s)*pow(static_cast<double>(d + n - 2*i), d)/fact(i)/fact(d + n - i);
128  if (i%2)
129  weight = -weight;
130 
131  // loop over all beta : beta_0 + ... + beta_{n-1} <= s - i
132  int k = s - i;
133  beta = 0;
134  sums = 0;
135  while (true)
136  {
137  IntegrationPoint &ip = IntPoint(pt++);
138  ip.weight = weight;
139  ip.x = double(2*beta[0] + 1)/(d + n - 2*i);
140  ip.y = double(2*beta[1] + 1)/(d + n - 2*i);
141  if (n == 3)
142  ip.z = double(2*beta[2] + 1)/(d + n - 2*i);
143 
144  int j = 0;
145  while (sums[j] == k)
146  {
147  beta[j++] = 0;
148  if (j == n)
149  goto done_beta;
150  }
151  beta[j]++;
152  sums[j]++;
153  for (j--; j >= 0; j--)
154  sums[j] = sums[j+1];
155  }
156  done_beta:
157  ;
158  }
159 }
160 
161 
162 IntegrationRules IntRules(0);
163 
164 IntegrationRules RefinedIntRules(1);
165 
166 IntegrationRules::IntegrationRules(int Ref)
167 {
168  refined = Ref;
169  if (refined < 0) { own_rules = 0; return; }
170 
171  own_rules = 1;
172 
173  PointIntRules.SetSize(2);
174  PointIntRules = NULL;
175 
176  SegmentIntRules.SetSize(32);
177  SegmentIntRules = NULL;
178 
179  // TriangleIntegrationRule() assumes that this size is >= 26
180  TriangleIntRules.SetSize(32);
181  TriangleIntRules = NULL;
182 
183  SquareIntRules.SetSize(32);
184  SquareIntRules = NULL;
185 
186  // TetrahedronIntegrationRule() assumes that this size is >= 10
187  TetrahedronIntRules.SetSize(32);
188  TetrahedronIntRules = NULL;
189 
190  CubeIntRules.SetSize(32);
191  CubeIntRules = NULL;
192 }
193 
194 const IntegrationRule &IntegrationRules::Get(int GeomType, int Order)
195 {
196  Array<IntegrationRule *> *ir_array;
197 
198  switch (GeomType)
199  {
200  case Geometry::POINT: ir_array = &PointIntRules; Order = 0; break;
201  case Geometry::SEGMENT: ir_array = &SegmentIntRules; break;
202  case Geometry::TRIANGLE: ir_array = &TriangleIntRules; break;
203  case Geometry::SQUARE: ir_array = &SquareIntRules; break;
204  case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
205  case Geometry::CUBE: ir_array = &CubeIntRules; break;
206  default:
207  mfem_error("IntegrationRules::Get(...) : Unknown geometry type!");
208  ir_array = NULL;
209  }
210 
211  if (!HaveIntRule(*ir_array, Order))
212  GenerateIntegrationRule(GeomType, Order);
213 
214  return *(*ir_array)[Order];
215 }
216 
217 void IntegrationRules::Set(int GeomType, int Order, IntegrationRule &IntRule)
218 {
219  Array<IntegrationRule *> *ir_array;
220 
221  switch (GeomType)
222  {
223  case Geometry::POINT: ir_array = &PointIntRules; break;
224  case Geometry::SEGMENT: ir_array = &SegmentIntRules; break;
225  case Geometry::TRIANGLE: ir_array = &TriangleIntRules; break;
226  case Geometry::SQUARE: ir_array = &SquareIntRules; break;
227  case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
228  case Geometry::CUBE: ir_array = &CubeIntRules; break;
229  default:
230  mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
231  ir_array = NULL;
232  }
233 
234  if (HaveIntRule(*ir_array, Order))
235  MFEM_ABORT("Overwriting set rules is not supported!");
236 
237  AllocIntRule(*ir_array, Order);
238 
239  (*ir_array)[Order] = &IntRule;
240 }
241 
242 void IntegrationRules::DeleteIntRuleArray(Array<IntegrationRule *> &ir_array)
243 {
244  int i;
245  IntegrationRule *ir = NULL;
246 
247  // Many of the intrules have multiple contiguous copies in the ir_array
248  // so we have to be careful to not delete them twice.
249  for (i = 0; i < ir_array.Size(); i++)
250  {
251  if (ir_array[i] != NULL && ir_array[i] != ir)
252  {
253  ir = ir_array[i];
254  delete (ir_array[i]);
255  }
256  }
257 }
258 
259 IntegrationRules::~IntegrationRules()
260 {
261  if (!own_rules) return;
262 
263  DeleteIntRuleArray(PointIntRules);
264  DeleteIntRuleArray(SegmentIntRules);
265  DeleteIntRuleArray(TriangleIntRules);
266  DeleteIntRuleArray(SquareIntRules);
267  DeleteIntRuleArray(TetrahedronIntRules);
268  DeleteIntRuleArray(CubeIntRules);
269 }
270 
271 
272 IntegrationRule *IntegrationRules::GenerateIntegrationRule(int GeomType, int Order)
273 {
274  switch (GeomType)
275  {
276  case Geometry::POINT:
277  return PointIntegrationRule(Order);
278  case Geometry::SEGMENT:
279  return SegmentIntegrationRule(Order);
280  case Geometry::TRIANGLE:
281  return TriangleIntegrationRule(Order);
282  case Geometry::SQUARE:
283  return SquareIntegrationRule(Order);
284  case Geometry::TETRAHEDRON:
285  return TetrahedronIntegrationRule(Order);
286  case Geometry::CUBE:
287  return CubeIntegrationRule(Order);
288  default:
289  mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
290  return NULL;
291  }
292 }
293 
294 
295 // Integration rules for a point
296 IntegrationRule *IntegrationRules::PointIntegrationRule(int Order)
297 {
298  if (Order > 1)
299  {
300  mfem_error("Point Integration Rule of Order > 1 not defined");
301  return NULL;
302  }
303 
304  PointIntRules[0] = new IntegrationRule(1);
305  PointIntRules[0] -> IntPoint(0).x = .0;
306  PointIntRules[0] -> IntPoint(0).weight = 1.;
307 
308  PointIntRules[1] = PointIntRules[0];
309 
310  return PointIntRules[0];
311 }
312 
313 // Integration rules for line segment [0,1]
314 IntegrationRule *IntegrationRules::SegmentIntegrationRule(int Order)
315 {
316  int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
317 
318  AllocIntRule(SegmentIntRules, i);
319 
320  if (refined)
321  {
322  int n = i/2 + 1;
323 
324  IntegrationRule *tmp = new IntegrationRule(n);
325  tmp->GaussianRule();
326 
327  IntegrationRule *ir = new IntegrationRule(2*n);
328  SegmentIntRules[i-1] = SegmentIntRules[i] = ir;
329  for (int j = 0; j < n; j++)
330  {
331  ir->IntPoint(j).x = tmp->IntPoint(j).x/2.0;
332  ir->IntPoint(j).weight = tmp->IntPoint(j).weight/2.0;
333  ir->IntPoint(j+n).x = 0.5 + tmp->IntPoint(j).x/2.0;
334  ir->IntPoint(j+n).weight = tmp->IntPoint(j).weight/2.0;
335  }
336  delete tmp;
337 
338  return ir;
339  }
340 
341  switch (Order / 2)
342  {
343  case 0: // 1 point - 1 degree
344  SegmentIntRules[0] = SegmentIntRules[1] = new IntegrationRule (1);
345  SegmentIntRules[0] -> IntPoint(0).x = .5;
346  SegmentIntRules[0] -> IntPoint(0).weight = 1.;
347  return SegmentIntRules[0];
348  case 1: // 2 point - 3 degree
349  SegmentIntRules[2] = SegmentIntRules[3] = new IntegrationRule (2);
350  SegmentIntRules[2] -> IntPoint(0).x = 0.21132486540518711775;
351  SegmentIntRules[2] -> IntPoint(0).weight = .5;
352  SegmentIntRules[2] -> IntPoint(1).x = 0.78867513459481288225;
353  SegmentIntRules[2] -> IntPoint(1).weight = .5;
354  return SegmentIntRules[2];
355  case 2: // 3 point - 5 degree
356  SegmentIntRules[4] = SegmentIntRules[5] = new IntegrationRule (3);
357  SegmentIntRules[4] -> IntPoint(0).x = 0.11270166537925831148;
358  SegmentIntRules[4] -> IntPoint(0).weight = 5./18.;
359  SegmentIntRules[4] -> IntPoint(1).x = 0.5;
360  SegmentIntRules[4] -> IntPoint(1).weight = 4./9.;
361  SegmentIntRules[4] -> IntPoint(2).x = 0.88729833462074168852;
362  SegmentIntRules[4] -> IntPoint(2).weight = 5./18.;
363  return SegmentIntRules[4];
364  default:
365  SegmentIntRules[i-1] = SegmentIntRules[i] = new IntegrationRule (i/2+1);
366  SegmentIntRules[i]->GaussianRule();
367  return SegmentIntRules[i];
368  }
369 }
370 
371 // Integration rules for reference triangle {[0,0],[1,0],[0,1]}
372 IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
373 {
374  IntegrationRule *ir = NULL;
375 
376  // assuming that orders <= 25 are pre-allocated
377  switch (Order)
378  {
379  case 0: // 1 point - 0 degree
380  case 1:
381  TriangleIntRules[0] = TriangleIntRules[1] = ir = new IntegrationRule (1);
382  TriangleIntRules[0]->AddTriMidPoint(0, 0.5);
383  return ir;
384 
385  case 2: // 3 point - 2 degree
386  TriangleIntRules[2] = ir = new IntegrationRule (3);
387  // interior points
388  TriangleIntRules[2]->AddTriPoints3(0, 1./6., 1./6.);
389  return ir;
390 
391  case 3: // 4 point - 3 degree (has one negative weight)
392  TriangleIntRules[3] = ir = new IntegrationRule (4);
393  ir->AddTriMidPoint(0, -0.28125); // -9./32.
394  ir->AddTriPoints3(1, 0.2, 25./96.);
395  return ir;
396 
397  case 4: // 6 point - 4 degree
398  TriangleIntRules[4] = ir = new IntegrationRule (6);
399  ir->AddTriPoints3(0, 0.091576213509770743460, 0.054975871827660933819);
400  ir->AddTriPoints3(3, 0.44594849091596488632, 0.11169079483900573285);
401  return ir;
402 
403  case 5: // 7 point - 5 degree
404  TriangleIntRules[5] = ir = new IntegrationRule (7);
405  ir->AddTriMidPoint(0, 0.1125);
406  ir->AddTriPoints3(1, 0.10128650732345633880, 0.062969590272413576298);
407  ir->AddTriPoints3(4, 0.47014206410511508977, 0.066197076394253090369);
408  return ir;
409 
410  case 6: // 12 point - 6 degree
411  TriangleIntRules[6] = ir = new IntegrationRule (12);
412  ir->AddTriPoints3(0, 0.063089014491502228340, 0.025422453185103408460);
413  ir->AddTriPoints3(3, 0.24928674517091042129, 0.058393137863189683013);
414  ir->AddTriPoints6(6, 0.053145049844816947353, 0.31035245103378440542,
415  0.041425537809186787597);
416  return ir;
417 
418  case 7: // 12 point - degree 7
419  TriangleIntRules[7] = ir = new IntegrationRule(12);
420  ir->AddTriPoints3R(0, 0.062382265094402118174, 0.067517867073916085443,
421  0.026517028157436251429);
422  ir->AddTriPoints3R(3, 0.055225456656926611737, 0.32150249385198182267,
423  0.043881408714446055037);
424  // slightly better with explicit 3rd area coordinate
425  ir->AddTriPoints3R(6, 0.034324302945097146470, 0.66094919618673565761,
426  0.30472650086816719592, 0.028775042784981585738);
427  ir->AddTriPoints3R(9, 0.51584233435359177926, 0.27771616697639178257,
428  0.20644149867001643817, 0.067493187009802774463);
429  return ir;
430 
431  case 8: // 16 point - 8 degree
432  TriangleIntRules[8] = ir = new IntegrationRule(16);
433  ir->AddTriMidPoint(0, 0.0721578038388935841255455552445323);
434  ir->AddTriPoints3(1, 0.170569307751760206622293501491464,
435  0.0516086852673591251408957751460645);
436  ir->AddTriPoints3(4, 0.0505472283170309754584235505965989,
437  0.0162292488115990401554629641708902);
438  ir->AddTriPoints3(7, 0.459292588292723156028815514494169,
439  0.0475458171336423123969480521942921);
440  ir->AddTriPoints6(10, 0.008394777409957605337213834539296,
441  0.263112829634638113421785786284643,
442  0.0136151570872174971324223450369544);
443  return ir;
444 
445  case 9: // 19 point - 9 degree
446  TriangleIntRules[9] = ir = new IntegrationRule(19);
447  ir->AddTriMidPoint(0, 0.0485678981413994169096209912536443);
448  ir->AddTriPoints3b(1, 0.020634961602524744433,
449  0.0156673501135695352684274156436046);
450  ir->AddTriPoints3b(4, 0.12582081701412672546,
451  0.0389137705023871396583696781497019);
452  ir->AddTriPoints3(7, 0.188203535619032730240961280467335,
453  0.0398238694636051265164458871320226);
454  ir->AddTriPoints3(10, 0.0447295133944527098651065899662763,
455  0.0127888378293490156308393992794999);
456  ir->AddTriPoints6(13, 0.0368384120547362836348175987833851,
457  0.2219629891607656956751025276931919,
458  0.0216417696886446886446886446886446);
459  return ir;
460 
461  case 10: // 25 point - 10 degree
462  TriangleIntRules[10] = ir = new IntegrationRule(25);
463  ir->AddTriMidPoint(0, 0.0454089951913767900476432975500142);
464  ir->AddTriPoints3b(1, 0.028844733232685245264984935583748,
465  0.0183629788782333523585030359456832);
466  ir->AddTriPoints3(4, 0.109481575485037054795458631340522,
467  0.0226605297177639673913028223692986);
468  ir->AddTriPoints6(7, 0.141707219414879954756683250476361,
469  0.307939838764120950165155022930631,
470  0.0363789584227100543021575883096803);
471  ir->AddTriPoints6(13, 0.025003534762686386073988481007746,
472  0.246672560639902693917276465411176,
473  0.0141636212655287424183685307910495);
474  ir->AddTriPoints6(19, 0.0095408154002994575801528096228873,
475  0.0668032510122002657735402127620247,
476  4.71083348186641172996373548344341E-03);
477  return ir;
478 
479  case 11: // 28 point -- 11 degree
480  TriangleIntRules[11] = ir = new IntegrationRule(28);
481  ir->AddTriPoints6(0, 0.0,
482  0.141129718717363295960826061941652,
483  3.68119189165027713212944752369032E-03);
484  ir->AddTriMidPoint(6, 0.0439886505811161193990465846607278);
485  ir->AddTriPoints3(7, 0.0259891409282873952600324854988407,
486  4.37215577686801152475821439991262E-03);
487  ir->AddTriPoints3(10, 0.0942875026479224956305697762754049,
488  0.0190407859969674687575121697178070);
489  ir->AddTriPoints3b(13, 0.010726449965572372516734795387128,
490  9.42772402806564602923839129555767E-03);
491  ir->AddTriPoints3(16, 0.207343382614511333452934024112966,
492  0.0360798487723697630620149942932315);
493  ir->AddTriPoints3b(19, 0.122184388599015809877869236727746,
494  0.0346645693527679499208828254519072);
495  ir->AddTriPoints6(22, 0.0448416775891304433090523914688007,
496  0.2772206675282791551488214673424523,
497  0.0205281577146442833208261574536469);
498  return ir;
499 
500  case 12: // 33 point - 12 degree
501  TriangleIntRules[12] = ir = new IntegrationRule(33);
502  ir->AddTriPoints3b(0, 2.35652204523900E-02, 1.28655332202275E-02);
503  ir->AddTriPoints3b(3, 1.20551215411079E-01, 2.18462722690190E-02);
504  ir->AddTriPoints3(6, 2.71210385012116E-01, 3.14291121089425E-02);
505  ir->AddTriPoints3(9, 1.27576145541586E-01, 1.73980564653545E-02);
506  ir->AddTriPoints3(12, 2.13173504532100E-02, 3.08313052577950E-03);
507  ir->AddTriPoints6(15, 1.15343494534698E-01, 2.75713269685514E-01,
508  2.01857788831905E-02);
509  ir->AddTriPoints6(21, 2.28383322222570E-02, 2.81325580989940E-01,
510  1.11783866011515E-02);
511  ir->AddTriPoints6(27, 2.57340505483300E-02, 1.16251915907597E-01,
512  8.65811555432950E-03);
513  return ir;
514 
515  case 13: // 37 point - 13 degree
516  TriangleIntRules[13] = ir = new IntegrationRule(37);
517  ir->AddTriPoints3b(0, 0.0,
518  2.67845189554543044455908674650066E-03);
519  ir->AddTriMidPoint(3, 0.0293480398063595158995969648597808);
520  ir->AddTriPoints3(4, 0.0246071886432302181878499494124643,
521  3.92538414805004016372590903990464E-03);
522  ir->AddTriPoints3b(7, 0.159382493797610632566158925635800,
523  0.0253344765879434817105476355306468);
524  ir->AddTriPoints3(10, 0.227900255506160619646298948153592,
525  0.0250401630452545330803738542916538);
526  ir->AddTriPoints3(13, 0.116213058883517905247155321839271,
527  0.0158235572961491595176634480481793);
528  ir->AddTriPoints3b(16, 0.046794039901841694097491569577008,
529  0.0157462815379843978450278590138683);
530  ir->AddTriPoints6(19, 0.0227978945382486125477207592747430,
531  0.1254265183163409177176192369310890,
532  7.90126610763037567956187298486575E-03);
533  ir->AddTriPoints6(25, 0.0162757709910885409437036075960413,
534  0.2909269114422506044621801030055257,
535  7.99081889046420266145965132482933E-03);
536  ir->AddTriPoints6(31, 0.0897330604516053590796290561145196,
537  0.2723110556841851025078181617634414,
538  0.0182757511120486476280967518782978);
539  return ir;
540 
541  case 14: // 42 point - 14 degree
542  TriangleIntRules[14] = ir = new IntegrationRule(42);
543  ir->AddTriPoints3b(0, 2.20721792756430E-02, 1.09417906847145E-02);
544  ir->AddTriPoints3b(3, 1.64710561319092E-01, 1.63941767720625E-02);
545  ir->AddTriPoints3(6, 2.73477528308839E-01, 2.58870522536460E-02);
546  ir->AddTriPoints3(9, 1.77205532412543E-01, 2.10812943684965E-02);
547  ir->AddTriPoints3(12, 6.17998830908730E-02, 7.21684983488850E-03);
548  ir->AddTriPoints3(15, 1.93909612487010E-02, 2.46170180120000E-03);
549  ir->AddTriPoints6(18, 5.71247574036480E-02, 1.72266687821356E-01,
550  1.23328766062820E-02);
551  ir->AddTriPoints6(24, 9.29162493569720E-02, 3.36861459796345E-01,
552  1.92857553935305E-02);
553  ir->AddTriPoints6(30, 1.46469500556540E-02, 2.98372882136258E-01,
554  7.21815405676700E-03);
555  ir->AddTriPoints6(36, 1.26833093287200E-03, 1.18974497696957E-01,
556  2.50511441925050E-03);
557  return ir;
558 
559  case 15: // 54 point - 15 degree
560  TriangleIntRules[15] = ir = new IntegrationRule(54);
561  ir->AddTriPoints3b(0, 0.0834384072617499333, 0.016330909424402645);
562  ir->AddTriPoints3b(3, 0.192779070841738867, 0.01370640901568218);
563  ir->AddTriPoints3(6, 0.293197167913025367, 0.01325501829935165);
564  ir->AddTriPoints3(9, 0.146467786942772933, 0.014607981068243055);
565  ir->AddTriPoints3(12, 0.0563628676656034333, 0.005292304033121995);
566  ir->AddTriPoints3(15, 0.0165751268583703333, 0.0018073215320460175);
567  ir->AddTriPoints6(18, 0.0099122033092248, 0.239534554154794445,
568  0.004263874050854718);
569  ir->AddTriPoints6(24, 0.015803770630228, 0.404878807318339958,
570  0.006958088258345965);
571  ir->AddTriPoints6(30, 0.00514360881697066667, 0.0950021131130448885,
572  0.0021459664703674175);
573  ir->AddTriPoints6(36, 0.0489223257529888, 0.149753107322273969,
574  0.008117664640887445);
575  ir->AddTriPoints6(42, 0.0687687486325192, 0.286919612441334979,
576  0.012803670460631195);
577  ir->AddTriPoints6(48, 0.1684044181246992, 0.281835668099084562,
578  0.016544097765822835);
579  return ir;
580 
581  case 16: // 61 point - 17 degree (used for 16 as well)
582  case 17:
583  TriangleIntRules[16] = TriangleIntRules[17] = ir = new IntegrationRule(61);
584  ir->AddTriMidPoint(0, 1.67185996454015E-02);
585  ir->AddTriPoints3b(1, 5.65891888645200E-03, 2.54670772025350E-03);
586  ir->AddTriPoints3b(4, 3.56473547507510E-02, 7.33543226381900E-03);
587  ir->AddTriPoints3b(7, 9.95200619584370E-02, 1.21754391768360E-02);
588  ir->AddTriPoints3b(10, 1.99467521245206E-01, 1.55537754344845E-02);
589  ir->AddTriPoints3 (13, 2.52141267970953E-01, 1.56285556093100E-02);
590  ir->AddTriPoints3 (16, 1.62047004658461E-01, 1.24078271698325E-02);
591  ir->AddTriPoints3 (19, 7.58758822607460E-02, 7.02803653527850E-03);
592  ir->AddTriPoints3 (22, 1.56547269678220E-02, 1.59733808688950E-03);
593  ir->AddTriPoints6 (25, 1.01869288269190E-02, 3.34319867363658E-01,
594  4.05982765949650E-03);
595  ir->AddTriPoints6 (31, 1.35440871671036E-01, 2.92221537796944E-01,
596  1.34028711415815E-02);
597  ir->AddTriPoints6 (37, 5.44239242905830E-02, 3.19574885423190E-01,
598  9.22999660541100E-03);
599  ir->AddTriPoints6 (43, 1.28685608336370E-02, 1.90704224192292E-01,
600  4.23843426716400E-03);
601  ir->AddTriPoints6 (49, 6.71657824135240E-02, 1.80483211648746E-01,
602  9.14639838501250E-03);
603  ir->AddTriPoints6 (55, 1.46631822248280E-02, 8.07113136795640E-02,
604  3.33281600208250E-03);
605  return ir;
606 
607  case 18: // 73 point - 19 degree (used for 18 as well)
608  case 19:
609  TriangleIntRules[18] = TriangleIntRules[19] = ir = new IntegrationRule(73);
610  ir->AddTriMidPoint(0, 0.0164531656944595);
611  ir->AddTriPoints3b(1, 0.020780025853987, 0.005165365945636);
612  ir->AddTriPoints3b(4, 0.090926214604215, 0.011193623631508);
613  ir->AddTriPoints3b(7, 0.197166638701138, 0.015133062934734);
614  ir->AddTriPoints3 (10, 0.255551654403098, 0.015245483901099);
615  ir->AddTriPoints3 (13, 0.17707794215213, 0.0120796063708205);
616  ir->AddTriPoints3 (16, 0.110061053227952, 0.0080254017934005);
617  ir->AddTriPoints3 (19, 0.05552862425184, 0.004042290130892);
618  ir->AddTriPoints3 (22, 0.012621863777229, 0.0010396810137425);
619  ir->AddTriPoints6 (25, 0.003611417848412, 0.395754787356943,
620  0.0019424384524905);
621  ir->AddTriPoints6 (31, 0.13446675453078, 0.307929983880436,
622  0.012787080306011);
623  ir->AddTriPoints6 (37, 0.014446025776115, 0.26456694840652,
624  0.004440451786669);
625  ir->AddTriPoints6 (43, 0.046933578838178, 0.358539352205951,
626  0.0080622733808655);
627  ir->AddTriPoints6 (49, 0.002861120350567, 0.157807405968595,
628  0.0012459709087455);
629  ir->AddTriPoints6 (55, 0.075050596975911, 0.223861424097916,
630  0.0091214200594755);
631  ir->AddTriPoints6 (61, 0.03464707481676, 0.142421601113383,
632  0.0051292818680995);
633  ir->AddTriPoints6 (67, 0.065494628082938, 0.010161119296278,
634  0.001899964427651);
635  return ir;
636 
637  case 20: // 85 point - 20 degree
638  TriangleIntRules[20] = ir = new IntegrationRule(85);
639  ir->AddTriMidPoint(0, 0.01380521349884976);
640  ir->AddTriPoints3b(1, 0.001500649324429, 0.00088951477366337);
641  ir->AddTriPoints3b(4, 0.0941397519389508667, 0.010056199056980585);
642  ir->AddTriPoints3b(7, 0.2044721240895264, 0.013408923629665785);
643  ir->AddTriPoints3(10, 0.264500202532787333, 0.012261566900751005);
644  ir->AddTriPoints3(13, 0.211018964092076767, 0.008197289205347695);
645  ir->AddTriPoints3(16, 0.107735607171271333, 0.0073979536993248);
646  ir->AddTriPoints3(19, 0.0390690878378026667, 0.0022896411388521255);
647  ir->AddTriPoints3(22, 0.0111743797293296333, 0.0008259132577881085);
648  ir->AddTriPoints6(25, 0.00534961818733726667, 0.0635496659083522206,
649  0.001174585454287792);
650  ir->AddTriPoints6(31, 0.00795481706619893333, 0.157106918940706982,
651  0.0022329628770908965);
652  ir->AddTriPoints6(37, 0.0104223982812638, 0.395642114364374018,
653  0.003049783403953986);
654  ir->AddTriPoints6(43, 0.0109644147961233333, 0.273167570712910522,
655  0.0034455406635941015);
656  ir->AddTriPoints6(49, 0.0385667120854623333, 0.101785382485017108,
657  0.0039987375362390815);
658  ir->AddTriPoints6(55, 0.0355805078172182, 0.446658549176413815,
659  0.003693067142668012);
660  ir->AddTriPoints6(61, 0.0496708163627641333, 0.199010794149503095,
661  0.00639966593932413);
662  ir->AddTriPoints6(67, 0.0585197250843317333, 0.3242611836922827,
663  0.008629035587848275);
664  ir->AddTriPoints6(73, 0.121497787004394267, 0.208531363210132855,
665  0.009336472951467735);
666  ir->AddTriPoints6(79, 0.140710844943938733, 0.323170566536257485,
667  0.01140911202919763);
668  return ir;
669 
670  case 21: // 126 point - 25 degree (used also for degrees from 21 to 24)
671  case 22:
672  case 23:
673  case 24:
674  case 25:
675  TriangleIntRules[21] = TriangleIntRules[22] = TriangleIntRules[23] =
676  TriangleIntRules[24] = TriangleIntRules[25] =
677  ir = new IntegrationRule(126);
678  ir->AddTriPoints3b(0, 0.0279464830731742, 0.0040027909400102085);
679  ir->AddTriPoints3b(3, 0.131178601327651467, 0.00797353841619525);
680  ir->AddTriPoints3b(6, 0.220221729512072267, 0.006554570615397765);
681  ir->AddTriPoints3 (9, 0.298443234019804467, 0.00979150048281781);
682  ir->AddTriPoints3(12, 0.2340441723373718, 0.008235442720768635);
683  ir->AddTriPoints3(15, 0.151468334609017567, 0.00427363953704605);
684  ir->AddTriPoints3(18, 0.112733893545993667, 0.004080942928613246);
685  ir->AddTriPoints3(21, 0.0777156920915263, 0.0030605732699918895);
686  ir->AddTriPoints3(24, 0.034893093614297, 0.0014542491324683325);
687  ir->AddTriPoints3(27, 0.00725818462093236667, 0.00034613762283099815);
688  ir->AddTriPoints6(30, 0.0012923527044422, 0.227214452153364077,
689  0.0006241445996386985);
690  ir->AddTriPoints6(36, 0.0053997012721162, 0.435010554853571706,
691  0.001702376454401511);
692  ir->AddTriPoints6(42, 0.006384003033975, 0.320309599272204437,
693  0.0016798271630320255);
694  ir->AddTriPoints6(48, 0.00502821150199306667, 0.0917503222800051889,
695  0.000858078269748377);
696  ir->AddTriPoints6(54, 0.00682675862178186667, 0.0380108358587243835,
697  0.000740428158357803);
698  ir->AddTriPoints6(60, 0.0100161996399295333, 0.157425218485311668,
699  0.0017556563053643425);
700  ir->AddTriPoints6(66, 0.02575781317339, 0.239889659778533193,
701  0.003696775074853242);
702  ir->AddTriPoints6(72, 0.0302278981199158, 0.361943118126060531,
703  0.003991543738688279);
704  ir->AddTriPoints6(78, 0.0305049901071620667, 0.0835519609548285602,
705  0.0021779813065790205);
706  ir->AddTriPoints6(84, 0.0459565473625693333, 0.148443220732418205,
707  0.003682528350708916);
708  ir->AddTriPoints6(90, 0.0674428005402775333, 0.283739708727534955,
709  0.005481786423209775);
710  ir->AddTriPoints6(96, 0.0700450914159106, 0.406899375118787573,
711  0.00587498087177056);
712  ir->AddTriPoints6(102, 0.0839115246401166, 0.194113987024892542,
713  0.005007800356899285);
714  ir->AddTriPoints6(108, 0.120375535677152667, 0.32413434700070316,
715  0.00665482039381434);
716  ir->AddTriPoints6(114, 0.148066899157366667, 0.229277483555980969,
717  0.00707722325261307);
718  ir->AddTriPoints6(120, 0.191771865867325067, 0.325618122595983752,
719  0.007440689780584005);
720  return ir;
721 
722  default:
723  // Grundmann-Moller rules
724  int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
725  AllocIntRule(TriangleIntRules, i);
726  TriangleIntRules[i-1] = TriangleIntRules[i] = ir = new IntegrationRule;
727  ir->GrundmannMollerSimplexRule(i/2,2);
728  return ir;
729  }
730 }
731 
732 // Integration rules for unit square
733 IntegrationRule *IntegrationRules::SquareIntegrationRule(int Order)
734 {
735  int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
736 
737  if (!HaveIntRule(SegmentIntRules, i))
738  SegmentIntegrationRule(i);
739  AllocIntRule(SquareIntRules, i);
740  SquareIntRules[i-1] = SquareIntRules[i] =
741  new IntegrationRule(*SegmentIntRules[i], *SegmentIntRules[i]);
742  return SquareIntRules[i];
743 }
744 
747 IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
748 {
749  IntegrationRule *ir;
750 
751  // assuming that orders <= 9 are pre-allocated
752  switch (Order)
753  {
754  case 0: // 1 point - degree 1
755  case 1:
756  TetrahedronIntRules[0] =
757  TetrahedronIntRules[1] = ir = new IntegrationRule (1);
758  ir->AddTetMidPoint(0, 1./6.);
759  return ir;
760 
761  case 2: // 4 points - degree 2
762  TetrahedronIntRules[2] = ir = new IntegrationRule (4);
763  // ir->AddTetPoints4(0, 0.13819660112501051518, 1./24.);
764  ir->AddTetPoints4b(0, 0.58541019662496845446, 1./24.);
765  return ir;
766 
767  case 3: // 5 points - degree 3 (negative weight)
768  TetrahedronIntRules[3] = ir = new IntegrationRule (5);
769  ir->AddTetMidPoint(0, -2./15.);
770  ir->AddTetPoints4b(1, 0.5, 0.075);
771  return ir;
772 
773  case 4: // 11 points - degree 4 (negative weight)
774  TetrahedronIntRules[4] = ir = new IntegrationRule (11);
775  ir->AddTetPoints4(0, 1./14., 343./45000.);
776  ir->AddTetMidPoint(4, -74./5625.);
777  ir->AddTetPoints6(5, 0.10059642383320079500, 28./1125.);
778  return ir;
779 
780  case 5: // 14 points - degree 5
781  TetrahedronIntRules[5] = ir = new IntegrationRule (14);
782  ir->AddTetPoints6(0, 0.045503704125649649492, 7.0910034628469110730E-03);
783  ir->AddTetPoints4(6, 0.092735250310891226402, 0.012248840519393658257);
784  ir->AddTetPoints4b(10, 0.067342242210098170608, 0.018781320953002641800);
785  return ir;
786 
787  case 6: // 24 points - degree 6
788  TetrahedronIntRules[6] = ir = new IntegrationRule (24);
789  ir->AddTetPoints4(0, 0.21460287125915202929, 6.6537917096945820166E-03);
790  ir->AddTetPoints4(4, 0.040673958534611353116, 1.6795351758867738247E-03);
791  ir->AddTetPoints4b(8, 0.032986329573173468968, 9.2261969239424536825E-03);
792  ir->AddTetPoints12(12, 0.063661001875017525299, 0.26967233145831580803,
793  8.0357142857142857143E-03);
794  return ir;
795 
796  case 7: // 31 points - degree 7 (negative weight)
797  TetrahedronIntRules[7] = ir = new IntegrationRule (31);
798  ir->AddTetPoints6(0, 0.0, 9.7001763668430335097E-04);
799  ir->AddTetMidPoint(6, 0.018264223466108820291);
800  ir->AddTetPoints4(7, 0.078213192330318064374, 0.010599941524413686916);
801  ir->AddTetPoints4(11, 0.12184321666390517465, -0.062517740114331851691);
802  ir->AddTetPoints4b(15, 2.3825066607381275412E-03, 4.8914252630734993858E-03);
803  ir->AddTetPoints12(19, 0.1, 0.2, 0.027557319223985890653);
804  return ir;
805 
806  case 8: // 43 points - degree 8 (negative weight)
807  TetrahedronIntRules[8] = ir = new IntegrationRule (43);
808  ir->AddTetPoints4(0, 5.7819505051979972532E-03, 1.6983410909288737984E-04);
809  ir->AddTetPoints4(4, 0.082103588310546723091, 1.9670333131339009876E-03);
810  ir->AddTetPoints12(8, 0.036607749553197423679, 0.19048604193463345570,
811  2.1405191411620925965E-03);
812  ir->AddTetPoints6(20, 0.050532740018894224426, 4.5796838244672818007E-03);
813  ir->AddTetPoints12(26, 0.22906653611681113960, 0.035639582788534043717,
814  5.7044858086819185068E-03);
815  ir->AddTetPoints4(38, 0.20682993161067320408, 0.014250305822866901248);
816  ir->AddTetMidPoint(42, -0.020500188658639915841);
817  return ir;
818 
819  case 9: // orders 9 and higher -- Grundmann-Moller rules
820  TetrahedronIntRules[9] = ir = new IntegrationRule;
821  ir->GrundmannMollerSimplexRule(4,3);
822  return ir;
823 
824  default: // Grundmann-Moller rules
825  int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
826  AllocIntRule(TetrahedronIntRules, i);
827  TetrahedronIntRules[i-1] = TetrahedronIntRules[i] = ir = new IntegrationRule;
828  ir->GrundmannMollerSimplexRule(i/2,3);
829  return ir;
830  }
831 }
832 
834 IntegrationRule *IntegrationRules::CubeIntegrationRule(int Order)
835 {
836  int k, l, m, np;
837  int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
838 
839  if (!HaveIntRule(SegmentIntRules, i))
840  SegmentIntegrationRule(i);
841  AllocIntRule(CubeIntRules, i);
842  np = SegmentIntRules[i] -> GetNPoints();
843  CubeIntRules[i-1] = CubeIntRules[i] = new IntegrationRule(np*np*np);
844  for (k = 0; k < np; k++)
845  for (l = 0; l < np; l++)
846  for (m = 0; m < np; m++)
847  {
848  CubeIntRules[i] -> IntPoint((k*np+l)*np+m).x =
849  SegmentIntRules[i] -> IntPoint(m).x;
850 
851  CubeIntRules[i] -> IntPoint((k*np+l)*np+m).y =
852  SegmentIntRules[i] -> IntPoint(l).x;
853 
854  CubeIntRules[i] -> IntPoint((k*np+l)*np+m).z =
855  SegmentIntRules[i] -> IntPoint(k).x;
856 
857  CubeIntRules[i] -> IntPoint((k*np+l)*np+m).weight =
858  SegmentIntRules[i] -> IntPoint(k).weight *
859  SegmentIntRules[i] -> IntPoint(l).weight *
860  SegmentIntRules[i] -> IntPoint(m).weight;
861  }
862  return CubeIntRules[i];
863 }
864 
865 }
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition: intrules.hpp:202
int Size() const
Logical size of the array.
Definition: array.hpp:108
Class for integration rule.
Definition: intrules.hpp:63
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition: intrules.hpp:205
IntegrationRules IntRules(0)
A global object with all integration rules (defined in intrules.cpp)
Definition: intrules.hpp:264
void mfem_error(const char *msg)
Definition: error.cpp:23
Class for integration point with weight.
Definition: intrules.hpp:25
IntegrationRules RefinedIntRules(1)
A global object with all refined integration rules.
Definition: intrules.hpp:267