$extrastylesheet
quadrature_conical.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_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