Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_Workset.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 #include "Panzer_Workset.hpp"
44 
45 #include "Phalanx_DataLayout.hpp"
46 #include "Phalanx_DataLayout_MDALayout.hpp"
47 
49 #include "Panzer_Workset_Builder.hpp"
50 #include "Panzer_WorksetNeeds.hpp"
51 #include "Panzer_Dimension.hpp"
52 #include "Panzer_LocalMeshInfo.hpp"
54 #include "Panzer_PointValues2.hpp"
55 
57 
58 #include "Shards_CellTopology.hpp"
59 
60 namespace panzer {
61 
62 void
64  const panzer::WorksetNeeds & needs)
65 {
66 
67 
68  const size_t num_cells = partition.local_cells.extent(0);
69 
73 
74  subcell_index = -1;
75  block_id = partition.element_block_name;
76 
77  Kokkos::View<int*, PHX::Device> cell_ids = Kokkos::View<int*, PHX::Device>("cell_ids",num_cells);
78  Kokkos::deep_copy(cell_ids, partition.local_cells);
79  cell_local_ids_k = cell_ids;
80 
81  cell_local_ids.resize(num_cells,-1);
82  for(size_t cell=0;cell<num_cells;++cell){
83  const int local_cell = partition.local_cells(cell);
84  cell_local_ids[cell] = local_cell;
85  }
86 
87  auto fc = Teuchos::rcp(new panzer::FaceConnectivity());
88  fc->setup(partition);
89  _face_connectivity = fc;
90 
91  setupNeeds(partition.cell_topology, partition.cell_vertices, needs);
92 }
93 
95  const Kokkos::View<double***,PHX::Device> & cell_vertices,
96  const panzer::WorksetNeeds & needs)
97 {
98  const size_t num_cells = cell_vertices.extent(0);
99  const size_t num_vertices_per_cell = cell_vertices.extent(1);
100  const size_t num_dims_per_vertex = cell_vertices.extent(2);
101 
102  // Set cell vertices
103  {
104 
105  MDFieldArrayFactory af("",true);
106 
107  cell_vertex_coordinates = af.template buildStaticArray<double, Cell, NODE, Dim>("cell_vertices",num_cells, num_vertices_per_cell, num_dims_per_vertex);
108 
109  for(size_t i=0;i<num_cells;++i)
110  for(size_t j=0;j<num_vertices_per_cell;++j)
111  for(size_t k=0;k<num_dims_per_vertex;++k)
112  cell_vertex_coordinates(i,j,k) = cell_vertices(i,j,k);
113 
114  }
115 
116  // DEPRECATED - makes sure deprecated arrays are filled with something - this will probably segfault or throw an error
117  panzer::populateValueArrays(num_cells, false, needs, *this);
118 
119  const std::vector<panzer::BasisDescriptor> & basis_descriptors = needs.getBases();
120  const std::vector<panzer::IntegrationDescriptor> & integration_descriptors = needs.getIntegrators();
121  const std::vector<panzer::PointDescriptor> & point_descriptors = needs.getPoints();
122 
123  // Create the pure basis
124  for(const panzer::BasisDescriptor & basis_description : basis_descriptors){
125  // Create and store integration rule
126  Teuchos::RCP<panzer::PureBasis> basis = Teuchos::rcp(new panzer::PureBasis(basis_description, cell_topology, num_cells));
127  _pure_basis_map[basis_description.getKey()] = basis;
128  }
129 
130  // Create the integration terms and basis-integrator pairs
131  for(const panzer::IntegrationDescriptor & integration_description : integration_descriptors){
132 
133  int num_faces = -1;
134  if(integration_description.getType() == panzer::IntegrationRule::SURFACE){
135  num_faces = getFaceConnectivity().numSubcells();
136  }
137 
138  // Create and store integration rule
139  Teuchos::RCP<panzer::IntegrationRule> ir = Teuchos::rcp(new panzer::IntegrationRule(integration_description, cell_topology, num_cells, num_faces));
140  _integration_rule_map[integration_description.getKey()] = ir;
141 
142  // Create and store integration values
144  iv->setupArrays(ir);
145  iv->evaluateValues(cell_vertex_coordinates,num_cells);
146  if (iv->int_rule->getType() == panzer::IntegrationDescriptor::SURFACE)
147  {
148  // IntegrationValues2 doesn't know anything about virtual cells, so it sets up incorrect normals for those.
149  // What we want is for the adjoining face of the virtual cell to have normals that are the negated real cell's normals.
150  // we correct the normals here:
151  auto num_real_cells = _num_owned_cells + _num_ghost_cells;
152  const int space_dim = cell_topology->getDimension();
153  const int faces_per_cell = cell_topology->getSubcellCount(space_dim-1);
154  const int points = iv->surface_normals.extent_int(1);
155  const int points_per_face = points / faces_per_cell;
156  for (int virtual_cell_ordinal=0; virtual_cell_ordinal<_num_virtual_cells; virtual_cell_ordinal++)
157  {
158  const panzer::LocalOrdinal virtual_cell = virtual_cell_ordinal+num_real_cells;
159  int virtual_local_face_id = -1; // the virtual cell face that adjoins the real cell
160  int face_ordinal = -1;
161  for (int local_face_id=0; local_face_id<faces_per_cell; local_face_id++)
162  {
163  face_ordinal = _face_connectivity->subcellForCell(virtual_cell, local_face_id);
164  if (face_ordinal >= 0)
165  {
166  virtual_local_face_id = local_face_id;
167  break;
168  }
169  }
170  if (face_ordinal >= 0)
171  {
172  const int first_cell_for_face = _face_connectivity->cellForSubcell(face_ordinal, 0);
173  const panzer::LocalOrdinal other_side = (first_cell_for_face == virtual_cell) ? 1 : 0;
174  const panzer::LocalOrdinal real_cell = _face_connectivity->cellForSubcell(face_ordinal,other_side);
175  const panzer::LocalOrdinal face_in_real_cell = _face_connectivity->localSubcellForSubcell(face_ordinal,other_side);
176  TEUCHOS_ASSERT(real_cell < num_real_cells);
177  for (int point_ordinal=0; point_ordinal<points_per_face; point_ordinal++)
178  {
179  int virtual_cell_point = points_per_face * virtual_local_face_id + point_ordinal;
180  int real_cell_point = points_per_face * face_in_real_cell + point_ordinal;
181  // the following arrays will be used to produce/store the rotation matrix below
182  double normal[3], transverse[3], binormal[3];
183  for(int i=0;i<3;i++)
184  {
185  normal[i]=0.;
186  transverse[i]=0.;
187  binormal[i]=0.;
188  }
189 
190  for (int d=0; d<space_dim; d++)
191  {
192  const auto n_d = iv->surface_normals(real_cell,real_cell_point,d);
193  iv->surface_normals(virtual_cell,virtual_cell_point,d) = -n_d;
194  normal[d] = -n_d;
195  }
196 
198 
199  for(int dim=0; dim<3; ++dim){
200  iv->surface_rotation_matrices(virtual_cell,virtual_cell_point,0,dim) = normal[dim];
201  iv->surface_rotation_matrices(virtual_cell,virtual_cell_point,1,dim) = transverse[dim];
202  iv->surface_rotation_matrices(virtual_cell,virtual_cell_point,2,dim) = binormal[dim];
203  }
204  }
205  // clear the other normals and rotation matrices for the virtual cell:
206  for (int local_face_id=0; local_face_id<faces_per_cell; local_face_id++)
207  {
208  if (local_face_id == virtual_local_face_id) continue;
209  for (int point_ordinal=0; point_ordinal<points_per_face; point_ordinal++)
210  {
211  int point = local_face_id * points_per_face + point_ordinal;
212  for (int dim=0; dim<space_dim; dim++)
213  {
214  iv->surface_normals(virtual_cell,point,dim) = 0.0;
215  }
216  for(int dim1=0; dim1<3; ++dim1)
217  {
218  for(int dim2=0; dim2<3; ++dim2)
219  {
220  iv->surface_rotation_matrices(virtual_cell,point,dim1,dim2) = 0;
221  }
222  }
223  }
224  }
225  }
226  }
227  }
228  _integrator_map[integration_description.getKey()] = iv;
229 
230  // We need to generate a integration rule - basis pair for each basis
231  for(const panzer::BasisDescriptor & basis_description : basis_descriptors){
232 
233  // Grab the basis that was pre-calculated
234  const Teuchos::RCP<const panzer::PureBasis> & basis = _pure_basis_map[basis_description.getKey()];
235 
236  // Create a basis ir layout for this pair of integrator and basis
238 
239  // Create and store basis values
241  bv->setupArrays(b_layout);
243  bv->evaluateValues(iv->ref_ip_coordinates,
244  iv->jac,
245  iv->jac_det,
246  iv->jac_inv,
247  iv->weighted_measure,
249  true,
250  num_cells);
254  bv->evaluateValuesCV(iv->ref_ip_coordinates,
255  iv->jac,
256  iv->jac_det,
257  iv->jac_inv);
258  } else {
259  bv->evaluateValues(iv->cub_points,
260  iv->jac,
261  iv->jac_det,
262  iv->jac_inv,
263  iv->weighted_measure,
265  true,
266  num_cells);
267  }
268  _basis_map[basis_description.getKey()][integration_description.getKey()] = bv;
269  }
270 
271  }
272 
273  // Create the point terms and basis-integrator pairs
274  for(const panzer::PointDescriptor & point_description : point_descriptors){
275 
276  // get the generaotr, and build some points from a topology
277  auto points = point_description.getGenerator().getPoints(*cell_topology);
278 
279  // Create and store integration rule
281  cell_topology,
282  num_cells));
283  _point_rule_map[point_description.getKey()] = pr;
284 
285  // Create and store integration values
287  pv->setupArrays(pr);
288  pv->evaluateValues(cell_vertex_coordinates,points);
289 
290  _point_map[point_description.getKey()] = pv;
291 
292  // We need to generate a integration rule - basis pair for each basis
293  for(const panzer::BasisDescriptor & basis_description : basis_descriptors){
294 
295  // Grab the basis that was pre-calculated
296  const Teuchos::RCP<const panzer::PureBasis> & basis = _pure_basis_map[basis_description.getKey()];
297 
298  // Create a basis ir layout for this pair of integrator and basis
300 
301  // Create and store basis values
303  bv->setupArrays(b_layout);
304 
305  bv->evaluateValues(pv->coords_ref,
306  pv->jac,
307  pv->jac_det,
308  pv->jac_inv);
309 
310  _basis_map[basis_description.getKey()][point_description.getKey()] = bv;
311  }
312 
313  }
314 
315 }
316 
319 {
320  TEUCHOS_ASSERT(_face_connectivity != Teuchos::null);
321  return *_face_connectivity;
322 }
323 
326 {
327  const auto itr = _integrator_map.find(description.getKey());
328  TEUCHOS_ASSERT(itr != _integrator_map.end());
329  return *(itr->second);
330 }
331 
334 {
335  const auto itr = _integration_rule_map.find(description.getKey());
337  return *(itr->second);
338 }
339 
342  const panzer::IntegrationDescriptor & integration_description)
343 {
344  const auto itr = _basis_map.find(basis_description.getKey());
346  "Workset::getBasisValues: Can't find basis \"" + basis_description.getType() + "\" "
347  "of order " + std::to_string(basis_description.getOrder()));
348  const auto & integration_map = itr->second;
349  const auto itr2 = integration_map.find(integration_description.getKey());
350  TEUCHOS_TEST_FOR_EXCEPT_MSG(itr2 == integration_map.end(),
351  "Workset::getBasisValues: Can't find integration " + std::to_string(integration_description.getType()) + " "
352  "of order " + std::to_string(integration_description.getOrder()));
353  return *(itr2->second);
354 }
355 
358  const panzer::PointDescriptor & point_description) const
359 {
360  const auto itr = _basis_map.find(basis_description.getKey());
362  "Workset::getBasisValues: Can't find basis \"" + basis_description.getType() + "\" "
363  "of order " + std::to_string(basis_description.getOrder()));
364  const auto & point_map = itr->second;
365  const auto itr2 = point_map.find(point_description.getKey());
366  TEUCHOS_TEST_FOR_EXCEPT_MSG(itr2 == point_map.end(),
367  "Workset::getBasisValues: Can't find point values \"" + point_description.getType() + "\"");
368  return *(itr2->second);
369 }
370 
373  const panzer::IntegrationDescriptor & integration_description) const
374 {
375  const auto itr = _basis_map.find(basis_description.getKey());
377  "Workset::getBasisValues: Can't find basis \"" + basis_description.getType() + "\" "
378  "of order " + std::to_string(basis_description.getOrder()));
379  const auto & integration_map = itr->second;
380  const auto itr2 = integration_map.find(integration_description.getKey());
381  TEUCHOS_TEST_FOR_EXCEPT_MSG(itr2 == integration_map.end(),
382  "Workset::getBasisValues: Can't find integration " + std::to_string(integration_description.getType()) + " "
383  "of order " + std::to_string(integration_description.getOrder()));
384  return *(itr2->second);
385 }
386 
389 {
390  const auto itr = _point_map.find(point_description.getKey());
392  "Workset::getPointValues: Can't find point values \"" + point_description.getType() + "\"");
393  return *(itr->second);
394 }
395 
396 const panzer::PureBasis &
398 {
399  const auto itr = _pure_basis_map.find(description.getKey());
400  TEUCHOS_ASSERT(itr != _pure_basis_map.end());
401  return *(itr->second);
402 }
403 
404  std::ostream& operator<<(std::ostream& os, const panzer::Workset& w)
405  {
406  using std::endl;
407 
408  os << "Workset" << endl;
409  os << " block_id=" << w.block_id << endl;
410  os << " num_cells:" << w.num_cells << endl;
411  os << " cell_local_ids (size=" << w.cell_local_ids.size() << ")" << endl;
412  os << " subcell_dim = " << w.subcell_dim << endl;
413  os << " subcell_index = " << w.subcell_index << endl;
414 
415  os << " ir_degrees: " << endl;
416  for (std::vector<int>::const_iterator ir = w.ir_degrees->begin();
417  ir != w.ir_degrees->end(); ++ir)
418  os << " " << *ir << std::endl;
419 
420  std::vector<int>::const_iterator ir = w.ir_degrees->begin();
421  for (std::vector<Teuchos::RCP<panzer::IntegrationValues2<double> > >::const_iterator irv = w.int_rules.begin();
422  irv != w.int_rules.end(); ++irv,++ir) {
423 
424  os << " IR Values (Degree=" << *ir << "):" << endl;
425 
426  os << " cub_points:" << endl;
427  os << (*irv)->cub_points << endl;
428 
429  os << " side_cub_points:" << endl;
430  os << (*irv)->side_cub_points << endl;
431 
432  os << " cub_weights:" << endl;
433  os << (*irv)->cub_weights << endl;
434 
435  os << " node_coordinates:" << endl;
436  os << (*irv)->node_coordinates << endl;
437 
438  os << " jac:" << endl;
439  os << (*irv)->jac << endl;
440 
441  os << " jac_inv:" << endl;
442  os << (*irv)->jac_inv << endl;
443 
444  os << " jac_det:" << endl;
445  os << (*irv)->jac_det << endl;
446 
447  os << " weighted_measure:" << endl;
448  os << (*irv)->weighted_measure << endl;
449 
450  os << " covarient:" << endl;
451  os << (*irv)->covarient << endl;
452 
453  os << " contravarient:" << endl;
454  os << (*irv)->contravarient << endl;
455 
456  os << " norm_contravarient:" << endl;
457  os << (*irv)->norm_contravarient << endl;
458 
459  os << " ip_coordinates:" << endl;
460  os << (*irv)->ip_coordinates << endl;
461 
462  os << " int_rule->getName():" << (*irv)->int_rule->getName() << endl;
463  }
464 
465 
466  os << " basis_names: " << endl;
467  for (std::vector<std::string>::const_iterator b = w.basis_names->begin();
468  b != w.basis_names->end(); ++b)
469  os << " " << *b << std::endl;
470 
471  std::vector<std::string>::const_iterator b = w.basis_names->begin();
472 
473  for (std::vector<Teuchos::RCP< panzer::BasisValues2<double> > >::const_iterator bv = w.bases.begin(); bv != w.bases.end(); ++bv,++b) {
474 
475  os << " Basis Values (basis_name=" << *b << "):" << endl;
476 
477 /*
478  os << " basis_ref:" << endl;
479  os << (*bv)->basis_ref << endl;
480 
481  os << " basis:" << endl;
482  os << (*bv)->basis_scalar << endl;
483 
484  os << " grad_basis_ref:" << endl;
485  os << (*bv)->grad_basis_ref << endl;
486 
487  os << " grad_basis:" << endl;
488  os << (*bv)->grad_basis << endl;
489 
490  os << " curl_basis_ref:" << endl;
491  os << (*bv)->curl_basis_ref_vector << endl;
492 
493  os << " curl_basis:" << endl;
494  os << (*bv)->curl_basis_vector << endl;
495 
496  os << " basis_coordinates_ref:" << endl;
497  os << (*bv)->basis_coordinates_ref << endl;
498 
499  os << " basis_coordinates:" << endl;
500  os << (*bv)->basis_coordinates << endl;
501 */
502 
503  os << " basis_layout->name():" << (*bv)->basis_layout->name() << endl;
504  }
505 
506 
507 
508  return os;
509  }
510 
511 }
std::map< size_t, std::map< size_t, Teuchos::RCP< panzer::BasisValues2< double > > > > _basis_map
static void convertNormalToRotationMatrix(const Scalar normal[3], Scalar transverse[3], Scalar binormal[3])
Kokkos::View< double ***, PHX::Device > cell_vertices
Teuchos::RCP< const shards::CellTopology > cell_topology
std::map< size_t, Teuchos::RCP< const panzer::IntegrationRule > > _integration_rule_map
Kokkos::View< panzer::LocalOrdinal * > local_cells
std::size_t getKey() const
Get unique key associated with integrator of this order and type The key is used to sort through a ma...
std::size_t getKey() const
Get unique key associated with integrator of this order and type The key is used to sort through a ma...
Integral over a specific side of cells (side must be set)
std::size_t getKey() const
Get unique key associated with basis of this order and type The key is used to sort through a map of ...
Teuchos::RCP< std::vector< int > > ir_degrees
If workset corresponds to a sub cell, what is the index?
panzer::BasisValues2< double > & getBasisValues(const panzer::BasisDescriptor &basis_description, const panzer::IntegrationDescriptor &integration_description)
Grab the basis values for a given basis description and integration description (throws error if it d...
std::vector< Teuchos::RCP< panzer::BasisValues2< double > > > bases
Static basis function data, key is basis name, value is index in the static_bases vector...
Teuchos::RCP< std::vector< std::string > > basis_names
Value corresponds to basis type. Use the offest for indexing.
void setup(const panzer::LocalMeshPartition &partition, const panzer::WorksetNeeds &needs)
Constructs the workset details from a given chunk of the mesh.
std::map< size_t, Teuchos::RCP< const panzer::PureBasis > > _pure_basis_map
Generates a SubcellConnectivity associated with faces and cells given a partition of the local mesh...
const int & getType() const
Get type of integrator.
panzer::LocalOrdinal num_owned_cells
CellCoordArray cell_vertex_coordinates
const std::vector< panzer::PointDescriptor > & getPoints() const
Get a list of points being requested.
const std::vector< panzer::BasisDescriptor > & getBases() const
Get a list of bases being requested.
panzer::LocalOrdinal num_virtual_cells
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const panzer::IntegrationValues2< double > & getIntegrationValues(const panzer::IntegrationDescriptor &description) const
Grab the integration values for a given integration description (throws error if integration doesn&#39;t ...
const std::string & getType() const
Get type of basis.
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
std::map< size_t, Teuchos::RCP< const panzer::PointRule > > _point_rule_map
void setupNeeds(Teuchos::RCP< const shards::CellTopology > cell_topology, const Kokkos::View< double ***, PHX::Device > &cell_vertices, const panzer::WorksetNeeds &needs)
const panzer::PureBasis & getBasis(const panzer::BasisDescriptor &description) const
Grab the pure basis (contains data layouts) for a given basis description (throws error if integratio...
Teuchos::RCP< panzer::SubcellConnectivity > _face_connectivity
std::map< size_t, Teuchos::RCP< const panzer::IntegrationValues2< double > > > _integrator_map
std::vector< Teuchos::RCP< panzer::IntegrationValues2< double > > > int_rules
panzer::LocalOrdinal num_ghstd_cells
int getOrder() const
Get order of basis.
KOKKOS_INLINE_FUNCTION int numSubcells() const
Gives number of subcells (e.g. faces) in connectivity.
const panzer::IntegrationRule & getIntegrationRule(const panzer::IntegrationDescriptor &description) const
Grab the integration rule (contains data layouts) for a given integration description (throws error i...
const std::vector< panzer::IntegrationDescriptor > & getIntegrators() const
Get a list of integrators being requested.
Kokkos::View< const int *, PHX::Device > cell_local_ids_k
const std::string & getType() const
Get unique string associated with the type of point descriptor. This will be used generate a hash to ...
std::ostream & operator<<(std::ostream &os, const AssemblyEngineInArgs &in)
std::map< size_t, Teuchos::RCP< const panzer::PointValues2< double > > > _point_map
Description and data layouts associated with a particular basis.
#define TEUCHOS_ASSERT(assertion_test)
void populateValueArrays(std::size_t num_cells, bool isSide, const WorksetNeeds &needs, WorksetDetails &details, const Teuchos::RCP< WorksetDetails > other_details)
const panzer::SubcellConnectivity & getFaceConnectivity() const
Grab the face connectivity for this workset.
const panzer::PointValues2< double > & getPointValues(const panzer::PointDescriptor &point_description) const
Grab the basis values for a given basis description and integration description (throws error if it d...
std::vector< GO > cell_local_ids
const int & getOrder() const
Get order of integrator.