11 #ifndef __Panzer_Workset_Builder_impl_hpp__
12 #define __Panzer_Workset_Builder_impl_hpp__
24 #include "Phalanx_DataLayout_MDALayout.hpp"
27 #include "Shards_CellTopology.hpp"
28 #include "Intrepid2_DefaultCubatureFactory.hpp"
29 #include "Intrepid2_CellTools.hpp"
30 #include "Intrepid2_FunctionSpaceTools.hpp"
31 #include "Intrepid2_Basis.hpp"
33 template<
typename ArrayT>
36 const std::string & elementBlock,
37 const std::vector<std::size_t>& local_cell_ids,
38 const ArrayT& node_coordinates)
47 std::size_t total_num_cells = local_cell_ids.size();
49 std::size_t workset_size = needs.cellData.numCells();
53 std::vector<panzer::Workset>& worksets = *worksets_ptr;
56 if(total_num_cells==0) {
59 RCP<vector<int> > ir_degrees =
rcp(
new vector<int>(0));
60 RCP<vector<string> > basis_names =
rcp(
new vector<string>(0));
63 std::vector<panzer::Workset>::iterator i = worksets.begin();
64 i->setNumberOfCells(0,0,0);
65 i->block_id = elementBlock;
66 i->ir_degrees = ir_degrees;
67 i->basis_names = basis_names;
69 for (std::size_t j=0;j<needs.int_rules.size();j++) {
71 RCP<panzer::IntegrationValues2<double> > iv2 =
73 iv2->setupArrays(needs.int_rules[j]);
75 ir_degrees->push_back(needs.int_rules[j]->cubature_degree);
76 i->int_rules.push_back(iv2);
80 for (std::size_t j=0;j<needs.int_rules.size();j++) {
81 for (std::size_t b=0;b<needs.bases.size();b++) {
82 RCP<panzer::BasisIRLayout> b_layout
85 RCP<panzer::BasisValues2<double> > bv2
87 bv2->setupArrays(b_layout);
88 i->bases.push_back(bv2);
90 basis_names->push_back(b_layout->name());
99 std::size_t num_worksets = total_num_cells / workset_size;
100 bool last_set_is_full =
true;
101 std::size_t last_workset_size = total_num_cells % workset_size;
102 if (last_workset_size != 0) {
104 last_set_is_full =
false;
107 worksets.resize(num_worksets);
108 std::vector<panzer::Workset>::iterator i;
109 for (i = worksets.begin(); i != worksets.end(); ++i)
110 i->setNumberOfCells(workset_size,0,0);
112 if (!last_set_is_full) {
113 worksets.back().setNumberOfCells(last_workset_size,0,0);
118 std::vector<std::size_t>::const_iterator local_begin = local_cell_ids.begin();
119 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
120 std::vector<std::size_t>::const_iterator begin_iter = local_begin;
121 std::vector<std::size_t>::const_iterator end_iter = begin_iter + wkst->num_cells;
122 local_begin = end_iter;
123 wkst->cell_local_ids.assign(begin_iter,end_iter);
125 PHX::View<int*> cell_local_ids_k = PHX::View<int*>(
"Workset:cell_local_ids",wkst->cell_local_ids.size());
126 auto cell_local_ids_k_h = Kokkos::create_mirror_view(cell_local_ids_k);
127 for(std::size_t i=0;i<wkst->cell_local_ids.size();i++)
128 cell_local_ids_k_h(i) = wkst->cell_local_ids[i];
129 Kokkos::deep_copy(cell_local_ids_k, cell_local_ids_k_h);
130 wkst->cell_local_ids_k = cell_local_ids_k;
132 wkst->cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",workset_size,
133 node_coordinates.extent(1),
134 node_coordinates.extent(2));
135 wkst->block_id = elementBlock;
136 wkst->subcell_dim = needs.cellData.baseCellDimension();
137 wkst->subcell_index = 0;
143 std::size_t offset = 0;
144 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
145 auto cell_node_coordinates = wkst->cell_node_coordinates.get_static_view();
146 Kokkos::parallel_for(wkst->num_cells, KOKKOS_LAMBDA (
int cell) {
147 for (std::size_t node = 0; node < node_coordinates.extent(1); ++ node)
148 for (std::size_t dim = 0; dim < node_coordinates.extent(2); ++ dim) {
149 cell_node_coordinates(cell,node,dim) = node_coordinates(cell + offset,node,dim);
153 offset += wkst->num_cells;
156 TEUCHOS_ASSERT(offset == Teuchos::as<std::size_t>(node_coordinates.extent(0)));
159 RCP<vector<int> > ir_degrees =
rcp(
new vector<int>(0));
160 RCP<vector<string> > basis_names =
rcp(
new vector<string>(0));
161 for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) {
162 wkst->ir_degrees = ir_degrees;
163 wkst->basis_names = basis_names;
167 for(std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst)
176 template<
typename ArrayT>
179 const std::string & elementBlock,
180 const std::vector<std::size_t>& local_cell_ids,
181 const std::vector<std::size_t>& local_side_ids,
182 const ArrayT& node_coordinates,
183 const bool populate_value_arrays)
192 auto worksets_ptr =
Teuchos::rcp(
new std::map<unsigned,panzer::Workset>);
201 TEUCHOS_ASSERT(local_side_ids.size() ==
static_cast<std::size_t
>(node_coordinates.extent(0)));
204 std::map< unsigned, std::vector< std::pair< std::size_t, std::size_t>>> element_list;
205 for (std::size_t cell = 0; cell < local_cell_ids.size(); ++cell)
206 element_list[local_side_ids[cell]].push_back(std::make_pair(cell, local_cell_ids[cell]));
208 auto& worksets = *worksets_ptr;
211 for (
const auto& side : element_list) {
213 auto& cell_local_ids = worksets[side.first].cell_local_ids;
215 worksets[side.first].cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",
217 node_coordinates.extent(1),
218 node_coordinates.extent(2));
219 auto coords_view = worksets[side.first].cell_node_coordinates.get_view();
220 auto coords_h = Kokkos::create_mirror_view(coords_view);
222 auto node_coordinates_h = Kokkos::create_mirror_view(PHX::as_view(node_coordinates));
223 Kokkos::deep_copy(node_coordinates_h, PHX::as_view(node_coordinates));
225 for (std::size_t cell = 0; cell < side.second.size(); ++cell) {
226 cell_local_ids.push_back(side.second[cell].second);
227 const auto dim0 = side.second[cell].first;
229 for(std::size_t node = 0; node < node_coordinates.extent(1); ++node)
231 const auto extent = Teuchos::as<std::size_t>(node_coordinates.extent(2));
233 for (std::size_t dim = 0; dim < extent; ++dim)
234 coords_h(cell, node, dim) = node_coordinates_h(dim0, node, dim);
238 Kokkos::deep_copy(coords_view, coords_h);
240 const auto cell_local_ids_size = worksets[side.first].cell_local_ids.size();
241 auto cell_local_ids_k = PHX::View<int*>(
"Workset:cell_local_ids", cell_local_ids_size);
242 auto cell_local_ids_k_h = Kokkos::create_mirror_view(cell_local_ids_k);
244 for(std::size_t i = 0; i < cell_local_ids_size; ++i){
245 cell_local_ids_k_h(i) = worksets.at(side.first).cell_local_ids[i];
248 Kokkos::deep_copy(cell_local_ids_k, cell_local_ids_k_h);
250 worksets[side.first].cell_local_ids_k = cell_local_ids_k;
251 worksets[side.first].num_cells = worksets[side.first].cell_local_ids.size();
252 worksets[side.first].block_id = elementBlock;
253 worksets[side.first].subcell_dim = needs.cellData.baseCellDimension() - 1;
254 worksets[side.first].subcell_index = side.first;
257 if (populate_value_arrays) {
259 for (std::map<unsigned,panzer::Workset>::iterator wkst = worksets.begin();
260 wkst != worksets.end(); ++wkst) {
287 const std::vector<std::size_t>& sib )
291 auto sip2i_p =
Teuchos::rcp(
new std::map< std::pair<std::size_t, std::size_t>, std::vector<std::size_t> >);
292 auto& sip2i = *sip2i_p;
294 for (std::size_t i = 0; i < sia.size(); ++i)
295 sip2i[std::make_pair(sia[i], sib[i])].push_back(i);
301 template <
typename T>
302 void subset(
const std::vector<T>& a,
const std::vector<std::size_t>& idxs, std::vector<T>& s)
304 s.resize(idxs.size());
305 for (std::size_t i = 0; i < idxs.size(); ++i)
309 template<
typename ArrayT>
312 const std::string & blockid_a,
313 const std::vector<std::size_t>& local_cell_ids_a,
314 const std::vector<std::size_t>& local_side_ids_a,
315 const ArrayT& node_coordinates_a,
317 const std::string & blockid_b,
318 const std::vector<std::size_t>& local_cell_ids_b,
319 const std::vector<std::size_t>& local_side_ids_b,
320 const ArrayT& node_coordinates_b,
323 TEUCHOS_ASSERT(local_cell_ids_a.size() == local_cell_ids_b.size());
326 mwa =
buildBCWorkset(needs_a,blockid_a, local_cell_ids_a, local_side_ids_a, node_coordinates_a),
327 mwb =
buildBCWorkset(needs_b2, blockid_b, local_cell_ids_b, local_side_ids_b,
328 node_coordinates_b,
false );
330 for (std::map<unsigned,panzer::Workset>::iterator ait = mwa->begin(), bit = mwb->begin();
331 ait != mwa->end(); ++ait, ++bit) {
332 TEUCHOS_ASSERT(Teuchos::as<std::size_t>(ait->second.num_cells) == local_cell_ids_a.size() &&
333 Teuchos::as<std::size_t>(bit->second.num_cells) == local_cell_ids_b.size());
338 populateValueArrays(wa.num_cells,
true, needs_b, wa.details(1), Teuchos::rcpFromRef(wa.details(0)));
350 template<
typename ArrayT>
353 const std::string & blockid_a,
354 const std::vector<std::size_t>& local_cell_ids_a,
355 const std::vector<std::size_t>& local_side_ids_a,
356 const ArrayT& node_coordinates_a,
358 const std::string & blockid_b,
359 const std::vector<std::size_t>& local_cell_ids_b,
360 const std::vector<std::size_t>& local_side_ids_b,
361 const ArrayT& node_coordinates_b)
368 if (side_id_associations->size() == 1) {
371 needs_b, blockid_b, local_cell_ids_b, local_side_ids_b, node_coordinates_b,
377 std::vector<std::size_t> lci_a, lci_b, lsi_a, lsi_b;
379 const int d1 = Teuchos::as<std::size_t>(node_coordinates_a.extent(1)),
380 d2 = Teuchos::as<std::size_t>(node_coordinates_a.extent(2));
381 for (
auto it : *side_id_associations) {
382 const auto& idxs = it.second;
389 auto nc_a_h = Kokkos::create_mirror_view(nc_a.get_static_view());
390 auto nc_b_h = Kokkos::create_mirror_view(nc_b.get_static_view());
391 auto node_coordinates_a_h = Kokkos::create_mirror_view(PHX::as_view(node_coordinates_a));
392 auto node_coordinates_b_h = Kokkos::create_mirror_view(PHX::as_view(node_coordinates_b));
393 Kokkos::deep_copy(node_coordinates_a_h, PHX::as_view(node_coordinates_a));
394 Kokkos::deep_copy(node_coordinates_b_h, PHX::as_view(node_coordinates_b));
395 for (std::size_t i = 0; i < idxs.size(); ++i) {
396 const auto ii = idxs[i];
397 for (
int j = 0; j < d1; ++j)
398 for (
int k = 0; k < d2; ++k) {
399 nc_a_h(i, j, k) = node_coordinates_a_h(ii, j, k);
400 nc_b_h(i, j, k) = node_coordinates_b_h(ii, j, k);
403 Kokkos::deep_copy(nc_a.get_static_view(), nc_a_h);
404 Kokkos::deep_copy(nc_b.get_static_view(), nc_b_h);
406 needs_b,blockid_b, lci_b, lsi_b, nc_b,
413 const std::size_t key = lsi_a[0] * 1000 + lsi_b[0];
414 (*mwa)[key] = mwa_it->begin()->second;
423 template<
typename ArrayT>
426 const std::string & eblock_a,
427 const std::vector<std::size_t>& local_cell_ids_a,
428 const std::vector<std::size_t>& local_side_ids_a,
429 const ArrayT& node_coordinates_a,
430 const WorksetNeeds & needs_b,
431 const std::string & eblock_b,
432 const std::vector<std::size_t>& local_cell_ids_b,
433 const std::vector<std::size_t>& local_side_ids_b,
434 const ArrayT& node_coordinates_b)
441 std::size_t total_num_cells_a = local_cell_ids_a.size();
442 std::size_t total_num_cells_b = local_cell_ids_b.size();
445 TEUCHOS_ASSERT(local_side_ids_a.size() == local_cell_ids_a.size());
446 TEUCHOS_ASSERT(local_side_ids_a.size() ==
static_cast<std::size_t
>(node_coordinates_a.extent(0)));
447 TEUCHOS_ASSERT(local_side_ids_b.size() == local_cell_ids_b.size());
448 TEUCHOS_ASSERT(local_side_ids_b.size() ==
static_cast<std::size_t
>(node_coordinates_b.extent(0)));
450 std::size_t total_num_cells = total_num_cells_a;
452 std::size_t workset_size = needs_a.cellData.numCells();
456 std::vector<panzer::Workset>& worksets = *worksets_ptr;
459 if(total_num_cells==0) {
462 RCP<std::vector<int> > ir_degrees =
rcp(
new std::vector<int>(0));
463 RCP<std::vector<std::string> > basis_names =
rcp(
new std::vector<std::string>(0));
466 std::vector<panzer::Workset>::iterator i = worksets.begin();
468 i->details(0).block_id = eblock_a;
470 i->details(1).block_id = eblock_b;
473 i->ir_degrees = ir_degrees;
474 i->basis_names = basis_names;
476 for(std::size_t j=0;j<needs_a.int_rules.size();j++) {
478 RCP<panzer::IntegrationValues2<double> > iv2 =
480 iv2->setupArrays(needs_a.int_rules[j]);
482 ir_degrees->push_back(needs_a.int_rules[j]->cubature_degree);
483 i->int_rules.push_back(iv2);
487 for(std::size_t j=0;j<needs_a.int_rules.size();j++) {
489 for(std::size_t b=0;b<needs_a.bases.size();b++) {
493 RCP<panzer::BasisValues2<double> > bv2 =
495 bv2->setupArrays(b_layout);
496 i->bases.push_back(bv2);
498 basis_names->push_back(b_layout->name());
509 std::map<std::pair<unsigned,unsigned>,std::vector<std::size_t> > element_list;
510 for (std::size_t cell=0; cell < local_cell_ids_a.size(); ++cell)
511 element_list[std::make_pair(local_side_ids_a[cell],local_side_ids_b[cell])].push_back(cell);
514 std::size_t num_worksets = 0;
515 for(
const auto& edge : element_list) {
516 std::size_t num_worksets_for_edge = edge.second.size() / workset_size;
517 std::size_t last_workset_size = edge.second.size() % workset_size;
518 if(last_workset_size!=0)
519 num_worksets_for_edge += 1;
521 num_worksets += num_worksets_for_edge;
523 worksets.resize(num_worksets);
526 std::vector<Workset>::iterator current_workset = worksets.begin();
527 for(
const auto& edge : element_list) {
529 const std::vector<std::size_t> & cell_indices = edge.second;
532 needs_a,eblock_a,local_cell_ids_a,local_side_ids_a,node_coordinates_a,
533 needs_b,eblock_b,local_cell_ids_b,local_side_ids_b,node_coordinates_b,
543 template<
typename ArrayT>
544 std::vector<panzer::Workset>::iterator
546 const WorksetNeeds & needs_a,
547 const std::string & eblock_a,
548 const std::vector<std::size_t>& local_cell_ids_a,
549 const std::vector<std::size_t>& local_side_ids_a,
550 const ArrayT& node_coordinates_a,
551 const WorksetNeeds & needs_b,
552 const std::string & eblock_b,
553 const std::vector<std::size_t>& local_cell_ids_b,
554 const std::vector<std::size_t>& local_side_ids_b,
555 const ArrayT& node_coordinates_b,
556 std::vector<Workset>::iterator beg)
560 std::vector<Workset>::iterator wkst = beg;
562 std::size_t current_cell_index = 0;
563 while (current_cell_index<cell_indices.size()) {
564 std::size_t workset_size = needs_a.cellData.numCells();
570 wkst->subcell_dim = needs_a.cellData.baseCellDimension()-1;
572 wkst->details(0).subcell_index = local_side_ids_a[cell_indices[current_cell_index]];
573 wkst->details(0).block_id = eblock_a;
574 wkst->details(0).cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",workset_size,
575 node_coordinates_a.extent(1),
576 node_coordinates_a.extent(2));
578 wkst->details(1).subcell_index = local_side_ids_b[cell_indices[current_cell_index]];
579 wkst->details(1).block_id = eblock_b;
580 wkst->details(1).cell_node_coordinates = mdArrayFactory.buildStaticArray<double,Cell,
NODE,Dim>(
"cnc",workset_size,
581 node_coordinates_a.extent(1),
582 node_coordinates_a.extent(2));
584 std::size_t remaining_cells = cell_indices.size()-current_cell_index;
585 if(remaining_cells<workset_size)
586 workset_size = remaining_cells;
589 wkst->setNumberOfCells(workset_size,0,0);
590 wkst->details(0).cell_local_ids.resize(workset_size);
591 wkst->details(1).cell_local_ids.resize(workset_size);
593 auto dim0_cell_node_coordinates_view = wkst->details(0).cell_node_coordinates.get_static_view();
594 auto dim0_cell_node_coordinates_h = Kokkos::create_mirror_view(dim0_cell_node_coordinates_view);
595 Kokkos::deep_copy(dim0_cell_node_coordinates_h, dim0_cell_node_coordinates_view);
597 auto dim1_cell_node_coordinates_view = wkst->details(1).cell_node_coordinates.get_static_view();
598 auto dim1_cell_node_coordinates_h = Kokkos::create_mirror_view(dim1_cell_node_coordinates_view);
599 Kokkos::deep_copy(dim1_cell_node_coordinates_h, dim1_cell_node_coordinates_view);
601 auto node_coordinates_a_h = Kokkos::create_mirror_view(node_coordinates_a);
602 Kokkos::deep_copy(node_coordinates_a_h, node_coordinates_a);
604 auto node_coordinates_b_h = Kokkos::create_mirror_view(node_coordinates_b);
605 Kokkos::deep_copy(node_coordinates_b_h, node_coordinates_b);
607 for(std::size_t cell=0;cell<workset_size; cell++,current_cell_index++) {
609 wkst->details(0).cell_local_ids[cell] = local_cell_ids_a[cell_indices[current_cell_index]];
610 wkst->details(1).cell_local_ids[cell] = local_cell_ids_b[cell_indices[current_cell_index]];
612 for (std::size_t node = 0; node < Teuchos::as<std::size_t>(node_coordinates_a.extent(1)); ++ node) {
613 for (std::size_t dim = 0; dim < Teuchos::as<std::size_t>(node_coordinates_a.extent(2)); ++ dim) {
614 dim0_cell_node_coordinates_h(cell,node,dim) = node_coordinates_a_h(cell_indices[current_cell_index],node,dim);
615 dim1_cell_node_coordinates_h(cell,node,dim) = node_coordinates_b_h(cell_indices[current_cell_index],node,dim);
620 Kokkos::deep_copy(dim0_cell_node_coordinates_view, dim0_cell_node_coordinates_h);
621 Kokkos::deep_copy(dim1_cell_node_coordinates_view, dim1_cell_node_coordinates_h);
623 auto cell_local_ids_k_0 = PHX::View<int*>(
"Workset:cell_local_ids",wkst->details(0).cell_local_ids.size());
624 auto cell_local_ids_k_0_h = Kokkos::create_mirror_view(cell_local_ids_k_0);
626 auto cell_local_ids_k_1 = PHX::View<int*>(
"Workset:cell_local_ids",wkst->details(1).cell_local_ids.size());
627 auto cell_local_ids_k_1_h = Kokkos::create_mirror_view(cell_local_ids_k_1);
629 for(std::size_t i=0;i<wkst->details(0).cell_local_ids.size();i++)
630 cell_local_ids_k_0_h(i) = wkst->details(0).cell_local_ids[i];
631 for(std::size_t i=0;i<wkst->details(1).cell_local_ids.size();i++)
632 cell_local_ids_k_1_h(i) = wkst->details(1).cell_local_ids[i];
634 Kokkos::deep_copy(cell_local_ids_k_0, cell_local_ids_k_0_h);
635 Kokkos::deep_copy(cell_local_ids_k_1, cell_local_ids_k_1_h);
637 wkst->details(0).cell_local_ids_k = cell_local_ids_k_0;
638 wkst->details(1).cell_local_ids_k = cell_local_ids_k_1;
641 std::size_t max_workset_size = needs_a.cellData.numCells();
643 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)