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