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& node_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();
96 i->setNumberOfCells(0,0,0);
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->setNumberOfCells(workset_size,0,0);
144 if (!last_set_is_full) {
145 worksets.back().setNumberOfCells(last_workset_size,0,0);
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 PHX::View<int*> cell_local_ids_k = PHX::View<int*>(
"Workset:cell_local_ids",wkst->cell_local_ids.size());
158 auto cell_local_ids_k_h = Kokkos::create_mirror_view(cell_local_ids_k);
159 for(std::size_t i=0;i<wkst->cell_local_ids.size();i++)
160 cell_local_ids_k_h(i) = wkst->cell_local_ids[i];
161 Kokkos::deep_copy(cell_local_ids_k, cell_local_ids_k_h);
162 wkst->cell_local_ids_k = cell_local_ids_k;
164 wkst->cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",workset_size,
165 node_coordinates.extent(1),
166 node_coordinates.extent(2));
167 wkst->block_id = elementBlock;
168 wkst->subcell_dim = needs.cellData.baseCellDimension();
169 wkst->subcell_index = 0;
175 std::size_t offset = 0;
176 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
177 auto cell_node_coordinates = wkst->cell_node_coordinates.get_static_view();
178 Kokkos::parallel_for(wkst->num_cells, KOKKOS_LAMBDA (
int cell) {
179 for (std::size_t node = 0; node < node_coordinates.extent(1); ++ node)
180 for (std::size_t dim = 0; dim < node_coordinates.extent(2); ++ dim) {
181 cell_node_coordinates(cell,node,dim) = node_coordinates(cell + offset,node,dim);
185 offset += wkst->num_cells;
188 TEUCHOS_ASSERT(offset == Teuchos::as<std::size_t>(node_coordinates.extent(0)));
191 RCP<vector<int> > ir_degrees =
rcp(
new vector<int>(0));
192 RCP<vector<string> > basis_names =
rcp(
new vector<string>(0));
193 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
194 wkst->ir_degrees = ir_degrees;
195 wkst->basis_names = basis_names;
199 for(std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst)
208 template<
typename ArrayT>
211 const std::string & elementBlock,
212 const std::vector<std::size_t>& local_cell_ids,
213 const std::vector<std::size_t>& local_side_ids,
214 const ArrayT& node_coordinates,
215 const bool populate_value_arrays)
224 auto worksets_ptr =
Teuchos::rcp(
new std::map<unsigned,panzer::Workset>);
233 TEUCHOS_ASSERT(local_side_ids.size() ==
static_cast<std::size_t
>(node_coordinates.extent(0)));
236 std::map< unsigned, std::vector< std::pair< std::size_t, std::size_t>>> element_list;
237 for (std::size_t cell = 0; cell < local_cell_ids.size(); ++cell)
238 element_list[local_side_ids[cell]].push_back(std::make_pair(cell, local_cell_ids[cell]));
240 auto& worksets = *worksets_ptr;
243 for (
const auto& side : element_list) {
245 auto& cell_local_ids = worksets[side.first].cell_local_ids;
247 worksets[side.first].cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",
249 node_coordinates.extent(1),
250 node_coordinates.extent(2));
251 auto coords_view = worksets[side.first].cell_node_coordinates.get_view();
252 auto coords_h = Kokkos::create_mirror_view(coords_view);
254 auto node_coordinates_h = Kokkos::create_mirror_view(PHX::as_view(node_coordinates));
255 Kokkos::deep_copy(node_coordinates_h, PHX::as_view(node_coordinates));
257 for (std::size_t cell = 0; cell < side.second.size(); ++cell) {
258 cell_local_ids.push_back(side.second[cell].second);
259 const auto dim0 = side.second[cell].first;
261 for(std::size_t node = 0; node < node_coordinates.extent(1); ++node)
263 const auto extent = Teuchos::as<std::size_t>(node_coordinates.extent(2));
265 for (std::size_t dim = 0; dim < extent; ++dim)
266 coords_h(cell, node, dim) = node_coordinates_h(dim0, node, dim);
270 Kokkos::deep_copy(coords_view, coords_h);
272 const auto cell_local_ids_size = worksets[side.first].cell_local_ids.size();
273 auto cell_local_ids_k = PHX::View<int*>(
"Workset:cell_local_ids", cell_local_ids_size);
274 auto cell_local_ids_k_h = Kokkos::create_mirror_view(cell_local_ids_k);
276 for(std::size_t i = 0; i < cell_local_ids_size; ++i){
277 cell_local_ids_k_h(i) = worksets.at(side.first).cell_local_ids[i];
280 Kokkos::deep_copy(cell_local_ids_k, cell_local_ids_k_h);
282 worksets[side.first].cell_local_ids_k = cell_local_ids_k;
283 worksets[side.first].num_cells = worksets[side.first].cell_local_ids.size();
284 worksets[side.first].block_id = elementBlock;
285 worksets[side.first].subcell_dim = needs.cellData.baseCellDimension() - 1;
286 worksets[side.first].subcell_index = side.first;
289 if (populate_value_arrays) {
291 for (std::map<unsigned,panzer::Workset>::iterator wkst = worksets.begin();
292 wkst != worksets.end(); ++wkst) {
319 const std::vector<std::size_t>& sib )
323 auto sip2i_p =
Teuchos::rcp(
new std::map< std::pair<std::size_t, std::size_t>, std::vector<std::size_t> >);
324 auto& sip2i = *sip2i_p;
326 for (std::size_t i = 0; i < sia.size(); ++i)
327 sip2i[std::make_pair(sia[i], sib[i])].push_back(i);
333 template <
typename T>
334 void subset(
const std::vector<T>& a,
const std::vector<std::size_t>& idxs, std::vector<T>& s)
336 s.resize(idxs.size());
337 for (std::size_t i = 0; i < idxs.size(); ++i)
341 template<
typename ArrayT>
344 const std::string & blockid_a,
345 const std::vector<std::size_t>& local_cell_ids_a,
346 const std::vector<std::size_t>& local_side_ids_a,
347 const ArrayT& node_coordinates_a,
349 const std::string & blockid_b,
350 const std::vector<std::size_t>& local_cell_ids_b,
351 const std::vector<std::size_t>& local_side_ids_b,
352 const ArrayT& node_coordinates_b,
355 TEUCHOS_ASSERT(local_cell_ids_a.size() == local_cell_ids_b.size());
358 mwa =
buildBCWorkset(needs_a,blockid_a, local_cell_ids_a, local_side_ids_a, node_coordinates_a),
359 mwb =
buildBCWorkset(needs_b2, blockid_b, local_cell_ids_b, local_side_ids_b,
360 node_coordinates_b,
false );
362 for (std::map<unsigned,panzer::Workset>::iterator ait = mwa->begin(), bit = mwb->begin();
363 ait != mwa->end(); ++ait, ++bit) {
364 TEUCHOS_ASSERT(Teuchos::as<std::size_t>(ait->second.num_cells) == local_cell_ids_a.size() &&
365 Teuchos::as<std::size_t>(bit->second.num_cells) == local_cell_ids_b.size());
370 populateValueArrays(wa.num_cells,
true, needs_b, wa.details(1), Teuchos::rcpFromRef(wa.details(0)));
382 template<
typename ArrayT>
385 const std::string & blockid_a,
386 const std::vector<std::size_t>& local_cell_ids_a,
387 const std::vector<std::size_t>& local_side_ids_a,
388 const ArrayT& node_coordinates_a,
390 const std::string & blockid_b,
391 const std::vector<std::size_t>& local_cell_ids_b,
392 const std::vector<std::size_t>& local_side_ids_b,
393 const ArrayT& node_coordinates_b)
400 if (side_id_associations->size() == 1) {
403 needs_b, blockid_b, local_cell_ids_b, local_side_ids_b, node_coordinates_b,
409 std::vector<std::size_t> lci_a, lci_b, lsi_a, lsi_b;
411 const int d1 = Teuchos::as<std::size_t>(node_coordinates_a.extent(1)),
412 d2 = Teuchos::as<std::size_t>(node_coordinates_a.extent(2));
413 for (
auto it : *side_id_associations) {
414 const auto& idxs = it.second;
421 auto nc_a_h = Kokkos::create_mirror_view(nc_a.get_static_view());
422 auto nc_b_h = Kokkos::create_mirror_view(nc_b.get_static_view());
423 auto node_coordinates_a_h = Kokkos::create_mirror_view(PHX::as_view(node_coordinates_a));
424 auto node_coordinates_b_h = Kokkos::create_mirror_view(PHX::as_view(node_coordinates_b));
425 Kokkos::deep_copy(node_coordinates_a_h, PHX::as_view(node_coordinates_a));
426 Kokkos::deep_copy(node_coordinates_b_h, PHX::as_view(node_coordinates_b));
427 for (std::size_t i = 0; i < idxs.size(); ++i) {
428 const auto ii = idxs[i];
429 for (
int j = 0; j < d1; ++j)
430 for (
int k = 0; k < d2; ++k) {
431 nc_a_h(i, j, k) = node_coordinates_a_h(ii, j, k);
432 nc_b_h(i, j, k) = node_coordinates_b_h(ii, j, k);
435 Kokkos::deep_copy(nc_a.get_static_view(), nc_a_h);
436 Kokkos::deep_copy(nc_b.get_static_view(), nc_b_h);
438 needs_b,blockid_b, lci_b, lsi_b, nc_b,
445 const std::size_t key = lsi_a[0] * 1000 + lsi_b[0];
446 (*mwa)[key] = mwa_it->begin()->second;
455 template<
typename ArrayT>
458 const std::string & eblock_a,
459 const std::vector<std::size_t>& local_cell_ids_a,
460 const std::vector<std::size_t>& local_side_ids_a,
461 const ArrayT& node_coordinates_a,
462 const WorksetNeeds & needs_b,
463 const std::string & eblock_b,
464 const std::vector<std::size_t>& local_cell_ids_b,
465 const std::vector<std::size_t>& local_side_ids_b,
466 const ArrayT& node_coordinates_b)
473 std::size_t total_num_cells_a = local_cell_ids_a.size();
474 std::size_t total_num_cells_b = local_cell_ids_b.size();
477 TEUCHOS_ASSERT(local_side_ids_a.size() == local_cell_ids_a.size());
478 TEUCHOS_ASSERT(local_side_ids_a.size() ==
static_cast<std::size_t
>(node_coordinates_a.extent(0)));
479 TEUCHOS_ASSERT(local_side_ids_b.size() == local_cell_ids_b.size());
480 TEUCHOS_ASSERT(local_side_ids_b.size() ==
static_cast<std::size_t
>(node_coordinates_b.extent(0)));
482 std::size_t total_num_cells = total_num_cells_a;
484 std::size_t workset_size = needs_a.cellData.numCells();
488 std::vector<panzer::Workset>& worksets = *worksets_ptr;
491 if(total_num_cells==0) {
494 RCP<std::vector<int> > ir_degrees =
rcp(
new std::vector<int>(0));
495 RCP<std::vector<std::string> > basis_names =
rcp(
new std::vector<std::string>(0));
498 std::vector<panzer::Workset>::iterator i = worksets.begin();
500 i->details(0).block_id = eblock_a;
502 i->details(1).block_id = eblock_b;
505 i->ir_degrees = ir_degrees;
506 i->basis_names = basis_names;
508 for(std::size_t j=0;j<needs_a.int_rules.size();j++) {
510 RCP<panzer::IntegrationValues2<double> > iv2 =
512 iv2->setupArrays(needs_a.int_rules[j]);
514 ir_degrees->push_back(needs_a.int_rules[j]->cubature_degree);
515 i->int_rules.push_back(iv2);
519 for(std::size_t j=0;j<needs_a.int_rules.size();j++) {
521 for(std::size_t b=0;b<needs_a.bases.size();b++) {
525 RCP<panzer::BasisValues2<double> > bv2 =
527 bv2->setupArrays(b_layout);
528 i->bases.push_back(bv2);
530 basis_names->push_back(b_layout->name());
541 std::map<std::pair<unsigned,unsigned>,std::vector<std::size_t> > element_list;
542 for (std::size_t cell=0; cell < local_cell_ids_a.size(); ++cell)
543 element_list[std::make_pair(local_side_ids_a[cell],local_side_ids_b[cell])].push_back(cell);
546 std::size_t num_worksets = 0;
547 for(
const auto& edge : element_list) {
548 std::size_t num_worksets_for_edge = edge.second.size() / workset_size;
549 std::size_t last_workset_size = edge.second.size() % workset_size;
550 if(last_workset_size!=0)
551 num_worksets_for_edge += 1;
553 num_worksets += num_worksets_for_edge;
555 worksets.resize(num_worksets);
558 std::vector<Workset>::iterator current_workset = worksets.begin();
559 for(
const auto& edge : element_list) {
561 const std::vector<std::size_t> & cell_indices = edge.second;
564 needs_a,eblock_a,local_cell_ids_a,local_side_ids_a,node_coordinates_a,
565 needs_b,eblock_b,local_cell_ids_b,local_side_ids_b,node_coordinates_b,
575 template<
typename ArrayT>
576 std::vector<panzer::Workset>::iterator
578 const WorksetNeeds & needs_a,
579 const std::string & eblock_a,
580 const std::vector<std::size_t>& local_cell_ids_a,
581 const std::vector<std::size_t>& local_side_ids_a,
582 const ArrayT& node_coordinates_a,
583 const WorksetNeeds & needs_b,
584 const std::string & eblock_b,
585 const std::vector<std::size_t>& local_cell_ids_b,
586 const std::vector<std::size_t>& local_side_ids_b,
587 const ArrayT& node_coordinates_b,
588 std::vector<Workset>::iterator beg)
592 std::vector<Workset>::iterator wkst = beg;
594 std::size_t current_cell_index = 0;
595 while (current_cell_index<cell_indices.size()) {
596 std::size_t workset_size = needs_a.cellData.numCells();
602 wkst->subcell_dim = needs_a.cellData.baseCellDimension()-1;
604 wkst->details(0).subcell_index = local_side_ids_a[cell_indices[current_cell_index]];
605 wkst->details(0).block_id = eblock_a;
606 wkst->details(0).cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",workset_size,
607 node_coordinates_a.extent(1),
608 node_coordinates_a.extent(2));
610 wkst->details(1).subcell_index = local_side_ids_b[cell_indices[current_cell_index]];
611 wkst->details(1).block_id = eblock_b;
612 wkst->details(1).cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",workset_size,
613 node_coordinates_a.extent(1),
614 node_coordinates_a.extent(2));
616 std::size_t remaining_cells = cell_indices.size()-current_cell_index;
617 if(remaining_cells<workset_size)
618 workset_size = remaining_cells;
621 wkst->setNumberOfCells(workset_size,0,0);
622 wkst->details(0).cell_local_ids.resize(workset_size);
623 wkst->details(1).cell_local_ids.resize(workset_size);
625 auto dim0_cell_node_coordinates_view = wkst->details(0).cell_node_coordinates.get_static_view();
626 auto dim0_cell_node_coordinates_h = Kokkos::create_mirror_view(dim0_cell_node_coordinates_view);
627 Kokkos::deep_copy(dim0_cell_node_coordinates_h, dim0_cell_node_coordinates_view);
629 auto dim1_cell_node_coordinates_view = wkst->details(1).cell_node_coordinates.get_static_view();
630 auto dim1_cell_node_coordinates_h = Kokkos::create_mirror_view(dim1_cell_node_coordinates_view);
631 Kokkos::deep_copy(dim1_cell_node_coordinates_h, dim1_cell_node_coordinates_view);
633 auto node_coordinates_a_h = Kokkos::create_mirror_view(node_coordinates_a);
634 Kokkos::deep_copy(node_coordinates_a_h, node_coordinates_a);
636 auto node_coordinates_b_h = Kokkos::create_mirror_view(node_coordinates_b);
637 Kokkos::deep_copy(node_coordinates_b_h, node_coordinates_b);
639 for(std::size_t cell=0;cell<workset_size; cell++,current_cell_index++) {
641 wkst->details(0).cell_local_ids[cell] = local_cell_ids_a[cell_indices[current_cell_index]];
642 wkst->details(1).cell_local_ids[cell] = local_cell_ids_b[cell_indices[current_cell_index]];
644 for (std::size_t node = 0; node < Teuchos::as<std::size_t>(node_coordinates_a.extent(1)); ++ node) {
645 for (std::size_t dim = 0; dim < Teuchos::as<std::size_t>(node_coordinates_a.extent(2)); ++ dim) {
646 dim0_cell_node_coordinates_h(cell,node,dim) = node_coordinates_a_h(cell_indices[current_cell_index],node,dim);
647 dim1_cell_node_coordinates_h(cell,node,dim) = node_coordinates_b_h(cell_indices[current_cell_index],node,dim);
652 Kokkos::deep_copy(dim0_cell_node_coordinates_view, dim0_cell_node_coordinates_h);
653 Kokkos::deep_copy(dim1_cell_node_coordinates_view, dim1_cell_node_coordinates_h);
655 auto cell_local_ids_k_0 = PHX::View<int*>(
"Workset:cell_local_ids",wkst->details(0).cell_local_ids.size());
656 auto cell_local_ids_k_0_h = Kokkos::create_mirror_view(cell_local_ids_k_0);
658 auto cell_local_ids_k_1 = PHX::View<int*>(
"Workset:cell_local_ids",wkst->details(1).cell_local_ids.size());
659 auto cell_local_ids_k_1_h = Kokkos::create_mirror_view(cell_local_ids_k_1);
661 for(std::size_t i=0;i<wkst->details(0).cell_local_ids.size();i++)
662 cell_local_ids_k_0_h(i) = wkst->details(0).cell_local_ids[i];
663 for(std::size_t i=0;i<wkst->details(1).cell_local_ids.size();i++)
664 cell_local_ids_k_1_h(i) = wkst->details(1).cell_local_ids[i];
666 Kokkos::deep_copy(cell_local_ids_k_0, cell_local_ids_k_0_h);
667 Kokkos::deep_copy(cell_local_ids_k_1, cell_local_ids_k_1_h);
669 wkst->details(0).cell_local_ids_k = cell_local_ids_k_0;
670 wkst->details(1).cell_local_ids_k = cell_local_ids_k_1;
673 std::size_t max_workset_size = needs_a.cellData.numCells();
675 populateValueArrays(max_workset_size,
true,needs_b,wkst->details(1),Teuchos::rcpFromRef(wkst->details(0)));
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 &node_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 &node_coordinates_b, const WorksetNeeds &needs_b2)
Teuchos::RCP< std::vector< Workset > > buildWorksets(const WorksetNeeds &needs, const std::string &elementBlock, const std::vector< std::size_t > &local_cell_ids, const ArrayT &node_coordinates)
PHX::MDField< Scalar, T0 > buildStaticArray(const std::string &str, int d0) const
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 &node_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 &node_coordinates_b)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
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, 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 &node_coordinates, const bool populate_value_arrays=true)
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)