Teuchos::RCP< std::vector<panzer::Workset> > panzer::buildWorksets(const panzer::PhysicsBlock& pb, const std::vector<std::size_t>& local_cell_ids, const ArrayT& vertex_coordinates) { using std::vector; using std::string; using Teuchos::RCP; using Teuchos::rcp; panzer::IntrepidFieldContainerFactory arrayFactory; std::size_t total_num_cells = local_cell_ids.size(); std::size_t workset_size = pb.cellData().numCells(); Teuchos::RCP< std::vector<panzer::Workset> > worksets_ptr = Teuchos::rcp(new std::vector<panzer::Workset>); std::vector<panzer::Workset>& worksets = *worksets_ptr; // special case for 0 elements! if(total_num_cells==0) { // Setup integration rules and basis RCP<vector<int> > ir_degrees = rcp(new vector<int>(0)); RCP<vector<string> > basis_names = rcp(new vector<string>(0)); worksets.resize(1); std::vector<panzer::Workset>::iterator i = worksets.begin(); i->num_cells = 0; i->block_id = pb.elementBlockID(); i->ir_degrees = ir_degrees; i->basis_names = basis_names; const std::map<int,RCP<panzer::IntegrationRule> >& int_rules = pb.getIntegrationRules(); for (std::map<int,RCP<panzer::IntegrationRule> >::const_iterator ir_itr = int_rules.begin(); ir_itr != int_rules.end(); ++ir_itr) { RCP<panzer::IntegrationValues<double,Intrepid::FieldContainer<double> > > iv = rcp(new panzer::IntegrationValues<double,Intrepid::FieldContainer<double> >); iv->setupArrays(ir_itr->second); ir_degrees->push_back(ir_itr->first); i->int_rules.push_back(iv); } const std::map<std::string,Teuchos::RCP<panzer::PureBasis> >& bases= pb.getBases(); // Need to create all combinations of basis/ir pairings for (std::map<int,RCP<panzer::IntegrationRule> >::const_iterator ir_itr = int_rules.begin(); ir_itr != int_rules.end(); ++ir_itr) { for (std::map<std::string,Teuchos::RCP<panzer::PureBasis> >::const_iterator b_itr = bases.begin(); b_itr != bases.end(); ++b_itr) { RCP<panzer::BasisIRLayout> b_layout = rcp(new panzer::BasisIRLayout(b_itr->second,*ir_itr->second)); RCP<panzer::BasisValues<double,Intrepid::FieldContainer<double> > > bv = rcp(new panzer::BasisValues<double,Intrepid::FieldContainer<double> >); bv->setupArrays(b_layout,arrayFactory); basis_names->push_back(b_layout->name()); i->bases.push_back(bv); } } i->details.push_back(Teuchos::rcpFromRef(*i)); return worksets_ptr; } // end special case { std::size_t num_worksets = total_num_cells / workset_size; bool last_set_is_full = true; std::size_t last_workset_size = total_num_cells % workset_size; if (last_workset_size != 0) { num_worksets += 1; last_set_is_full = false; } worksets.resize(num_worksets); std::vector<panzer::Workset>::iterator i; for (i = worksets.begin(); i != worksets.end(); ++i) i->num_cells = workset_size; if (!last_set_is_full) { worksets.back().num_cells = last_workset_size; } } // assign workset cell local ids std::vector<std::size_t>::const_iterator local_begin = local_cell_ids.begin(); for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) { std::vector<std::size_t>::const_iterator begin_iter = local_begin; std::vector<std::size_t>::const_iterator end_iter = begin_iter + wkst->num_cells; local_begin = end_iter; wkst->cell_local_ids.assign(begin_iter,end_iter); wkst->cell_vertex_coordinates.resize(workset_size, vertex_coordinates.dimension(1), vertex_coordinates.dimension(2)); wkst->block_id = pb.elementBlockID(); wkst->subcell_dim = pb.cellData().baseCellDimension(); wkst->subcell_index = 0; wkst->details.push_back(Teuchos::rcpFromRef(*wkst)); } TEUCHOS_ASSERT(local_begin == local_cell_ids.end()); // Copy cell vertex coordinates into local workset arrays std::size_t offset = 0; for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) { for (std::size_t cell = 0; cell < wkst->num_cells; ++cell) for (std::size_t vertex = 0; vertex < Teuchos::as<std::size_t>(vertex_coordinates.dimension(1)); ++ vertex) for (std::size_t dim = 0; dim < Teuchos::as<std::size_t>(vertex_coordinates.dimension(2)); ++ dim) wkst->cell_vertex_coordinates(cell,vertex,dim) = vertex_coordinates(cell + offset,vertex,dim); offset += wkst->num_cells; } TEUCHOS_ASSERT(offset == Teuchos::as<std::size_t>(vertex_coordinates.dimension(0))); // Set ir and basis arrayskset RCP<vector<int> > ir_degrees = rcp(new vector<int>(0)); RCP<vector<string> > basis_names = rcp(new vector<string>(0)); for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) { wkst->ir_degrees = ir_degrees; wkst->basis_names = basis_names; } const std::map<int,RCP<panzer::IntegrationRule> >& int_rules = pb.getIntegrationRules(); for (std::map<int,RCP<panzer::IntegrationRule> >::const_iterator ir_itr = int_rules.begin(); ir_itr != int_rules.end(); ++ir_itr) { ir_degrees->push_back(ir_itr->first); for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) { RCP<panzer::IntegrationValues<double,Intrepid::FieldContainer<double> > > iv = rcp(new panzer::IntegrationValues<double,Intrepid::FieldContainer<double> >); iv->setupArrays(ir_itr->second); iv->evaluateValues(wkst->cell_vertex_coordinates); wkst->int_rules.push_back(iv); } } const std::map<std::string,Teuchos::RCP<panzer::PureBasis> >& bases= pb.getBases(); // Need to create all combinations of basis/ir pairings // Loop over ir for (std::map<int,RCP<panzer::IntegrationRule> >::const_iterator ir_itr = int_rules.begin(); ir_itr != int_rules.end(); ++ir_itr) { // Loop over basis for (std::map<std::string,Teuchos::RCP<panzer::PureBasis> >::const_iterator b_itr = bases.begin(); b_itr != bases.end(); ++b_itr) { RCP<panzer::BasisIRLayout> b_layout = rcp(new panzer::BasisIRLayout(b_itr->second,*ir_itr->second)); basis_names->push_back(b_layout->name()); // Loop over worksets for (std::vector<panzer::Workset>::iterator wkst = worksets.begin(); wkst != worksets.end(); ++wkst) { RCP<panzer::BasisValues<double,Intrepid::FieldContainer<double> > > bv = rcp(new panzer::BasisValues<double,Intrepid::FieldContainer<double> >); bv->setupArrays(b_layout,arrayFactory); std::size_t int_degree_index = std::distance(ir_degrees->begin(), std::find(ir_degrees->begin(), ir_degrees->end(), ir_itr->second->order())); bv->evaluateValues(wkst->int_rules[int_degree_index]->cub_points, wkst->int_rules[int_degree_index]->jac, wkst->int_rules[int_degree_index]->jac_det, wkst->int_rules[int_degree_index]->jac_inv, wkst->int_rules[int_degree_index]->weighted_measure, wkst->cell_vertex_coordinates); wkst->bases.push_back(bv); } } } return worksets_ptr; }
Teuchos::RCP< std::vector<panzer::Workset> > panzer::buildEdgeWorksets(const panzer::PhysicsBlock & pb_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::PhysicsBlock & pb_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) { using std::vector; using std::string; using Teuchos::RCP; using Teuchos::rcp; panzer::IntrepidFieldContainerFactory arrayFactory; std::size_t total_num_cells_a = local_cell_ids_a.size(); std::size_t total_num_cells_b = local_cell_ids_b.size(); TEUCHOS_ASSERT(total_num_cells_a==total_num_cells_b); TEUCHOS_ASSERT(local_side_ids_a.size() == local_cell_ids_a.size()); TEUCHOS_ASSERT(local_side_ids_a.size() == static_cast<std::size_t>(vertex_coordinates_a.dimension(0))); TEUCHOS_ASSERT(local_side_ids_b.size() == local_cell_ids_b.size()); TEUCHOS_ASSERT(local_side_ids_b.size() == static_cast<std::size_t>(vertex_coordinates_b.dimension(0))); std::size_t total_num_cells = total_num_cells_a; std::size_t workset_size = pb_a.cellData().numCells(); Teuchos::RCP< std::vector<panzer::Workset> > worksets_ptr = Teuchos::rcp(new std::vector<panzer::Workset>); std::vector<panzer::Workset>& worksets = *worksets_ptr; // special case for 0 elements! if(total_num_cells==0) { // Setup integration rules and basis RCP<vector<int> > ir_degrees = rcp(new vector<int>(0)); RCP<vector<string> > basis_names = rcp(new vector<string>(0)); worksets.resize(1); std::vector<panzer::Workset>::iterator i = worksets.begin(); i->details.resize(2); i->details[0] = Teuchos::rcpFromRef(*i); i->details[0]->block_id = pb_a.elementBlockID(); i->details[1] = Teuchos::rcp(new panzer::WorksetDetails); i->details[1]->block_id = pb_b.elementBlockID(); i->num_cells = 0; i->ir_degrees = ir_degrees; i->basis_names = basis_names; const std::map<int,RCP<panzer::IntegrationRule> >& int_rules = pb_a.getIntegrationRules(); for (std::map<int,RCP<panzer::IntegrationRule> >::const_iterator ir_itr = int_rules.begin(); ir_itr != int_rules.end(); ++ir_itr) { RCP<panzer::IntegrationValues<double,Intrepid::FieldContainer<double> > > iv = rcp(new panzer::IntegrationValues<double,Intrepid::FieldContainer<double> >); iv->setupArrays(ir_itr->second); ir_degrees->push_back(ir_itr->first); i->int_rules.push_back(iv); } const std::map<std::string,Teuchos::RCP<panzer::PureBasis> >& bases = pb_a.getBases(); // Need to create all combinations of basis/ir pairings for (std::map<int,RCP<panzer::IntegrationRule> >::const_iterator ir_itr = int_rules.begin(); ir_itr != int_rules.end(); ++ir_itr) { for (std::map<std::string,Teuchos::RCP<panzer::PureBasis> >::const_iterator b_itr = bases.begin(); b_itr != bases.end(); ++b_itr) { RCP<panzer::BasisIRLayout> b_layout = rcp(new panzer::BasisIRLayout(b_itr->second,*ir_itr->second)); RCP<panzer::BasisValues<double,Intrepid::FieldContainer<double> > > bv = rcp(new panzer::BasisValues<double,Intrepid::FieldContainer<double> >); bv->setupArrays(b_layout,arrayFactory); basis_names->push_back(b_layout->name()); i->bases.push_back(bv); } } return worksets_ptr; } // end special case // This collects all the elements that share the same sub cell pairs, this makes it easier to // build the required worksets // key is the pair of local face indices, value is a vector of cell indices that satisfy this pair std::map<std::pair<unsigned,unsigned>,std::vector<std::size_t> > element_list; for (std::size_t cell=0; cell < local_cell_ids_a.size(); ++cell) element_list[std::make_pair<unsigned,unsigned>(local_side_ids_a[cell],local_side_ids_b[cell])].push_back(cell); // this is the lone iterator that will be used to loop over the element edge list std::map<std::pair<unsigned,unsigned>,std::vector<std::size_t> >::const_iterator edge; // figure out how many worksets will be needed, resize workset vector accordingly std::size_t num_worksets = 0; for(edge=element_list.begin(); edge!=element_list.end();++edge) { std::size_t num_worksets_for_edge = edge->second.size() / workset_size; std::size_t last_workset_size = edge->second.size() % workset_size; if(last_workset_size!=0) num_worksets_for_edge += 1; num_worksets += num_worksets_for_edge; } worksets.resize(num_worksets); // fill the worksets std::vector<Workset>::iterator current_workset = worksets.begin(); for(edge=element_list.begin(); edge!=element_list.end();++edge) { // loop over each workset const std::vector<std::size_t> & cell_indices = edge->second; current_workset = buildEdgeWorksets(cell_indices, pb_a,local_cell_ids_a,local_side_ids_a,vertex_coordinates_a, pb_b,local_cell_ids_b,local_side_ids_b,vertex_coordinates_b, current_workset); } // sanity check TEUCHOS_ASSERT(current_workset==worksets.end()); return worksets_ptr; }