Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_IntegrationRule.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 
45 
46 #include "Teuchos_ArrayRCP.hpp"
47 #include "Teuchos_Assert.hpp"
48 #include "Phalanx_DataLayout_MDALayout.hpp"
49 #include "Intrepid2_DefaultCubatureFactory.hpp"
50 #include "Intrepid2_CubatureControlVolume.hpp"
51 #include "Intrepid2_CubatureControlVolumeSide.hpp"
52 #include "Intrepid2_CubatureControlVolumeBoundary.hpp"
53 #include "Panzer_Dimension.hpp"
54 #include "Panzer_CellData.hpp"
55 
56 
58 IntegrationRule(int in_cubature_degree, const panzer::CellData& cell_data)
60 {
61  if(cell_data.isSide()){
62  IntegrationDescriptor::setup(in_cubature_degree, IntegrationDescriptor::SIDE, cell_data.side());
63  } else {
65  }
66  setup(in_cubature_degree,cell_data);
67 }
68 
70 IntegrationRule(const panzer::CellData& cell_data, const std::string & in_cv_type)
72 {
73  // Cubature orders are only used for indexing so we make them large enough not to interfere with other rules.
74  // TODO: This requirement (on arbitrary cubature order) will be dropped with the new Workset design (using descriptors to find integration rules)
75  // TODO: These isSide conditions shouldn't be required... I'm missing something...
76  if(in_cv_type == "volume"){
77  if(cell_data.isSide()){
79  } else {
81  }
82  } else if(in_cv_type == "side"){
83  if(cell_data.isSide()){
85  } else {
87  }
88  } else if(in_cv_type == "boundary"){
89  if(cell_data.isSide()){
91  } else {
93  }
94  } else {
95  TEUCHOS_ASSERT(false);
96  }
97  setup_cv(cell_data,in_cv_type);
98 }
99 
102  const Teuchos::RCP<const shards::CellTopology> & cell_topology,
103  const int num_cells,
104  const int num_faces)
105  : PointRule(), IntegrationDescriptor(description)
106 {
107 
109 
110  cubature_degree = description.getOrder();
111  cv_type = "none";
112 
113  panzer::CellData cell_data;
114  if(isSide()){
115  cell_data = panzer::CellData(num_cells, getSide(), cell_topology);
116  } else {
117  cell_data = panzer::CellData(num_cells, cell_topology);
118  }
119 
121  setup(getOrder(), cell_data);
122  } else if(description.getType() == panzer::IntegrationDescriptor::SIDE){
123  setup(getOrder(), cell_data);
124  } else if(description.getType() == panzer::IntegrationDescriptor::SURFACE){
125  TEUCHOS_ASSERT(num_faces!=-1);
126  setup_surface(cell_topology, num_cells, num_faces);
127  } else if(description.getType() == panzer::IntegrationDescriptor::CV_VOLUME){
128  setup_cv(cell_data, "volume");
129  } else if(description.getType() == panzer::IntegrationDescriptor::CV_SIDE){
130  setup_cv(cell_data, "side");
131  } else if(description.getType() == panzer::IntegrationDescriptor::CV_BOUNDARY){
132  setup_cv(cell_data, "boundary");
133  } else {
134  TEUCHOS_ASSERT(false);
135  }
136 
137 }
138 
139 void panzer::IntegrationRule::setup(int in_cubature_degree, const panzer::CellData& cell_data)
140 {
141  cubature_degree = in_cubature_degree;
142  cv_type = "none";
143  int spatialDimension = cell_data.baseCellDimension();
144 
145  std::stringstream ss;
146  ss << "CubaturePoints (Degree=" << cubature_degree;
147 
148  // Intrepid2 does not support a quadrature on a 0-dimensional object
149  // (which doesn't make much sense anyway) to work around this we
150  // will adjust the integration rule manually
151  if(cell_data.isSide() && spatialDimension==1) {
152  ss << ",side)";
153  PointRule::setup(ss.str(),1,cell_data);
154 
155  return;
156  }
157 
158  const shards::CellTopology & topo = *cell_data.getCellTopology();
159  Teuchos::RCP<shards::CellTopology> sideTopo = getSideTopology(cell_data);
160 
161  Intrepid2::DefaultCubatureFactory cubature_factory;
163 
164  // get side topology
165  if (Teuchos::is_null(sideTopo)) {
166  ss << ",volume)";
167  intrepid_cubature = cubature_factory.create<PHX::Device::execution_space,double,double>(topo, cubature_degree);
168  }
169  else {
170  ss << ",side)";
171  intrepid_cubature = cubature_factory.create<PHX::Device::execution_space,double,double>(*sideTopo, cubature_degree);
172  }
173 
174  PointRule::setup(ss.str(),intrepid_cubature->getNumPoints(),cell_data);
175 }
176 
177 void panzer::IntegrationRule::setup_surface(const Teuchos::RCP<const shards::CellTopology> & cell_topology, const int num_cells, const int num_faces)
178 {
179 
180  const int cell_dim = cell_topology->getDimension();
181  const int subcell_dim = cell_dim-1;
182  const int num_faces_per_cell = cell_topology->getSubcellCount(subcell_dim);
183 
184  panzer::CellData cell_data(num_cells, cell_topology);
185 
186  std::string point_rule_name;
187  {
188  std::stringstream ss;
189  ss << "CubaturePoints (Degree=" << getOrder() << ",surface)";
190  point_rule_name = ss.str();
191  }
192 
193  // We can skip some steps for 1D
194  if(cell_dim == 1){
195  const int num_points_per_cell = num_faces_per_cell;
196  const int num_points_per_face = 1;
197  PointRule::setup(point_rule_name, num_cells, num_points_per_cell, num_faces, num_points_per_face, cell_topology);
198  _point_offsets.resize(3,0);
199  _point_offsets[0] = 0;
200  _point_offsets[1] = num_points_per_face;
201  _point_offsets[2] = _point_offsets[1]+num_points_per_face;
202  return;
203  }
204 
205  Intrepid2::DefaultCubatureFactory cubature_factory;
206 
207  _point_offsets.resize(num_faces_per_cell+1,0);
208  int test_face_size = -1;
209  for(int subcell_index=0; subcell_index<num_faces_per_cell; ++subcell_index){
210  Teuchos::RCP<shards::CellTopology> face_topology = Teuchos::rcp(new shards::CellTopology(cell_topology->getCellTopologyData(subcell_dim,subcell_index)));
211  const auto & intrepid_cubature = cubature_factory.create<PHX::Device::execution_space,double,double>(*face_topology, getOrder());
212  const int num_face_points = intrepid_cubature->getNumPoints();
213  _point_offsets[subcell_index+1] = _point_offsets[subcell_index] + num_face_points;
214 
215  // Right now we only support each face having the same number of points
216  if(test_face_size==-1){
217  test_face_size = num_face_points;
218  } else {
219  TEUCHOS_ASSERT(num_face_points == test_face_size);
220  }
221  }
222 
223  const int num_points_per_cell = _point_offsets.back();
224  const int num_points_per_face = _point_offsets[1];
225 
226  PointRule::setup(point_rule_name, num_cells, num_points_per_cell, num_faces, num_points_per_face, cell_topology);
227 
228 }
229 
230 void panzer::IntegrationRule::setup_cv(const panzer::CellData& cell_data, std::string in_cv_type)
231 {
232  // set cubature degree to arbitrary constant for indexing
233  cubature_degree = 1;
234  cv_type = in_cv_type;
235  if (cv_type == "volume") {
236  cubature_degree = 75;
237  }
238  if (cv_type == "side") {
239  cubature_degree = 85;
240  }
241  if (cv_type == "boundary") {
242  cubature_degree = 95;
243  }
244 
245  //int spatialDimension = cell_data.baseCellDimension();
246 
247  std::stringstream ss;
248  ss << "CubaturePoints ControlVol (Index=" << cubature_degree;
249 
250  const shards::CellTopology & topo = *cell_data.getCellTopology();
251 
253 
254  int tmp_num_points = 0;
255  if (cv_type == "volume") {
256  ss << ",volume)";
257  intrepid_cubature = Teuchos::rcp(new Intrepid2::CubatureControlVolume<PHX::Device::execution_space,double,double>(topo));
258  tmp_num_points = intrepid_cubature->getNumPoints();
259  }
260  else if (cv_type == "side") {
261  ss << ",side)";
262  intrepid_cubature = Teuchos::rcp(new Intrepid2::CubatureControlVolumeSide<PHX::Device::execution_space,double,double>(topo));
263  tmp_num_points = intrepid_cubature->getNumPoints();
264  }
265  else if (cv_type == "boundary") {
266  ss << ",boundary)";
267  intrepid_cubature = Teuchos::rcp(new Intrepid2::CubatureControlVolumeBoundary<PHX::Device::execution_space,double,double>(topo,cell_data.side()));
268  tmp_num_points = intrepid_cubature->getNumPoints();
269  }
270 
271  PointRule::setup(ss.str(),tmp_num_points,cell_data);
272 }
273 
275 { return cubature_degree; }
276 
277 
278 int panzer::IntegrationRule::getPointOffset(const int subcell_index) const
279 {
280  // Need to make sure this is a surface integrator
281  TEUCHOS_ASSERT(getType() == SURFACE);
282  return _point_offsets[subcell_index];
283 }
284 
285 
286 void panzer::IntegrationRule::print(std::ostream & os)
287 {
288  os << "IntegrationRule ( "
289  << "Name = " << getName()
290  << ", Degree = " << cubature_degree
291  << ", Dimension = " << spatial_dimension
292  << ", Workset Size = " << workset_size
293  << ", Num Points = " << num_points
294  << ", Side = " << side
295  << " )";
296 }
297 
298 void panzer::IntegrationRule::referenceCoordinates(Kokkos::DynRankView<double,PHX::Device> & cub_points)
299 {
300  // build an interpid cubature rule
302  Intrepid2::DefaultCubatureFactory cubature_factory;
303 
304  if (!isSide())
305  intrepid_cubature = cubature_factory.create<PHX::Device::execution_space,double,double>(*(topology),cubature_degree);
306  else
307  intrepid_cubature = cubature_factory.create<PHX::Device::execution_space,double,double>(*(side_topology),cubature_degree);
308 
309  int num_ip = intrepid_cubature->getNumPoints();
310  Kokkos::DynRankView<double,PHX::Device> cub_weights("cub_weights",num_ip);
311 
312  // now compute weights (and throw them out) as well as reference points
313  if (!isSide()) {
314  cub_points = Kokkos::DynRankView<double,PHX::Device>("cub_points", num_ip, topology->getDimension());
315  intrepid_cubature->getCubature(cub_points, cub_weights);
316  }
317  else {
318  cub_points = Kokkos::DynRankView<double,PHX::Device>("cub_points", num_ip, side_topology->getDimension());
319  intrepid_cubature->getCubature(cub_points, cub_weights);
320  }
321 }
int baseCellDimension() const
Dimension of the base cell. NOT the dimension of the local side, even if the side() method returns tr...
void setup(const std::string &ptName, int np, const panzer::CellData &cell_data)
bool is_null(const std::shared_ptr< T > &p)
Integral over a specific side of cells (side must be set)
Teuchos::RCP< const shards::CellTopology > getCellTopology() const
Get CellTopology for the base cell.
No integral specified - default state.
const int & getType() const
Get type of integrator.
void referenceCoordinates(Kokkos::DynRankView< double, PHX::Device > &container)
Construct an array containing the reference coordinates.
void setup(int cubature_degree, const panzer::CellData &cell_data)
int getPointOffset(const int subcell_index) const
Returns the integration point offset for a given subcell_index (i.e. local face index) ...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void setup(const int cubature_order, const int integration_type, const int side=-1)
Setup function.
Data for determining cell topology and dimensionality.
void setup_cv(const panzer::CellData &cell_data, std::string cv_type)
void setup_surface(const Teuchos::RCP< const shards::CellTopology > &cell_topology, const int num_cells, const int num_faces)
Setup a surface integration.
const int & getSide() const
Get side associated with integration - this is for backward compatibility.
Integral over all sides of cells (closed surface integral)
virtual void print(std::ostream &os)
print information about the integration rule
IntegrationRule(int cubature_degree, const panzer::CellData &cell_data)
if side = -1 then we use the cell volume integration rule.
int order() const
Returns the order of integration (cubature degree in intrepid lingo)
#define TEUCHOS_ASSERT(assertion_test)
bool isSide() const
const int & getOrder() const
Get order of integrator.