Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_WorksetContainer.cpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Panzer: A partial differential equation assembly
4// engine for strongly coupled complex multiphysics systems
5//
6// Copyright 2011 NTESS and the Panzer contributors.
7// SPDX-License-Identifier: BSD-3-Clause
8// *****************************************************************************
9// @HEADER
10
12
14
18#include "Panzer_Dimension.hpp"
19
20namespace panzer {
21
24 : worksetSize_(1)
25{}
26WorksetContainer::WorksetContainer(const Teuchos::RCP<const WorksetFactoryBase> & factory,
27 const std::map<std::string,WorksetNeeds> & needs)
28 : wkstFactory_(factory), worksetSize_(0)
29{
30 // thats all!
31 ebToNeeds_ = needs;
32}
33
38 : wkstFactory_(wc.wkstFactory_)
39 , worksetSize_(wc.worksetSize_)
40{
41}
42
47{
48 this->clearVolumeWorksets();
49 this->clearSideWorksets();
50}
51
56
61
63setNeeds(const std::string & eBlock,const WorksetNeeds & needs)
64{
65 clear(); // clear out old worksets
66 ebToNeeds_[eBlock] = needs;
67}
68
70const WorksetNeeds & WorksetContainer::lookupNeeds(const std::string & eBlock) const
71{
72 std::map<std::string,WorksetNeeds>::const_iterator itr = ebToNeeds_.find(eBlock);
73
74 TEUCHOS_TEST_FOR_EXCEPTION(itr==ebToNeeds_.end(),std::logic_error,
75 "WorksetContainer::lookupNeeds no WorksetNeeds object is associated "
76 "with the element block \""+eBlock+"\".");
77
78 return itr->second;
79}
80
81Teuchos::RCP<std::vector<Workset> >
83{
84 PANZER_FUNC_TIME_MONITOR_DIFF("panzer::WorksetContainer::getWorksets()",pwkst_con_get_worksets);
85
86 Teuchos::RCP<std::vector<Workset> > worksetVector;
87 WorksetMap::iterator itr = worksets_.find(wd);
88 if(itr==worksets_.end()) {
89 // couldn't find workset, build it!
90 WorksetNeeds needs;
91 if(hasNeeds())
92 needs = lookupNeeds(wd.getElementBlock());
93 worksetVector = wkstFactory_->getWorksets(wd,needs);
94
95 // apply orientations to the just constructed worksets
96 if(worksetVector!=Teuchos::null && wd.applyOrientations()) {
97 applyOrientations(wd.getElementBlock(),*worksetVector);
98 }
99
100 if(worksetVector!=Teuchos::null)
101 setIdentifiers(wd,*worksetVector);
102
103 // store vector for reuse in the future
104 worksets_[wd] = worksetVector;
105 }
106 else
107 worksetVector = itr->second;
108
109 return worksetVector;
110}
111
113Teuchos::RCP<std::map<unsigned,Workset> >
115{
116 PANZER_FUNC_TIME_MONITOR_DIFF("panzer::WorksetContainer::getSideWorksets()",pwkst_con_get_side_worksets);
117
118 Teuchos::RCP<std::map<unsigned,Workset> > worksetMap;
119
120 // this is the key for the workset map
121 SideMap::iterator itr = sideWorksets_.find(desc);
122
123 if(itr==sideWorksets_.end()) {
124 // couldn't find workset, build it!
125 if (desc.connectsElementBlocks()) {
126 worksetMap = wkstFactory_->getSideWorksets(desc, lookupNeeds(desc.getElementBlock(0)),
128 }
129 else {
130 worksetMap = wkstFactory_->getSideWorksets(desc,lookupNeeds(desc.getElementBlock(0)));
131 }
132
133 // apply orientations to the worksets for this side
134 if(worksetMap!=Teuchos::null)
135 applyOrientations(desc,*worksetMap);
136
137 if(worksetMap!=Teuchos::null)
138 setIdentifiers(desc,*worksetMap);
139
140 // store map for reuse in the future
141 sideWorksets_[desc] = worksetMap;
142 }
143 else {
144 worksetMap = itr->second;
145 }
146
147 return worksetMap;
148}
149
150
152setGlobalIndexer(const Teuchos::RCP<const panzer::GlobalIndexer> & ugi)
153{
154 // apply the orientations for stored worksets
156}
157
159addBasis(const std::string & type,int order,const std::string & rep_field)
160{
161 using Teuchos::RCP;
162 using Teuchos::rcp;
163
164 for(auto itr=ebToNeeds_.begin();itr!=ebToNeeds_.end();++itr) {
165 WorksetNeeds & needs = itr->second;
166 RCP<PureBasis> basis = rcp(new PureBasis(type,order,needs.cellData));
167
168 // add in the new basis
169 needs.bases.push_back(basis);
170 needs.rep_field_name.push_back(rep_field);
171 }
172
173 // clear all arrays, lazy evaluation means it will be rebuilt
174 clear();
175}
176
178applyOrientations(const Teuchos::RCP<const panzer::GlobalIndexer> & ugi)
179{
180 PANZER_FUNC_TIME_MONITOR_DIFF("panzer::WorksetContainer::applyOrientations(ugi)",pwkst_con_apply_orts);
181
182 // this gurantees orientations won't accidently be applied twice.
183 TEUCHOS_ASSERT(globalIndexer_==Teuchos::null);
184
185 globalIndexer_ = ugi;
186
187 // this should be created once and stored in an appropriate place
188 TEUCHOS_TEST_FOR_EXCEPTION(globalIndexer_ == Teuchos::null, std::logic_error,
189 "global indexer is not set yet");
191
192 // loop over volume worksets, apply orientations to each
193 for(WorksetMap::iterator itr=worksets_.begin();
194 itr!=worksets_.end();++itr) {
195 std::string eBlock = itr->first.getElementBlock();
196
197 applyOrientations(eBlock,*itr->second);
198 }
199
200 // loop over side worksets, apply orientations to each
201 for(SideMap::iterator itr=sideWorksets_.begin();
202 itr!=sideWorksets_.end();itr++) {
203
204 applyOrientations(itr->first,*itr->second);
205 }
206}
207
209setIdentifiers(const WorksetDescriptor & wd,std::vector<Workset> & worksets)
210{
211 std::size_t hash = std::hash<WorksetDescriptor>()(wd); // this is really ugly, is this really a C++ standard?
212 for(std::size_t i=0;i<worksets.size();i++)
213 worksets[i].setIdentifier(hash+i);
214}
215
217setIdentifiers(const WorksetDescriptor & wd,std::map<unsigned,Workset> & workset_map)
218{
219 std::size_t hash = std::hash<WorksetDescriptor>()(wd); // this is really ugly, is this really a C++ standard?
220 std::size_t offset = 0;
221 for(auto itr : workset_map) {
222 // itr.second.setIdentifier(hash+offset);
223 workset_map[itr.first].setIdentifier(hash+offset);
224
225 offset++;
226 }
227}
228
230applyOrientations(const std::string & eBlock, std::vector<Workset> & worksets) const
231{
232 using Teuchos::RCP;
233
234 PANZER_FUNC_TIME_MONITOR_DIFF("panzer::WorksetContainer::applyOrientations(eBlock,worksets)",pwkst_con_apply_orts_eb_w);
235
237 // this is for volume worksets //
239
240 // short circuit if no global indexer exists
241 if((globalIndexer_==Teuchos::null) and (wkstFactory_->getOrientationsInterface() == Teuchos::null)) {
242 Teuchos::FancyOStream fout(Teuchos::rcpFromRef(std::cout));
243 fout.setOutputToRootOnly(0);
244
245 fout << "Panzer Warning: No global indexer assigned to a workset container or factory. "
246 << "Orientation of the basis for edge basis functions cannot be applied, "
247 << "if those basis functions are used, there will be problems!" << std::endl;
248 return;
249 }
250
251 // this should be matched to global indexer size (not sure how to retrive it)
252 if(globalIndexer_!=Teuchos::null){
253 TEUCHOS_TEST_FOR_EXCEPTION(orientations_ == Teuchos::null, std::logic_error,
254 "intrepid2 orientation is not constructed");
255 }
256
257 // loop over each basis requiring orientations, then apply them
259
260 // Note: It may be faster to loop over the basis pairs on the inside (not really sure)
261
262 WorksetNeeds needs;
263 if(hasNeeds())
264 needs = lookupNeeds(eBlock);
265
266 if(needs.bases.size()>0) {
267 // sanity check that we aren't missing something (the old and new "needs" should not be used together)
268 TEUCHOS_ASSERT(needs.getBases().size()==0);
269
270 for(std::size_t w=0;w<needs.bases.size();w++) {
271 const PureBasis & basis = *needs.bases[w];
272
273 // no need for this if orientations are not required!
274 if(!basis.requiresOrientations())
275 continue;
276
277 // build accessors for orientation fields
278 std::vector<Intrepid2::Orientation> ortsPerBlock;
279
280 // loop over worksets compute and apply orientations
281 for(std::size_t i=0;i<worksets.size();i++) {
282 // break out of the workset loop
283 if(worksets[i].num_cells<=0) continue;
284
285 for(std::size_t j=0;j<worksets[i].numDetails();j++) {
286 WorksetDetails & details = worksets[i](j);
287
288 ortsPerBlock.clear();
289 for (int k=0;k<worksets[i].num_cells;++k) {
290 ortsPerBlock.push_back((*orientations_)[details.cell_local_ids[k]]);
291 }
292
293 for(std::size_t basis_index=0;basis_index<details.bases.size();basis_index++) {
294 Teuchos::RCP<const BasisIRLayout> layout = details.bases[basis_index]->basis_layout;
295
296 // only apply orientations if its relevant to the current needs
297 if(layout->getBasis()->name()!=basis.name())
298 continue;
299
300 TEUCHOS_ASSERT(layout!=Teuchos::null);
301 TEUCHOS_ASSERT(layout->getBasis()!=Teuchos::null);
302 if(layout->getBasis()->requiresOrientations()) {
303 // apply orientations for this basis
304 auto & bv = *details.bases[basis_index];
305 if(not bv.orientationsApplied())
306 bv.applyOrientations(ortsPerBlock,(int) worksets[i].num_cells);
307 }
308 }
309 }
310 }
311 } // end for w
312 }
313 else if(needs.getBases().size()>0) {
314 // sanity check that we aren't missing something (the old and new "needs" should not be used together)
315 TEUCHOS_ASSERT(needs.bases.size()==0);
316
317 // This is for forwards compatibility, the needs now use "getBasis" calls as opposed
318 // to director accessors.
319 for(const auto & bd : needs.getBases()) {
320
321 // build accessors for orientation fields
322 std::vector<Intrepid2::Orientation> ortsPerBlock;
323
324 // loop over worksets compute and apply orientations
325 for(std::size_t i=0;i<worksets.size();i++) {
326 // break out of the workset loop
327 if(worksets[i].num_cells<=0) continue;
328
329 for(std::size_t j=0;j<worksets[i].numDetails();j++) {
330 WorksetDetails & details = worksets[i](j);
331
332 ortsPerBlock.clear();
333 // for (int k=0;k<worksets[i].num_cells;++k) {
334 for (int k=0;k<details.numOwnedCells();++k) {
335 ortsPerBlock.push_back((*orientations_)[details.cell_local_ids[k]]);
336 }
337
338 for(const auto & id : needs.getIntegrators()) {
339 // apply orientations for this basis
340 auto & bv = details.getBasisValues(bd,id);
341 if(not bv.orientationsApplied())
342 bv.applyOrientations(ortsPerBlock,(int) worksets[i].num_cells);
343 }
344 }
345 }
346 } // end for w
347 }
348}
349
350
352applyOrientations(const WorksetDescriptor & desc,std::map<unsigned,Workset> & worksets) const
353{
354 using Teuchos::RCP;
355
356 PANZER_FUNC_TIME_MONITOR_DIFF("panzer::WorksetContainer::applyOrientations(wd,worksets)",pwkst_con_apply_orts_wd_wksts);
357
359 // this is for side worksets //
361
362 // short circuit if no global indexer exists
363 if((globalIndexer_==Teuchos::null) and (wkstFactory_->getOrientationsInterface() == Teuchos::null)) {
364 Teuchos::FancyOStream fout(Teuchos::rcpFromRef(std::cout));
365 fout.setOutputToRootOnly(0);
366
367 fout << "Panzer Warning: No global indexer assigned to a workset container or factory. "
368 << "Orientation of the basis for edge basis functions cannot be applied, "
369 << "if those basis functions are used, there will be problems!";
370 return;
371 }
372
373 // loop over each basis requiring orientations, then apply them
375
376 // Note: It may be faster to loop over the basis pairs on the inside (not really sure)
377 WorksetNeeds needs;
378 if(hasNeeds())
379 needs = lookupNeeds(desc.getElementBlock());
380
381 if(needs.bases.size()>0) {
382 // sanity check that we aren't missing something (the old and new "needs" should not be used together)
383 TEUCHOS_ASSERT(needs.getBases().size()==0);
384 for(std::size_t i=0;i<needs.bases.size();i++) {
385 const PureBasis & basis = *needs.bases[i];
386
387 // no need for this if orientations are not required!
388 if(!basis.requiresOrientations()) continue;
389
390 // build accessors for orientation fields
391 std::vector<Intrepid2::Orientation> ortsPerBlock;
392
393 // loop over worksets compute and apply orientations
394 for(std::map<unsigned,Workset>::iterator itr=worksets.begin();
395 itr!=worksets.end();++itr) {
396
397 // break out of the workset loop
398 if(itr->second.num_cells<=0) continue;
399
400 for(std::size_t j=0;j<itr->second.numDetails();j++) {
401 WorksetDetails & details = itr->second(j);
402
403 ortsPerBlock.clear();
404 for (int k=0;k<itr->second.num_cells;++k) {
405 ortsPerBlock.push_back((*orientations_)[details.cell_local_ids[k]]);
406 }
407
408 for(std::size_t basis_index=0;basis_index<details.bases.size();basis_index++) {
409 Teuchos::RCP<const BasisIRLayout> layout = details.bases[basis_index]->basis_layout;
410
411 // only apply orientations if its relevant to the current needs
412 if(layout->getBasis()->name()!=basis.name())
413 continue;
414
415 TEUCHOS_ASSERT(layout!=Teuchos::null);
416 TEUCHOS_ASSERT(layout->getBasis()!=Teuchos::null);
417 if(layout->getBasis()->requiresOrientations()) {
418 // apply orientations for this basis
419 auto & bv = *details.bases[basis_index];
420 if(not bv.orientationsApplied())
421 bv.applyOrientations(ortsPerBlock,(int) itr->second.num_cells);
422 }
423 }
424 }
425 }
426 } // end for i
427 }
428 else if(needs.getBases().size()>0) {
429 // sanity check that we aren't missing something (the old and new "needs" should not be used together)
430 TEUCHOS_ASSERT(needs.bases.size()==0);
431
432 // This is for forwards compatibility, the needs now use "getBasis" calls as opposed
433 // to director accessors.
434 for(const auto & bd : needs.getBases()) {
435
436 // build accessors for orientation fields
437 std::vector<Intrepid2::Orientation> ortsPerBlock;
438
439 // loop over worksets compute and apply orientations
440 for(std::map<unsigned,Workset>::iterator itr=worksets.begin();
441 itr!=worksets.end();++itr) {
442
443 // break out of the workset loop
444 if(itr->second.num_cells<=0) continue;
445
446 for(std::size_t j=0;j<itr->second.numDetails();j++) {
447 WorksetDetails & details = itr->second(j);
448
449 ortsPerBlock.clear();
450 for (int k=0;k<itr->second.num_cells;++k) {
451 ortsPerBlock.push_back((*orientations_)[details.cell_local_ids[k]]);
452 }
453
454 for(const auto & id : needs.getIntegrators()) {
455 // apply orientations for this basis
456 auto & bv = details.getBasisValues(bd,id);
457 if(not bv.orientationsApplied())
458 bv.applyOrientations(ortsPerBlock,(int) itr->second.num_cells);
459 }
460 }
461 }
462 } // end for w
463 }
464}
465
467 const std::vector<std::string> & elementBlockNames,
468 std::map<std::string,Teuchos::RCP<std::vector<Workset> > > & volumeWksts)
469{
470 for(std::size_t i=0;i<elementBlockNames.size();i++) {
471 WorksetDescriptor wd = blockDescriptor(elementBlockNames[i]);
472 volumeWksts[elementBlockNames[i]] = wc.getWorksets(wd);
473 }
474}
475
477 const std::vector<BC> & bcs,
478 std::map<BC,Teuchos::RCP<std::map<unsigned,Workset> >,LessBC> & sideWksts)
479{
480 for(std::size_t i=0;i<bcs.size();i++) {
481 WorksetDescriptor wd(bcs[i].elementBlockID(),bcs[i].sidesetID());
482 Teuchos::RCP<std::map<unsigned,Workset> > wksts = wc.getSideWorksets(wd);
483 if(wksts!=Teuchos::null)
484 sideWksts[bcs[i]] = wksts;
485 }
486}
487
488}
Stores input information for a boundary condition.
Definition Panzer_BC.hpp:48
Description and data layouts associated with a particular basis.
bool requiresOrientations() const
std::string name() const
A unique key that is the combination of the basis type and basis order.
Class that provides access to worksets on each element block and side set.
Teuchos::RCP< std::vector< Workset > > getWorksets(const WorksetDescriptor &wd)
Access to volume worksets.
const WorksetNeeds & lookupNeeds(const std::string &eBlock) const
Look up an input physics block, throws an exception if it can not be found.
void setIdentifiers(const WorksetDescriptor &wd, std::vector< Workset > &worksets)
void applyOrientations(const Teuchos::RCP< const panzer::GlobalIndexer > &ugi)
void addBasis(const std::string &type, int order, const std::string &rep_field)
WorksetMap worksets_
Maps element blocks to input physics block objects.
void setGlobalIndexer(const Teuchos::RCP< const panzer::GlobalIndexer > &ugi)
void setNeeds(const std::string &eBlock, const WorksetNeeds &needs)
Teuchos::RCP< std::vector< Intrepid2::Orientation > > orientations_
Teuchos::RCP< std::map< unsigned, Workset > > getSideWorksets(const WorksetDescriptor &desc)
Access, and construction of side worksets.
WorksetContainer()
Default contructor, starts with no workset factory objects.
Teuchos::RCP< const WorksetFactoryBase > wkstFactory_
Teuchos::RCP< const panzer::GlobalIndexer > globalIndexer_
std::map< std::string, WorksetNeeds > ebToNeeds_
How to construct worksets.
const std::string & getElementBlock(const int block=0) const
Get element block name.
bool connectsElementBlocks() const
Identifies this workset as an interface between two element blocks.
WorksetDescriptor blockDescriptor(const std::string &eBlock)
void getVolumeWorksetsFromContainer(WorksetContainer &wc, const std::vector< std::string > &elementBlockNames, std::map< std::string, Teuchos::RCP< std::vector< Workset > > > &volumeWksts)
void buildIntrepidOrientation(std::vector< Intrepid2::Orientation > &orientation, panzer::ConnManager &connMgr)
Builds the element orientations for all element blocks.
void getSideWorksetsFromContainer(WorksetContainer &wc, const std::vector< BC > &bcs, std::map< BC, Teuchos::RCP< std::map< unsigned, Workset > >, LessBC > &sideWksts)
std::vector< std::string > rep_field_name
const std::vector< panzer::IntegrationDescriptor > & getIntegrators() const
Get a list of integrators being requested.
const std::vector< panzer::BasisDescriptor > & getBases() const
Get a list of bases being requested.
std::vector< Teuchos::RCP< const PureBasis > > bases