$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_conical.h" 00020 #include "libmesh/quadrature_gauss.h" 00021 #include "libmesh/quadrature_jacobi.h" 00022 00023 namespace libMesh 00024 { 00025 00026 // See also the files: 00027 // quadrature_conical_2D.C 00028 // quadrature_conical_3D.C 00029 // for additional implementation. 00030 00031 00032 00033 00034 // Constructor 00035 QConical::QConical(const unsigned int d, 00036 const Order o) : QBase(d,o) 00037 { 00038 } 00039 00040 00041 00042 // Destructor 00043 QConical::~QConical() 00044 { 00045 } 00046 00047 00048 00049 // Builds and scales a Gauss rule and a Jacobi rule. 00050 // Then combines them to compute points and weights 00051 // of a 2D conical product rule. 00052 void QConical::conical_product_tri(unsigned int p) 00053 { 00054 // Be sure the underlying rule object was built with the same dimension as the 00055 // rule we are about to construct. 00056 libmesh_assert_equal_to (this->get_dim(), 2); 00057 00058 QGauss gauss1D(1,static_cast<Order>(_order+2*p)); 00059 QJacobi jac1D(1,static_cast<Order>(_order+2*p),1,0); 00060 00061 // The Gauss rule needs to be scaled to [0,1] 00062 std::pair<Real, Real> old_range(-1.0L, 1.0L); 00063 std::pair<Real, Real> new_range( 0.0L, 1.0L); 00064 gauss1D.scale(old_range, 00065 new_range); 00066 00067 // Now construct the points and weights for the conical product rule. 00068 00069 // Both rules should have the same number of points. 00070 libmesh_assert_equal_to (gauss1D.n_points(), jac1D.n_points()); 00071 00072 // Save the number of points as a convenient variable 00073 const unsigned int np = gauss1D.n_points(); 00074 00075 // Both rules should be between x=0 and x=1 00076 libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0); 00077 libmesh_assert_less_equal (gauss1D.qp(np-1)(0), 1.0); 00078 libmesh_assert_greater_equal (jac1D.qp(0)(0), 0.0); 00079 libmesh_assert_less_equal (jac1D.qp(np-1)(0), 1.0); 00080 00081 // Resize the points and weights vectors 00082 _points.resize(np * np); 00083 _weights.resize(np * np); 00084 00085 // Compute the conical product 00086 unsigned int gp = 0; 00087 for (unsigned int i=0; i<np; i++) 00088 for (unsigned int j=0; j<np; j++) 00089 { 00090 _points[gp](0) = jac1D.qp(j)(0); //s[j]; 00091 _points[gp](1) = gauss1D.qp(i)(0) * (1.-jac1D.qp(j)(0)); //r[i]*(1.-s[j]); 00092 _weights[gp] = gauss1D.w(i) * jac1D.w(j); //A[i]*B[j]; 00093 gp++; 00094 } 00095 } 00096 00097 00098 00099 00100 // Builds and scales a Gauss rule and a Jacobi rule. 00101 // Then combines them to compute points and weights 00102 // of a 3D conical product rule for the Tet. 00103 void QConical::conical_product_tet(unsigned int p) 00104 { 00105 // Be sure the underlying rule object was built with the same dimension as the 00106 // rule we are about to construct. 00107 libmesh_assert_equal_to (this->get_dim(), 3); 00108 00109 QGauss gauss1D(1,static_cast<Order>(_order+2*p)); 00110 QJacobi jacA1D(1,static_cast<Order>(_order+2*p),1,0); 00111 QJacobi jacB1D(1,static_cast<Order>(_order+2*p),2,0); 00112 00113 // The Gauss rule needs to be scaled to [0,1] 00114 std::pair<Real, Real> old_range(-1.0L, 1.0L); 00115 std::pair<Real, Real> new_range( 0.0L, 1.0L); 00116 gauss1D.scale(old_range, 00117 new_range); 00118 00119 // Now construct the points and weights for the conical product rule. 00120 00121 // All rules should have the same number of points 00122 libmesh_assert_equal_to (gauss1D.n_points(), jacA1D.n_points()); 00123 libmesh_assert_equal_to (jacA1D.n_points(), jacB1D.n_points()); 00124 00125 // Save the number of points as a convenient variable 00126 const unsigned int np = gauss1D.n_points(); 00127 00128 // All rules should be between x=0 and x=1 00129 libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0); 00130 libmesh_assert_less_equal (gauss1D.qp(np-1)(0), 1.0); 00131 libmesh_assert_greater_equal (jacA1D.qp(0)(0), 0.0); 00132 libmesh_assert_less_equal (jacA1D.qp(np-1)(0), 1.0); 00133 libmesh_assert_greater_equal (jacB1D.qp(0)(0), 0.0); 00134 libmesh_assert_less_equal (jacB1D.qp(np-1)(0), 1.0); 00135 00136 // Resize the points and weights vectors 00137 _points.resize(np * np * np); 00138 _weights.resize(np * np * np); 00139 00140 // Compute the conical product 00141 unsigned int gp = 0; 00142 for (unsigned int i=0; i<np; i++) 00143 for (unsigned int j=0; j<np; j++) 00144 for (unsigned int k=0; k<np; k++) 00145 { 00146 _points[gp](0) = jacB1D.qp(k)(0); //t[k]; 00147 _points[gp](1) = jacA1D.qp(j)(0) * (1.-jacB1D.qp(k)(0)); //s[j]*(1.-t[k]); 00148 _points[gp](2) = gauss1D.qp(i)(0) * (1.-jacA1D.qp(j)(0)) * (1.-jacB1D.qp(k)(0)); //r[i]*(1.-s[j])*(1.-t[k]); 00149 _weights[gp] = gauss1D.w(i) * jacA1D.w(j) * jacB1D.w(k); //A[i]*B[j]*C[k]; 00150 gp++; 00151 } 00152 } 00153 00154 00155 00156 00157 00158 // Builds and scales a Gauss rule and a Jacobi rule. 00159 // Then combines them to compute points and weights 00160 // of a 3D conical product rule for the Pyramid. The integral 00161 // over the reference Tet can be written (in LaTeX notation) as: 00162 // 00163 // If := \int_0^1 dz \int_{-(1-z)}^{(1-z)} dy \int_{-(1-z)}^{(1-z)} f(x,y,z) dx (1) 00164 // 00165 // (Imagine a stack of infinitely thin squares which decrease in size as 00166 // you approach the apex.) Under the transformation of variables: 00167 // 00168 // z=w 00169 // y=(1-z)v 00170 // x=(1-z)u, 00171 // 00172 // The Jacobian determinant of this transformation is |J|=(1-w)^2, and 00173 // the integral itself is transformed to: 00174 // 00175 // If = \int_0^1 (1-w)^2 dw \int_{-1}^{1} dv \int_{-1}^{1} f((1-w)u, (1-w)v, w) du (2) 00176 // 00177 // The integral can now be approximated by the product of three 1D quadrature rules: 00178 // A Jacobi rule with alpha==2, beta==0 in w, and Gauss rules in v and u. In this way 00179 // we can obtain 3D rules to any order for which the 1D rules exist. 00180 void QConical::conical_product_pyramid(unsigned int p) 00181 { 00182 // Be sure the underlying rule object was built with the same dimension as the 00183 // rule we are about to construct. 00184 libmesh_assert_equal_to (this->get_dim(), 3); 00185 00186 QGauss gauss1D(1,static_cast<Order>(_order+2*p)); 00187 QJacobi jac1D(1,static_cast<Order>(_order+2*p),2,0); 00188 00189 // These rules should have the same number of points 00190 libmesh_assert_equal_to (gauss1D.n_points(), jac1D.n_points()); 00191 00192 // Save the number of points as a convenient variable 00193 const unsigned int np = gauss1D.n_points(); 00194 00195 // Resize the points and weights vectors 00196 _points.resize(np * np * np); 00197 _weights.resize(np * np * np); 00198 00199 // Compute the conical product 00200 unsigned int q = 0; 00201 for (unsigned int i=0; i<np; ++i) 00202 for (unsigned int j=0; j<np; ++j) 00203 for (unsigned int k=0; k<np; ++k, ++q) 00204 { 00205 const Real xi=gauss1D.qp(i)(0); 00206 const Real yj=gauss1D.qp(j)(0); 00207 const Real zk=jac1D.qp(k)(0); 00208 00209 _points[q](0) = (1.-zk) * xi; 00210 _points[q](1) = (1.-zk) * yj; 00211 _points[q](2) = zk; 00212 _weights[q] = gauss1D.w(i) * gauss1D.w(j) * jac1D.w(k); 00213 } 00214 00215 00216 } 00217 00218 } // namespace libMesh