$extrastylesheet
quadrature_gauss.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 #include "libmesh/quadrature_gauss.h"
00020 
00021 namespace libMesh
00022 {
00023 
00024 // See the files:
00025 
00026 // quadrature_gauss_1D.C
00027 // quadrature_gauss_2D.C
00028 // quadrature_gauss_3D.C
00029 
00030 // for implementation of specific element types.
00031 
00032 
00033 void QGauss::keast_rule(const Real rule_data[][4],
00034                         const unsigned int n_pts)
00035 {
00036   // Like the Dunavant rule, the input data should have 4 columns.  These columns
00037   // have the following format and implied permutations (w=weight).
00038   // {a, 0, 0, w} = 1-permutation  (a,a,a)
00039   // {a, b, 0, w} = 4-permutation  (a,b,b), (b,a,b), (b,b,a), (b,b,b)
00040   // {a, 0, b, w} = 6-permutation  (a,a,b), (a,b,b), (b,b,a), (b,a,b), (b,a,a), (a,b,a)
00041   // {a, b, c, w} = 12-permutation (a,a,b), (a,a,c), (b,a,a), (c,a,a), (a,b,a), (a,c,a)
00042   //                               (a,b,c), (a,c,b), (b,a,c), (b,c,a), (c,a,b), (c,b,a)
00043 
00044   // Always insert into the points & weights vector relative to the offset
00045   unsigned int offset=0;
00046 
00047 
00048   for (unsigned int p=0; p<n_pts; ++p)
00049     {
00050 
00051       // There must always be a non-zero entry to start the row
00052       libmesh_assert_not_equal_to (rule_data[p][0], static_cast<Real>(0.0));
00053 
00054       // A zero weight may imply you did not set up the raw data correctly
00055       libmesh_assert_not_equal_to (rule_data[p][3], static_cast<Real>(0.0));
00056 
00057       // What kind of point is this?
00058       // One non-zero entry in first 3 cols   ? 1-perm (centroid) point = 1
00059       // Two non-zero entries in first 3 cols ? 3-perm point            = 3
00060       // Three non-zero entries               ? 6-perm point            = 6
00061       unsigned int pointtype=1;
00062 
00063       if (rule_data[p][1] != static_cast<Real>(0.0))
00064         {
00065           if (rule_data[p][2] != static_cast<Real>(0.0))
00066             pointtype = 12;
00067           else
00068             pointtype = 4;
00069         }
00070       else
00071         {
00072           // The second entry is zero.  What about the third?
00073           if (rule_data[p][2] != static_cast<Real>(0.0))
00074             pointtype = 6;
00075         }
00076 
00077 
00078       switch (pointtype)
00079         {
00080         case 1:
00081           {
00082             // Be sure we have enough space to insert this point
00083             libmesh_assert_less (offset + 0, _points.size());
00084 
00085             const Real a = rule_data[p][0];
00086 
00087             // The point has only a single permutation (the centroid!)
00088             _points[offset  + 0] = Point(a,a,a);
00089 
00090             // The weight is always the last entry in the row.
00091             _weights[offset + 0] = rule_data[p][3];
00092 
00093             offset += pointtype;
00094             break;
00095           }
00096 
00097         case 4:
00098           {
00099             // Be sure we have enough space to insert these points
00100             libmesh_assert_less (offset + 3, _points.size());
00101 
00102             const Real a  = rule_data[p][0];
00103             const Real b  = rule_data[p][1];
00104             const Real wt = rule_data[p][3];
00105 
00106             // Here it's understood the second entry is to be used twice, and
00107             // thus there are three possible permutations.
00108             _points[offset + 0] = Point(a,b,b);
00109             _points[offset + 1] = Point(b,a,b);
00110             _points[offset + 2] = Point(b,b,a);
00111             _points[offset + 3] = Point(b,b,b);
00112 
00113             for (unsigned int j=0; j<pointtype; ++j)
00114               _weights[offset + j] = wt;
00115 
00116             offset += pointtype;
00117             break;
00118           }
00119 
00120         case 6:
00121           {
00122             // Be sure we have enough space to insert these points
00123             libmesh_assert_less (offset + 5, _points.size());
00124 
00125             const Real a  = rule_data[p][0];
00126             const Real b  = rule_data[p][2];
00127             const Real wt = rule_data[p][3];
00128 
00129             // Three individual entries with six permutations.
00130             _points[offset + 0] = Point(a,a,b);
00131             _points[offset + 1] = Point(a,b,b);
00132             _points[offset + 2] = Point(b,b,a);
00133             _points[offset + 3] = Point(b,a,b);
00134             _points[offset + 4] = Point(b,a,a);
00135             _points[offset + 5] = Point(a,b,a);
00136 
00137             for (unsigned int j=0; j<pointtype; ++j)
00138               _weights[offset + j] = wt;
00139 
00140             offset += pointtype;
00141             break;
00142           }
00143 
00144 
00145         case 12:
00146           {
00147             // Be sure we have enough space to insert these points
00148             libmesh_assert_less (offset + 11, _points.size());
00149 
00150             const Real a  = rule_data[p][0];
00151             const Real b  = rule_data[p][1];
00152             const Real c  = rule_data[p][2];
00153             const Real wt = rule_data[p][3];
00154 
00155             // Three individual entries with six permutations.
00156             _points[offset + 0] = Point(a,a,b);  _points[offset + 6]  = Point(a,b,c);
00157             _points[offset + 1] = Point(a,a,c); _points[offset + 7]  = Point(a,c,b);
00158             _points[offset + 2] = Point(b,a,a); _points[offset + 8]  = Point(b,a,c);
00159             _points[offset + 3] = Point(c,a,a); _points[offset + 9]  = Point(b,c,a);
00160             _points[offset + 4] = Point(a,b,a); _points[offset + 10] = Point(c,a,b);
00161             _points[offset + 5] = Point(a,c,a); _points[offset + 11] = Point(c,b,a);
00162 
00163             for (unsigned int j=0; j<pointtype; ++j)
00164               _weights[offset + j] = wt;
00165 
00166             offset += pointtype;
00167             break;
00168           }
00169 
00170         default:
00171           libmesh_error_msg("Don't know what to do with this many permutation points!");
00172         }
00173 
00174     }
00175 
00176 }
00177 
00178 
00179 // A number of different rules for triangles can be described by
00180 // permutations of the following types of points:
00181 // I:   "1"-permutation, (1/3,1/3)  (single point only)
00182 // II:   3-permutation, (a,a,1-2a)
00183 // III:  6-permutation, (a,b,1-a-b)
00184 // The weights for a given set of permutations are all the same.
00185 void QGauss::dunavant_rule2(const Real* wts,
00186                             const Real* a,
00187                             const Real* b,
00188                             const unsigned int* permutation_ids,
00189                             unsigned int n_wts)
00190 {
00191   // Figure out how many total points by summing up the entries
00192   // in the permutation_ids array, and resize the _points and _weights
00193   // vectors appropriately.
00194   unsigned int total_pts = 0;
00195   for (unsigned int p=0; p<n_wts; ++p)
00196     total_pts += permutation_ids[p];
00197 
00198   // Resize point and weight vectors appropriately.
00199   _points.resize(total_pts);
00200   _weights.resize(total_pts);
00201 
00202   // Always insert into the points & weights vector relative to the offset
00203   unsigned int offset=0;
00204 
00205   for (unsigned int p=0; p<n_wts; ++p)
00206     {
00207       switch (permutation_ids[p])
00208         {
00209         case 1:
00210           {
00211             // The point has only a single permutation (the centroid!)
00212             // So we don't even need to look in the a or b arrays.
00213             _points [offset  + 0] = Point(1.0L/3.0L, 1.0L/3.0L);
00214             _weights[offset + 0] = wts[p];
00215 
00216             offset += 1;
00217             break;
00218           }
00219 
00220 
00221         case 3:
00222           {
00223             // For this type of rule, don't need to look in the b array.
00224             _points[offset + 0] = Point(a[p],         a[p]);         // (a,a)
00225             _points[offset + 1] = Point(a[p],         1.L-2.L*a[p]); // (a,1-2a)
00226             _points[offset + 2] = Point(1.L-2.L*a[p], a[p]);         // (1-2a,a)
00227 
00228             for (unsigned int j=0; j<3; ++j)
00229               _weights[offset + j] = wts[p];
00230 
00231             offset += 3;
00232             break;
00233           }
00234 
00235         case 6:
00236           {
00237             // This type of point uses all 3 arrays...
00238             _points[offset + 0] = Point(a[p], b[p]);
00239             _points[offset + 1] = Point(b[p], a[p]);
00240             _points[offset + 2] = Point(a[p], 1.L-a[p]-b[p]);
00241             _points[offset + 3] = Point(1.L-a[p]-b[p], a[p]);
00242             _points[offset + 4] = Point(b[p], 1.L-a[p]-b[p]);
00243             _points[offset + 5] = Point(1.L-a[p]-b[p], b[p]);
00244 
00245             for (unsigned int j=0; j<6; ++j)
00246               _weights[offset + j] = wts[p];
00247 
00248             offset += 6;
00249             break;
00250           }
00251 
00252         default:
00253           libmesh_error_msg("Unknown permutation id: " << permutation_ids[p] << "!");
00254         }
00255     }
00256 
00257 }
00258 
00259 
00260 void QGauss::dunavant_rule(const Real rule_data[][4],
00261                            const unsigned int n_pts)
00262 {
00263   // The input data array has 4 columns.  The first 3 are the permutation points.
00264   // The last column is the weights for a given set of permutation points.  A zero
00265   // in two of the first 3 columns implies the point is a 1-permutation (centroid).
00266   // A zero in one of the first 3 columns implies the point is a 3-permutation.
00267   // Otherwise each point is assumed to be a 6-permutation.
00268 
00269   // Always insert into the points & weights vector relative to the offset
00270   unsigned int offset=0;
00271 
00272 
00273   for (unsigned int p=0; p<n_pts; ++p)
00274     {
00275 
00276       // There must always be a non-zero entry to start the row
00277       libmesh_assert_not_equal_to ( rule_data[p][0], static_cast<Real>(0.0) );
00278 
00279       // A zero weight may imply you did not set up the raw data correctly
00280       libmesh_assert_not_equal_to ( rule_data[p][3], static_cast<Real>(0.0) );
00281 
00282       // What kind of point is this?
00283       // One non-zero entry in first 3 cols   ? 1-perm (centroid) point = 1
00284       // Two non-zero entries in first 3 cols ? 3-perm point            = 3
00285       // Three non-zero entries               ? 6-perm point            = 6
00286       unsigned int pointtype=1;
00287 
00288       if (rule_data[p][1] != static_cast<Real>(0.0))
00289         {
00290           if (rule_data[p][2] != static_cast<Real>(0.0))
00291             pointtype = 6;
00292           else
00293             pointtype = 3;
00294         }
00295 
00296       switch (pointtype)
00297         {
00298         case 1:
00299           {
00300             // Be sure we have enough space to insert this point
00301             libmesh_assert_less (offset + 0, _points.size());
00302 
00303             // The point has only a single permutation (the centroid!)
00304             _points[offset  + 0] = Point(rule_data[p][0], rule_data[p][0]);
00305 
00306             // The weight is always the last entry in the row.
00307             _weights[offset + 0] = rule_data[p][3];
00308 
00309             offset += 1;
00310             break;
00311           }
00312 
00313         case 3:
00314           {
00315             // Be sure we have enough space to insert these points
00316             libmesh_assert_less (offset + 2, _points.size());
00317 
00318             // Here it's understood the second entry is to be used twice, and
00319             // thus there are three possible permutations.
00320             _points[offset + 0] = Point(rule_data[p][0], rule_data[p][1]);
00321             _points[offset + 1] = Point(rule_data[p][1], rule_data[p][0]);
00322             _points[offset + 2] = Point(rule_data[p][1], rule_data[p][1]);
00323 
00324             for (unsigned int j=0; j<3; ++j)
00325               _weights[offset + j] = rule_data[p][3];
00326 
00327             offset += 3;
00328             break;
00329           }
00330 
00331         case 6:
00332           {
00333             // Be sure we have enough space to insert these points
00334             libmesh_assert_less (offset + 5, _points.size());
00335 
00336             // Three individual entries with six permutations.
00337             _points[offset + 0] = Point(rule_data[p][0], rule_data[p][1]);
00338             _points[offset + 1] = Point(rule_data[p][0], rule_data[p][2]);
00339             _points[offset + 2] = Point(rule_data[p][1], rule_data[p][0]);
00340             _points[offset + 3] = Point(rule_data[p][1], rule_data[p][2]);
00341             _points[offset + 4] = Point(rule_data[p][2], rule_data[p][0]);
00342             _points[offset + 5] = Point(rule_data[p][2], rule_data[p][1]);
00343 
00344             for (unsigned int j=0; j<6; ++j)
00345               _weights[offset + j] = rule_data[p][3];
00346 
00347             offset += 6;
00348             break;
00349           }
00350 
00351         default:
00352           libmesh_error_msg("Don't know what to do with this many permutation points!");
00353         }
00354     }
00355 }
00356 
00357 } // namespace libMesh