43 #ifndef __Panzer_Workset_Builder_impl_hpp__
44 #define __Panzer_Workset_Builder_impl_hpp__
56 #include "Phalanx_DataLayout_MDALayout.hpp"
59 #include "Shards_CellTopology.hpp"
60 #include "Intrepid2_DefaultCubatureFactory.hpp"
61 #include "Intrepid2_CellTools.hpp"
62 #include "Intrepid2_FunctionSpaceTools.hpp"
63 #include "Intrepid2_Basis.hpp"
65 template<
typename ArrayT>
68 const std::string & elementBlock,
69 const std::vector<std::size_t>& local_cell_ids,
70 const ArrayT& vertex_coordinates)
79 std::size_t total_num_cells = local_cell_ids.size();
81 std::size_t workset_size = needs.cellData.numCells();
85 std::vector<panzer::Workset>& worksets = *worksets_ptr;
88 if(total_num_cells==0) {
91 RCP<vector<int> > ir_degrees =
rcp(
new vector<int>(0));
92 RCP<vector<string> > basis_names =
rcp(
new vector<string>(0));
95 std::vector<panzer::Workset>::iterator i = worksets.begin();
97 i->block_id = elementBlock;
98 i->ir_degrees = ir_degrees;
99 i->basis_names = basis_names;
101 for (std::size_t j=0;j<needs.int_rules.size();j++) {
103 RCP<panzer::IntegrationValues2<double> > iv2 =
105 iv2->setupArrays(needs.int_rules[j]);
107 ir_degrees->push_back(needs.int_rules[j]->cubature_degree);
108 i->int_rules.push_back(iv2);
112 for (std::size_t j=0;j<needs.int_rules.size();j++) {
113 for (std::size_t b=0;b<needs.bases.size();b++) {
114 RCP<panzer::BasisIRLayout> b_layout
117 RCP<panzer::BasisValues2<double> > bv2
119 bv2->setupArrays(b_layout);
120 i->bases.push_back(bv2);
122 basis_names->push_back(b_layout->name());
131 std::size_t num_worksets = total_num_cells / workset_size;
132 bool last_set_is_full =
true;
133 std::size_t last_workset_size = total_num_cells % workset_size;
134 if (last_workset_size != 0) {
136 last_set_is_full =
false;
139 worksets.resize(num_worksets);
140 std::vector<panzer::Workset>::iterator i;
141 for (i = worksets.begin(); i != worksets.end(); ++i)
142 i->num_cells = workset_size;
144 if (!last_set_is_full) {
145 worksets.back().num_cells = last_workset_size;
150 std::vector<std::size_t>::const_iterator local_begin = local_cell_ids.begin();
151 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
152 std::vector<std::size_t>::const_iterator begin_iter = local_begin;
153 std::vector<std::size_t>::const_iterator end_iter = begin_iter + wkst->num_cells;
154 local_begin = end_iter;
155 wkst->cell_local_ids.assign(begin_iter,end_iter);
157 Kokkos::View<int*,PHX::Device> cell_local_ids_k = Kokkos::View<int*,PHX::Device>(
"Workset:cell_local_ids",wkst->cell_local_ids.size());
158 for(std::size_t i=0;i<wkst->cell_local_ids.size();i++)
159 cell_local_ids_k(i) = wkst->cell_local_ids[i];
160 wkst->cell_local_ids_k = cell_local_ids_k;
162 wkst->cell_vertex_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cvc",workset_size,
163 vertex_coordinates.extent(1),
164 vertex_coordinates.extent(2));
165 wkst->block_id = elementBlock;
166 wkst->subcell_dim = needs.cellData.baseCellDimension();
167 wkst->subcell_index = 0;
173 std::size_t offset = 0;
174 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
175 for (index_t cell = 0; cell < wkst->num_cells; ++cell)
176 for (std::size_t vertex = 0; vertex < Teuchos::as<std::size_t>(vertex_coordinates.extent(1)); ++ vertex)
177 for (std::size_t dim = 0; dim < Teuchos::as<std::size_t>(vertex_coordinates.extent(2)); ++ dim) {
179 wkst->cell_vertex_coordinates(cell,vertex,dim) = vertex_coordinates(cell + offset,vertex,dim);
182 offset += wkst->num_cells;
185 TEUCHOS_ASSERT(offset == Teuchos::as<std::size_t>(vertex_coordinates.extent(0)));
188 RCP<vector<int> > ir_degrees =
rcp(
new vector<int>(0));
189 RCP<vector<string> > basis_names =
rcp(
new vector<string>(0));
190 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
191 wkst->ir_degrees = ir_degrees;
192 wkst->basis_names = basis_names;
196 for(std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst)
205 template<
typename ArrayT>
208 const std::string & elementBlock,
209 const std::vector<std::size_t>& local_cell_ids,
210 const std::vector<std::size_t>& local_side_ids,
211 const ArrayT& vertex_coordinates,
212 const bool populate_value_arrays)
231 TEUCHOS_ASSERT(local_side_ids.size() ==
static_cast<std::size_t
>(vertex_coordinates.extent(0)));
234 std::map<unsigned,std::vector<std::pair<std::size_t,std::size_t> > > element_list;
235 for (std::size_t cell=0; cell < local_cell_ids.size(); ++cell)
236 element_list[local_side_ids[cell]].push_back(std::make_pair(cell,local_cell_ids[cell]));
238 std::map<unsigned,panzer::Workset>& worksets = *worksets_ptr;
241 std::map<unsigned,std::vector<std::pair<std::size_t,std::size_t> > >::const_iterator side;
242 for (side = element_list.begin(); side != element_list.end(); ++side) {
244 std::vector<std::size_t>& cell_local_ids = worksets[side->first].cell_local_ids;
246 worksets[side->first].cell_vertex_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cvc",
248 vertex_coordinates.extent(1),
249 vertex_coordinates.extent(2));
250 Workset::CellCoordArray coords = worksets[side->first].cell_vertex_coordinates;
252 for (std::size_t cell = 0; cell < side->second.size(); ++cell) {
253 cell_local_ids.push_back(side->second[cell].second);
255 for (std::size_t vertex = 0; vertex < Teuchos::as<std::size_t>(vertex_coordinates.extent(1)); ++ vertex)
256 for (std::size_t dim = 0; dim < Teuchos::as<std::size_t>(vertex_coordinates.extent(2)); ++ dim) {
257 coords(cell,vertex,dim) = vertex_coordinates(side->second[cell].first,vertex,dim);
261 Kokkos::View<int*,PHX::Device> cell_local_ids_k = Kokkos::View<int*,PHX::Device>(
"Workset:cell_local_ids",worksets[side->first].cell_local_ids.size());
262 for(std::size_t i=0;i<worksets[side->first].cell_local_ids.size();i++)
263 cell_local_ids_k(i) = worksets[side->first].cell_local_ids[i];
264 worksets[side->first].cell_local_ids_k = cell_local_ids_k;
266 worksets[side->first].num_cells = worksets[side->first].cell_local_ids.size();
267 worksets[side->first].block_id = elementBlock;
268 worksets[side->first].subcell_dim = needs.cellData.baseCellDimension() - 1;
269 worksets[side->first].subcell_index = side->first;
272 if (populate_value_arrays) {
274 for (std::map<unsigned,panzer::Workset>::iterator wkst = worksets.begin();
275 wkst != worksets.end(); ++wkst) {
302 const std::vector<std::size_t>& sib )
306 auto sip2i_p =
Teuchos::rcp(
new std::map< std::pair<std::size_t, std::size_t>, std::vector<std::size_t> >);
307 auto& sip2i = *sip2i_p;
309 for (std::size_t i = 0; i < sia.size(); ++i)
310 sip2i[std::make_pair(sia[i], sib[i])].push_back(i);
316 template <
typename T>
317 void subset(
const std::vector<T>& a,
const std::vector<std::size_t>& idxs, std::vector<T>& s)
319 s.resize(idxs.size());
320 for (std::size_t i = 0; i < idxs.size(); ++i)
324 template<
typename ArrayT>
327 const std::string & blockid_a,
328 const std::vector<std::size_t>& local_cell_ids_a,
329 const std::vector<std::size_t>& local_side_ids_a,
330 const ArrayT& vertex_coordinates_a,
332 const std::string & blockid_b,
333 const std::vector<std::size_t>& local_cell_ids_b,
334 const std::vector<std::size_t>& local_side_ids_b,
335 const ArrayT& vertex_coordinates_b,
338 TEUCHOS_ASSERT(local_cell_ids_a.size() == local_cell_ids_b.size());
341 mwa =
buildBCWorkset(needs_a,blockid_a, local_cell_ids_a, local_side_ids_a, vertex_coordinates_a),
342 mwb =
buildBCWorkset(needs_b2, blockid_b, local_cell_ids_b, local_side_ids_b,
343 vertex_coordinates_b,
false );
345 for (std::map<unsigned,panzer::Workset>::iterator ait = mwa->begin(), bit = mwb->begin();
346 ait != mwa->end(); ++ait, ++bit) {
347 TEUCHOS_ASSERT(Teuchos::as<std::size_t>(ait->second.num_cells) == local_cell_ids_a.size() &&
348 Teuchos::as<std::size_t>(bit->second.num_cells) == local_cell_ids_b.size());
353 populateValueArrays(wa.num_cells,
true, needs_b, wa.details(1), Teuchos::rcpFromRef(wa.details(0)));
365 template<
typename ArrayT>
368 const std::string & blockid_a,
369 const std::vector<std::size_t>& local_cell_ids_a,
370 const std::vector<std::size_t>& local_side_ids_a,
371 const ArrayT& vertex_coordinates_a,
373 const std::string & blockid_b,
374 const std::vector<std::size_t>& local_cell_ids_b,
375 const std::vector<std::size_t>& local_side_ids_b,
376 const ArrayT& vertex_coordinates_b)
383 if (side_id_associations->size() == 1) {
386 needs_b, blockid_b, local_cell_ids_b, local_side_ids_b, vertex_coordinates_b,
392 std::vector<std::size_t> lci_a, lci_b, lsi_a, lsi_b;
394 const int d1 = Teuchos::as<std::size_t>(vertex_coordinates_a.extent(1)),
395 d2 = Teuchos::as<std::size_t>(vertex_coordinates_a.extent(2));
396 for (
auto it : *side_id_associations) {
397 const auto& idxs = it.second;
404 for (std::size_t i = 0; i < idxs.size(); ++i) {
405 const auto ii = idxs[i];
406 for (
int j = 0; j < d1; ++j)
407 for (
int k = 0; k < d2; ++k) {
408 vc_a(i, j, k) = vertex_coordinates_a(ii, j, k);
409 vc_b(i, j, k) = vertex_coordinates_b(ii, j, k);
413 needs_b,blockid_b, lci_b, lsi_b, vc_b,
420 const std::size_t key = lsi_a[0] * 1000 + lsi_b[0];
421 (*mwa)[key] = mwa_it->begin()->second;
430 template<
typename ArrayT>
433 const std::string & eblock_a,
434 const std::vector<std::size_t>& local_cell_ids_a,
435 const std::vector<std::size_t>& local_side_ids_a,
436 const ArrayT& vertex_coordinates_a,
437 const WorksetNeeds & needs_b,
438 const std::string & eblock_b,
439 const std::vector<std::size_t>& local_cell_ids_b,
440 const std::vector<std::size_t>& local_side_ids_b,
441 const ArrayT& vertex_coordinates_b)
448 std::size_t total_num_cells_a = local_cell_ids_a.size();
449 std::size_t total_num_cells_b = local_cell_ids_b.size();
452 TEUCHOS_ASSERT(local_side_ids_a.size() == local_cell_ids_a.size());
453 TEUCHOS_ASSERT(local_side_ids_a.size() ==
static_cast<std::size_t
>(vertex_coordinates_a.extent(0)));
454 TEUCHOS_ASSERT(local_side_ids_b.size() == local_cell_ids_b.size());
455 TEUCHOS_ASSERT(local_side_ids_b.size() ==
static_cast<std::size_t
>(vertex_coordinates_b.extent(0)));
457 std::size_t total_num_cells = total_num_cells_a;
459 std::size_t workset_size = needs_a.cellData.numCells();
463 std::vector<panzer::Workset>& worksets = *worksets_ptr;
466 if(total_num_cells==0) {
469 RCP<std::vector<int> > ir_degrees =
rcp(
new std::vector<int>(0));
470 RCP<std::vector<std::string> > basis_names =
rcp(
new std::vector<std::string>(0));
473 std::vector<panzer::Workset>::iterator i = worksets.begin();
475 i->details(0).block_id = eblock_a;
477 i->details(1).block_id = eblock_b;
480 i->ir_degrees = ir_degrees;
481 i->basis_names = basis_names;
483 for(std::size_t j=0;j<needs_a.int_rules.size();j++) {
485 RCP<panzer::IntegrationValues2<double> > iv2 =
487 iv2->setupArrays(needs_a.int_rules[j]);
489 ir_degrees->push_back(needs_a.int_rules[j]->cubature_degree);
490 i->int_rules.push_back(iv2);
494 for(std::size_t j=0;j<needs_a.int_rules.size();j++) {
496 for(std::size_t b=0;b<needs_a.bases.size();b++) {
500 RCP<panzer::BasisValues2<double> > bv2 =
502 bv2->setupArrays(b_layout);
503 i->bases.push_back(bv2);
505 basis_names->push_back(b_layout->name());
516 std::map<std::pair<unsigned,unsigned>,std::vector<std::size_t> > element_list;
517 for (std::size_t cell=0; cell < local_cell_ids_a.size(); ++cell)
518 element_list[std::make_pair(local_side_ids_a[cell],local_side_ids_b[cell])].push_back(cell);
521 std::map<std::pair<unsigned,unsigned>,std::vector<std::size_t> >::const_iterator edge;
524 std::size_t num_worksets = 0;
525 for(edge=element_list.begin(); edge!=element_list.end();++edge) {
526 std::size_t num_worksets_for_edge = edge->second.size() / workset_size;
527 std::size_t last_workset_size = edge->second.size() % workset_size;
528 if(last_workset_size!=0)
529 num_worksets_for_edge += 1;
531 num_worksets += num_worksets_for_edge;
533 worksets.resize(num_worksets);
536 std::vector<Workset>::iterator current_workset = worksets.begin();
537 for(edge=element_list.begin(); edge!=element_list.end();++edge) {
539 const std::vector<std::size_t> & cell_indices = edge->second;
542 needs_a,eblock_a,local_cell_ids_a,local_side_ids_a,vertex_coordinates_a,
543 needs_b,eblock_b,local_cell_ids_b,local_side_ids_b,vertex_coordinates_b,
553 template<
typename ArrayT>
554 std::vector<panzer::Workset>::iterator
556 const WorksetNeeds & needs_a,
557 const std::string & eblock_a,
558 const std::vector<std::size_t>& local_cell_ids_a,
559 const std::vector<std::size_t>& local_side_ids_a,
560 const ArrayT& vertex_coordinates_a,
561 const WorksetNeeds & needs_b,
562 const std::string & eblock_b,
563 const std::vector<std::size_t>& local_cell_ids_b,
564 const std::vector<std::size_t>& local_side_ids_b,
565 const ArrayT& vertex_coordinates_b,
566 std::vector<Workset>::iterator beg)
570 std::vector<Workset>::iterator wkst = beg;
572 std::size_t current_cell_index = 0;
573 while (current_cell_index<cell_indices.size()) {
574 std::size_t workset_size = needs_a.cellData.numCells();
580 wkst->subcell_dim = needs_a.cellData.baseCellDimension()-1;
582 wkst->details(0).subcell_index = local_side_ids_a[cell_indices[current_cell_index]];
583 wkst->details(0).block_id = eblock_a;
584 wkst->details(0).cell_vertex_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cvc",workset_size,
585 vertex_coordinates_a.extent(1),
586 vertex_coordinates_a.extent(2));
588 wkst->details(1).subcell_index = local_side_ids_b[cell_indices[current_cell_index]];
589 wkst->details(1).block_id = eblock_b;
590 wkst->details(1).cell_vertex_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cvc",workset_size,
591 vertex_coordinates_a.extent(1),
592 vertex_coordinates_a.extent(2));
594 std::size_t remaining_cells = cell_indices.size()-current_cell_index;
595 if(remaining_cells<workset_size)
596 workset_size = remaining_cells;
599 wkst->num_cells = workset_size;
600 wkst->details(0).cell_local_ids.resize(workset_size);
601 wkst->details(1).cell_local_ids.resize(workset_size);
603 for(std::size_t cell=0;cell<workset_size; cell++,current_cell_index++) {
605 wkst->details(0).cell_local_ids[cell] = local_cell_ids_a[cell_indices[current_cell_index]];
606 wkst->details(1).cell_local_ids[cell] = local_cell_ids_b[cell_indices[current_cell_index]];
608 for (std::size_t vertex = 0; vertex < Teuchos::as<std::size_t>(vertex_coordinates_a.extent(1)); ++ vertex) {
609 for (std::size_t dim = 0; dim < Teuchos::as<std::size_t>(vertex_coordinates_a.extent(2)); ++ dim) {
610 wkst->details(0).cell_vertex_coordinates(cell,vertex,dim) = vertex_coordinates_a(cell_indices[current_cell_index],vertex,dim);
611 wkst->details(1).cell_vertex_coordinates(cell,vertex,dim) = vertex_coordinates_b(cell_indices[current_cell_index],vertex,dim);
616 Kokkos::View<int*,PHX::Device> cell_local_ids_k_0 = Kokkos::View<int*,PHX::Device>(
"Workset:cell_local_ids",wkst->details(0).cell_local_ids.size());
617 Kokkos::View<int*,PHX::Device> cell_local_ids_k_1 = Kokkos::View<int*,PHX::Device>(
"Workset:cell_local_ids",wkst->details(1).cell_local_ids.size());
618 for(std::size_t i=0;i<wkst->details(0).cell_local_ids.size();i++)
619 cell_local_ids_k_0(i) = wkst->details(0).cell_local_ids[i];
620 for(std::size_t i=0;i<wkst->details(1).cell_local_ids.size();i++)
621 cell_local_ids_k_1(i) = wkst->details(1).cell_local_ids[i];
622 wkst->details(0).cell_local_ids_k = cell_local_ids_k_0;
623 wkst->details(1).cell_local_ids_k = cell_local_ids_k_1;
626 std::size_t max_workset_size = needs_a.cellData.numCells();
628 populateValueArrays(max_workset_size,
true,needs_b,wkst->details(1),Teuchos::rcpFromRef(wkst->details(0)));
Teuchos::RCP< std::vector< Workset > > buildEdgeWorksets(const WorksetNeeds &needs_a, const std::string &eblock_a, const std::vector< std::size_t > &local_cell_ids_a, const std::vector< std::size_t > &local_side_ids_a, const ArrayT &vertex_coordinates_a, const WorksetNeeds &needs_b, const std::string &eblock_b, const std::vector< std::size_t > &local_cell_ids_b, const std::vector< std::size_t > &local_side_ids_b, const ArrayT &vertex_coordinates_b)
Teuchos::RCP< std::vector< Workset > > buildWorksets(const WorksetNeeds &needs, const std::string &elementBlock, const std::vector< std::size_t > &local_cell_ids, const ArrayT &vertex_coordinates)
PHX::MDField< Scalar, T0 > buildStaticArray(const std::string &str, int d0) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< std::map< unsigned, Workset > > buildBCWorkset(const WorksetNeeds &needs, const std::string &elementBlock, const std::vector< std::size_t > &local_cell_ids, const std::vector< std::size_t > &local_side_ids, const ArrayT &vertex_coordinates, const bool populate_value_arrays=true)
Teuchos::RCP< std::map< std::pair< std::size_t, std::size_t >, std::vector< std::size_t > > > associateCellsBySideIds(const std::vector< std::size_t > &sia, const std::vector< std::size_t > &sib)
Teuchos::RCP< WorksetDetails > other
Teuchos::RCP< std::map< unsigned, panzer::Workset > > buildBCWorksetForUniqueSideId(const panzer::WorksetNeeds &needs_a, const std::string &blockid_a, const std::vector< std::size_t > &local_cell_ids_a, const std::vector< std::size_t > &local_side_ids_a, const ArrayT &vertex_coordinates_a, const panzer::WorksetNeeds &needs_b, const std::string &blockid_b, const std::vector< std::size_t > &local_cell_ids_b, const std::vector< std::size_t > &local_side_ids_b, const ArrayT &vertex_coordinates_b, const WorksetNeeds &needs_b2)
void subset(const std::vector< T > &a, const std::vector< std::size_t > &idxs, std::vector< T > &s)
#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)