$extrastylesheet
quadrature_composite.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2012 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/libmesh_config.h"
00020 #if defined(LIBMESH_HAVE_TRIANGLE) && defined(LIBMESH_HAVE_TETGEN)
00021 
00022 #include "libmesh/fe.h"
00023 #include "libmesh/quadrature_gauss.h"
00024 #include "libmesh/quadrature_trap.h"
00025 #include "libmesh/quadrature_simpson.h"
00026 #include "libmesh/quadrature_composite.h"
00027 #include "libmesh/elem.h"
00028 
00029 
00030 
00031 namespace libMesh
00032 {
00033 
00034 
00035 template <class QSubCell>
00036 QComposite<QSubCell>::QComposite(const unsigned int d,
00037                                  const Order o) :
00038   QSubCell(d,o), // explicitly call base class constructor
00039   _q_subcell(d,o),
00040   _lagrange_fe(FEBase::build (d, FEType (FIRST, LAGRANGE)))
00041 {
00042   // explicitly call the init function in 1D since the
00043   // other tensor-product rules require this one.
00044   // note that EDGE will not be used internally, however
00045   // if we called the function with INVALID_ELEM it would try to
00046   // be smart and return, thinking it had already done the work.
00047   if (_dim == 1)
00048     QSubCell::init(EDGE2);
00049 
00050   libmesh_assert (_lagrange_fe.get() != NULL);
00051 
00052   _lagrange_fe->attach_quadrature_rule (&_q_subcell);
00053 }
00054 
00055 
00056 
00057 template <class QSubCell>
00058 QComposite<QSubCell>::~QComposite()
00059 {}
00060 
00061 
00062 
00063 template <class QSubCell>
00064 void QComposite<QSubCell>::init (const Elem &elem,
00065                                  const std::vector<Real> &vertex_distance_func,
00066                                  unsigned int p_level)
00067 {
00068   libmesh_assert_equal_to (vertex_distance_func.size(), elem.n_vertices());
00069   libmesh_assert_equal_to (_dim, elem.dim());
00070 
00071   // if we are not cut, revert to simple base class init() method.
00072   if (!_elem_cutter.is_cut (elem, vertex_distance_func))
00073     {
00074       _q_subcell.init (elem.type(), p_level);
00075       _points  = _q_subcell.get_points();
00076       _weights = _q_subcell.get_weights();
00077 
00078       //this->print_info();
00079       return;
00080     }
00081 
00082   // Get a pointer to the element's reference element.  We want to
00083   // perform cutting on the reference element such that the quadrature
00084   // point locations of the subelements live in the reference
00085   // coordinate system, thereby eliminating the need for inverse
00086   // mapping.
00087   const Elem *reference_elem = elem.reference_elem();
00088 
00089   libmesh_assert (reference_elem != NULL);
00090 
00091   _elem_cutter(*reference_elem, vertex_distance_func);
00092   //_elem_cutter(elem, vertex_distance_func);
00093 
00094   // clear our state & accumulate points from subelements
00095   _points.clear();
00096   _weights.clear();
00097 
00098   // inside subelem
00099   {
00100     const std::vector<Elem const*> &inside_elem (_elem_cutter.inside_elements());
00101     std::cout << inside_elem.size() << " elements inside\n";
00102 
00103     this->add_subelem_values(inside_elem);
00104   }
00105 
00106   // outside subelem
00107   {
00108     const std::vector<Elem const*> &outside_elem (_elem_cutter.outside_elements());
00109     std::cout << outside_elem.size() << " elements outside\n";
00110 
00111     this->add_subelem_values(outside_elem);
00112   }
00113 
00114   this->print_info();
00115 }
00116 
00117 
00118 
00119 template <class QSubCell>
00120 void QComposite<QSubCell>::add_subelem_values (const std::vector<Elem const*> &subelem)
00121 
00122 {
00123   const std::vector<Real>  &subelem_weights = _lagrange_fe->get_JxW();
00124   const std::vector<Point> &subelem_points  = _lagrange_fe->get_xyz();
00125 
00126   for (std::vector<Elem const*>::const_iterator it = subelem.begin();
00127        it!=subelem.end(); ++it)
00128     {
00129       // tetgen seems to create 0-volume cells on occasion, but we *should*
00130       // be catching that appropriately now inside the ElemCutter class.
00131       // Just in case trap here, describe the error, and abort.
00132 #ifdef LIBMESH_ENABLE_EXCEPTIONS
00133       try
00134         {
00135 #endif
00136           _lagrange_fe->reinit(*it);
00137           _weights.insert(_weights.end(),
00138                           subelem_weights.begin(), subelem_weights.end());
00139 
00140           _points.insert(_points.end(),
00141                          subelem_points.begin(), subelem_points.end());
00142 #ifdef LIBMESH_ENABLE_EXCEPTIONS
00143         }
00144       catch (...)
00145         {
00146           libMesh::err << "ERROR: found a bad cut cell!\n";
00147 
00148           for (unsigned int n=0; n<(*it)->n_nodes(); n++)
00149             libMesh::err << (*it)->point(n) << std::endl;
00150 
00151           libmesh_error_msg("Tetgen may have created a 0-volume cell during Cutcell integration.");
00152         }
00153 #endif
00154     }
00155 }
00156 
00157 
00158 
00159 //--------------------------------------------------------------
00160 // Explicit instantiations
00161 template class QComposite<QGauss>;
00162 template class QComposite<QTrap>;
00163 template class QComposite<QSimpson>;
00164 
00165 } // namespace libMesh
00166 
00167 #endif // LIBMESH_HAVE_TRIANGLE && LIBMESH_HAVE_TETGEN