$extrastylesheet
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