quadrature_composite.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #include "libmesh/libmesh_config.h"
20 #if defined(LIBMESH_HAVE_TRIANGLE) && defined(LIBMESH_HAVE_TETGEN)
21 
22 #include "libmesh/fe.h"
27 #include "libmesh/elem.h"
29 
30 
31 
32 namespace libMesh
33 {
34 
35 
36 template <class QSubCell>
38 {
39  return QCOMPOSITE;
40 }
41 
42 
43 
44 template <class QSubCell>
46  Order o) :
47  QSubCell(d,o), // explicitly call base class constructor
48  _q_subcell(d,o),
49  _lagrange_fe(FEBase::build (d, FEType (FIRST, LAGRANGE)))
50 {
51  // explicitly call the init function in 1D since the
52  // other tensor-product rules require this one.
53  // note that EDGE will not be used internally, however
54  // if we called the function with INVALID_ELEM it would try to
55  // be smart and return, thinking it had already done the work.
56  if (_dim == 1)
58 
59  libmesh_assert (_lagrange_fe.get() != nullptr);
60 
61  _lagrange_fe->attach_quadrature_rule (&_q_subcell);
62 }
63 
64 
65 
66 template <class QSubCell>
67 void QComposite<QSubCell>::init (const Elem & elem,
68  const std::vector<Real> & vertex_distance_func,
69  unsigned int p_level)
70 {
71  libmesh_assert_equal_to (vertex_distance_func.size(), elem.n_vertices());
72  libmesh_assert_equal_to (_dim, elem.dim());
73 
74  // if we are not cut, revert to simple base class init() method.
75  if (!_elem_cutter.is_cut (elem, vertex_distance_func))
76  {
77  _q_subcell.init (elem.type(), p_level);
78  _points = _q_subcell.get_points();
79  _weights = _q_subcell.get_weights();
80 
81  //this->print_info();
82  return;
83  }
84 
85  // Get a pointer to the element's reference element. We want to
86  // perform cutting on the reference element such that the quadrature
87  // point locations of the subelements live in the reference
88  // coordinate system, thereby eliminating the need for inverse
89  // mapping.
90  const Elem * reference_elem = elem.reference_elem();
91 
92  libmesh_assert (reference_elem != nullptr);
93 
94  _elem_cutter(*reference_elem, vertex_distance_func);
95  //_elem_cutter(elem, vertex_distance_func);
96 
97  // clear our state & accumulate points from subelements
98  _points.clear();
99  _weights.clear();
100 
101  // inside subelem
102  {
103  const std::vector<Elem const *> & inside_elem (_elem_cutter.inside_elements());
104  std::cout << inside_elem.size() << " elements inside\n";
105 
106  this->add_subelem_values(inside_elem);
107  }
108 
109  // outside subelem
110  {
111  const std::vector<Elem const *> & outside_elem (_elem_cutter.outside_elements());
112  std::cout << outside_elem.size() << " elements outside\n";
113 
114  this->add_subelem_values(outside_elem);
115  }
116 
117  this->print_info();
118 }
119 
120 
121 
122 template <class QSubCell>
123 void QComposite<QSubCell>::add_subelem_values (const std::vector<Elem const *> & subelem)
124 
125 {
126  const std::vector<Real> & subelem_weights = _lagrange_fe->get_JxW();
127  const std::vector<Point> & subelem_points = _lagrange_fe->get_xyz();
128 
129  for (const auto & elem : subelem)
130  {
131  // tetgen seems to create 0-volume cells on occasion, but we *should*
132  // be catching that appropriately now inside the ElemCutter class.
133  // Just in case trap here, describe the error, and abort.
134  libmesh_try
135  {
136  _lagrange_fe->reinit(elem);
137  _weights.insert(_weights.end(),
138  subelem_weights.begin(), subelem_weights.end());
139 
140  _points.insert(_points.end(),
141  subelem_points.begin(), subelem_points.end());
142  }
143  libmesh_catch (...)
144  {
145  libMesh::err << "ERROR: found a bad cut cell!\n";
146 
147  for (unsigned int n=0; n<elem->n_nodes(); n++)
148  libMesh::err << elem->point(n) << std::endl;
149 
150  libmesh_error_msg("Tetgen may have created a 0-volume cell during Cutcell integration.");
151  }
152  }
153 }
154 
155 
156 
157 //--------------------------------------------------------------
158 // Explicit instantiations
159 template class QComposite<QGauss>;
160 template class QComposite<QTrap>;
161 template class QComposite<QSimpson>;
162 
163 } // namespace libMesh
164 
165 #endif // LIBMESH_HAVE_TRIANGLE && LIBMESH_HAVE_TETGEN
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
The base class for all geometric element types.
Definition: elem.h:100
QComposite(unsigned int dim, Order order=INVALID_ORDER)
virtual void init(const Elem &elem, const std::vector< Real > &vertex_distance_func, unsigned int p_level=0) override
void init(triangulateio &t)
const Elem * reference_elem() const
Definition: elem.C:337
OStreamProxy err(std::cerr)
A quadrature rule for subdivided elements.
std::unique_ptr< FEBase > _lagrange_fe
virtual unsigned int n_vertices() const =0
virtual unsigned short dim() const =0
virtual QuadratureType type() const override
virtual ElemType type() const =0
void add_subelem_values(const std::vector< Elem const *> &subelem)