$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 00020 // Local includes 00021 #include "libmesh/quadrature_monomial.h" 00022 #include "libmesh/quadrature_gauss.h" 00023 00024 namespace libMesh 00025 { 00026 00027 00028 void QMonomial::init_3D(const ElemType type_in, 00029 unsigned int p) 00030 { 00031 00032 switch (type_in) 00033 { 00034 //--------------------------------------------- 00035 // Hex quadrature rules 00036 case HEX8: 00037 case HEX20: 00038 case HEX27: 00039 { 00040 switch(_order + 2*p) 00041 { 00042 00043 // The CONSTANT/FIRST rule is the 1-point Gauss "product" rule...we fall 00044 // through to the default case for this rule. 00045 00046 case SECOND: 00047 case THIRD: 00048 { 00049 // A degree 3, 6-point, "rotationally-symmetric" rule by 00050 // Kim and Song, Comm. Korean Math. Soc vol. 13, no. 4, 1998, pp. 913-931. 00051 // 00052 // Warning: this rule contains points on the boundary of the reference 00053 // element, and therefore may be unsuitable for some problems. The alternative 00054 // would be a 2x2x2 Gauss product rule. 00055 const Real data[1][4] = 00056 { 00057 {1.0L, 0.0L, 0.0L, static_cast<Real>(4.0L/3.0L)} 00058 }; 00059 00060 const unsigned int rule_id[1] = { 00061 1 // (x,0,0) -> 6 permutations 00062 }; 00063 00064 _points.resize(6); 00065 _weights.resize(6); 00066 00067 kim_rule(data, rule_id, 1); 00068 return; 00069 } // end case SECOND,THIRD 00070 00071 case FOURTH: 00072 case FIFTH: 00073 { 00074 // A degree 5, 13-point rule by Stroud, 00075 // AH Stroud, "Some Fifth Degree Integration Formulas for Symmetric Regions II.", 00076 // Numerische Mathematik 9, pp. 460-468 (1967). 00077 // 00078 // This rule is provably minimal in the number of points. The equations given for 00079 // the n-cube on pg. 466 of the paper for mu/gamma and gamma are wrong, at least for 00080 // the n=3 case. The analytical values given here were computed by me [JWP] in Maple. 00081 00082 // Convenient intermediate values. 00083 const Real sqrt19 = std::sqrt(19.L); 00084 const Real tp = std::sqrt(71440.L + 6802.L*sqrt19); 00085 00086 // Point data for permutations. 00087 const Real eta = 0.00000000000000000000000000000000e+00L; 00088 00089 const Real lambda = std::sqrt(1919.L/3285.L - 148.L*sqrt19/3285.L + 4.L*tp/3285.L); 00090 // 8.8030440669930978047737818209860e-01L; 00091 00092 const Real xi = -std::sqrt(1121.L/3285.L + 74.L*sqrt19/3285.L - 2.L*tp/3285.L); 00093 // -4.9584817142571115281421242364290e-01L; 00094 00095 const Real mu = std::sqrt(1121.L/3285.L + 74.L*sqrt19/3285.L + 2.L*tp/3285.L); 00096 // 7.9562142216409541542982482567580e-01L; 00097 00098 const Real gamma = std::sqrt(1919.L/3285.L - 148.L*sqrt19/3285.L - 4.L*tp/3285.L); 00099 // 2.5293711744842581347389255929324e-02L; 00100 00101 // Weights: the centroid weight is given analytically. Weight B (resp C) goes 00102 // with the {lambda,xi} (resp {gamma,mu}) permutation. The single-precision 00103 // results reported by Stroud are given for reference. 00104 00105 const Real A = 32.0L / 19.0L; 00106 // Stroud: 0.21052632 * 8.0 = 1.684210560; 00107 00108 const Real B = 1.L / ( 260072.L/133225.L - 1520*sqrt19/133225.L + (133.L - 37.L*sqrt19)*tp/133225.L ); 00109 // 5.4498735127757671684690782180890e-01L; // Stroud: 0.068123420 * 8.0 = 0.544987360; 00110 00111 const Real C = 1.L / ( 260072.L/133225.L - 1520*sqrt19/133225.L - (133.L - 37.L*sqrt19)*tp/133225.L ); 00112 // 5.0764422766979170420572375713840e-01L; // Stroud: 0.063455527 * 8.0 = 0.507644216; 00113 00114 _points.resize(13); 00115 _weights.resize(13); 00116 00117 unsigned int c=0; 00118 00119 // Point with weight A (origin) 00120 _points[c] = Point(eta, eta, eta); 00121 _weights[c++] = A; 00122 00123 // Points with weight B 00124 _points[c] = Point(lambda, xi, xi); 00125 _weights[c++] = B; 00126 _points[c] = -_points[c-1]; 00127 _weights[c++] = B; 00128 00129 _points[c] = Point(xi, lambda, xi); 00130 _weights[c++] = B; 00131 _points[c] = -_points[c-1]; 00132 _weights[c++] = B; 00133 00134 _points[c] = Point(xi, xi, lambda); 00135 _weights[c++] = B; 00136 _points[c] = -_points[c-1]; 00137 _weights[c++] = B; 00138 00139 // Points with weight C 00140 _points[c] = Point(mu, mu, gamma); 00141 _weights[c++] = C; 00142 _points[c] = -_points[c-1]; 00143 _weights[c++] = C; 00144 00145 _points[c] = Point(mu, gamma, mu); 00146 _weights[c++] = C; 00147 _points[c] = -_points[c-1]; 00148 _weights[c++] = C; 00149 00150 _points[c] = Point(gamma, mu, mu); 00151 _weights[c++] = C; 00152 _points[c] = -_points[c-1]; 00153 _weights[c++] = C; 00154 00155 return; 00156 00157 00158 // // A degree 5, 14-point, "rotationally-symmetric" rule by 00159 // // Kim and Song, Comm. Korean Math. Soc vol. 13, no. 4, 1998, pp. 913-931. 00160 // // Was also reported in Stroud's 1971 book. 00161 // const Real data[2][4] = 00162 // { 00163 // {7.95822425754221463264548820476135e-01L, 0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 8.86426592797783933518005540166204e-01L}, 00164 // {7.58786910639328146269034278112267e-01L, 7.58786910639328146269034278112267e-01L, 7.58786910639328146269034278112267e-01L, 3.35180055401662049861495844875346e-01L} 00165 // }; 00166 00167 // const unsigned int rule_id[2] = { 00168 // 1, // (x,0,0) -> 6 permutations 00169 // 4 // (x,x,x) -> 8 permutations 00170 // }; 00171 00172 // _points.resize(14); 00173 // _weights.resize(14); 00174 00175 // kim_rule(data, rule_id, 2); 00176 // return; 00177 } // end case FOURTH,FIFTH 00178 00179 case SIXTH: 00180 case SEVENTH: 00181 { 00182 if (allow_rules_with_negative_weights) 00183 { 00184 // A degree 7, 31-point, "rotationally-symmetric" rule by 00185 // Kim and Song, Comm. Korean Math. Soc vol. 13, no. 4, 1998, pp. 913-931. 00186 // This rule contains a negative weight, so only use it if such type of 00187 // rules are allowed. 00188 const Real data[3][4] = 00189 { 00190 {0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, -1.27536231884057971014492753623188e+00L}, 00191 {5.85540043769119907612630781744060e-01L, 0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 8.71111111111111111111111111111111e-01L}, 00192 {6.94470135991704766602025803883310e-01L, 9.37161638568208038511047377665396e-01L, 4.15659267604065126239606672567031e-01L, 1.68695652173913043478260869565217e-01L} 00193 }; 00194 00195 const unsigned int rule_id[3] = { 00196 0, // (0,0,0) -> 1 permutation 00197 1, // (x,0,0) -> 6 permutations 00198 6 // (x,y,z) -> 24 permutations 00199 }; 00200 00201 _points.resize(31); 00202 _weights.resize(31); 00203 00204 kim_rule(data, rule_id, 3); 00205 return; 00206 } // end if (allow_rules_with_negative_weights) 00207 00208 00209 // A degree 7, 34-point, "fully-symmetric" rule, first published in 00210 // P.C. Hammer and A.H. Stroud, "Numerical Evaluation of Multiple Integrals II", 00211 // Mathmatical Tables and Other Aids to Computation, vol 12., no 64, 1958, pp. 272-280 00212 // 00213 // This rule happens to fall under the same general 00214 // construction as the Kim rules, so we've re-used 00215 // that code here. Stroud gives 16 digits for his rule, 00216 // and this is the most accurate version I've found. 00217 // 00218 // For comparison, a SEVENTH-order Gauss product rule 00219 // (which integrates tri-7th order polynomials) would 00220 // have 4^3=64 points. 00221 const Real 00222 r = std::sqrt(6.L/7.L), 00223 s = std::sqrt((960.L - 3.L*std::sqrt(28798.L)) / 2726.L), 00224 t = std::sqrt((960.L + 3.L*std::sqrt(28798.L)) / 2726.L), 00225 B1 = 8624.L / 29160.L, 00226 B2 = 2744.L / 29160.L, 00227 B3 = 8.L*(774.L*t*t - 230.L)/(9720.L*(t*t-s*s)), 00228 B4 = 8.L*(230.L - 774.L*s*s)/(9720.L*(t*t-s*s)); 00229 00230 const Real data[4][4] = 00231 { 00232 {r, 0.L, 0.L, B1}, 00233 {r, r, 0.L, B2}, 00234 {s, s, s, B3}, 00235 {t, t, t, B4} 00236 }; 00237 00238 const unsigned int rule_id[4] = { 00239 1, // (x,0,0) -> 6 permutations 00240 2, // (x,x,0) -> 12 permutations 00241 4, // (x,x,x) -> 8 permutations 00242 4 // (x,x,x) -> 8 permutations 00243 }; 00244 00245 _points.resize(34); 00246 _weights.resize(34); 00247 00248 kim_rule(data, rule_id, 4); 00249 return; 00250 00251 00252 // // A degree 7, 38-point, "rotationally-symmetric" rule by 00253 // // Kim and Song, Comm. Korean Math. Soc vol. 13, no. 4, 1998, pp. 913-931. 00254 // // 00255 // // This rule is obviously inferior to the 34-point rule above... 00256 // const Real data[3][4] = 00257 //{ 00258 // {9.01687807821291289082811566285950e-01L, 0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 2.95189738262622903181631100062774e-01L}, 00259 // {4.08372221499474674069588900002128e-01L, 4.08372221499474674069588900002128e-01L, 4.08372221499474674069588900002128e-01L, 4.04055417266200582425904380777126e-01L}, 00260 // {8.59523090201054193116477875786220e-01L, 8.59523090201054193116477875786220e-01L, 4.14735913727987720499709244748633e-01L, 1.24850759678944080062624098058597e-01L} 00261 //}; 00262 // 00263 // const unsigned int rule_id[3] = { 00264 //1, // (x,0,0) -> 6 permutations 00265 //4, // (x,x,x) -> 8 permutations 00266 //5 // (x,x,z) -> 24 permutations 00267 // }; 00268 // 00269 // _points.resize(38); 00270 // _weights.resize(38); 00271 // 00272 // kim_rule(data, rule_id, 3); 00273 // return; 00274 } // end case SIXTH,SEVENTH 00275 00276 case EIGHTH: 00277 { 00278 // A degree 8, 47-point, "rotationally-symmetric" rule by 00279 // Kim and Song, Comm. Korean Math. Soc vol. 13, no. 4, 1998, pp. 913-931. 00280 // 00281 // A EIGHTH-order Gauss product rule (which integrates tri-8th order polynomials) 00282 // would have 5^3=125 points. 00283 const Real data[5][4] = 00284 { 00285 {0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 4.51903714875199690490763818699555e-01L}, 00286 {7.82460796435951590652813975429717e-01L, 0.00000000000000000000000000000000e+00L, 0.00000000000000000000000000000000e+00L, 2.99379177352338919703385618576171e-01L}, 00287 {4.88094669706366480526729301468686e-01L, 4.88094669706366480526729301468686e-01L, 4.88094669706366480526729301468686e-01L, 3.00876159371240019939698689791164e-01L}, 00288 {8.62218927661481188856422891110042e-01L, 8.62218927661481188856422891110042e-01L, 8.62218927661481188856422891110042e-01L, 4.94843255877038125738173175714853e-02L}, 00289 {2.81113909408341856058098281846420e-01L, 9.44196578292008195318687494773744e-01L, 6.97574833707236996779391729948984e-01L, 1.22872389222467338799199767122592e-01L} 00290 }; 00291 00292 const unsigned int rule_id[5] = { 00293 0, // (0,0,0) -> 1 permutation 00294 1, // (x,0,0) -> 6 permutations 00295 4, // (x,x,x) -> 8 permutations 00296 4, // (x,x,x) -> 8 permutations 00297 6 // (x,y,z) -> 24 permutations 00298 }; 00299 00300 _points.resize(47); 00301 _weights.resize(47); 00302 00303 kim_rule(data, rule_id, 5); 00304 return; 00305 } // end case EIGHTH 00306 00307 00308 // By default: construct and use a Gauss quadrature rule 00309 default: 00310 { 00311 // Break out and fall down into the default: case for the 00312 // outer switch statement. 00313 break; 00314 } 00315 00316 } // end switch(_order + 2*p) 00317 } // end case HEX8/20/27 00318 00319 00320 // By default: construct and use a Gauss quadrature rule 00321 default: 00322 { 00323 QGauss gauss_rule(3, _order); 00324 gauss_rule.init(type_in, p); 00325 00326 // Swap points and weights with the about-to-be destroyed rule. 00327 _points.swap (gauss_rule.get_points() ); 00328 _weights.swap(gauss_rule.get_weights()); 00329 00330 return; 00331 } 00332 } // end switch (type_in) 00333 } 00334 00335 } // namespace libMesh