Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_DOFManagerFEI_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef PANZER_DOF_MANAGER_FEI_IMPL_HPP
44 #define PANZER_DOF_MANAGER_FEI_IMPL_HPP
45 
46 #include "PanzerDofMgr_config.hpp"
47 
48 #ifdef PANZER_HAVE_FEI
49 
50 // FEI includes
51 #include "fei_Factory_Trilinos.hpp"
52 
53 #include <map>
54 
58 
60 
61 using Teuchos::RCP;
62 
63 namespace panzer {
64 
65 // ************************************************************
66 // class DOFManagerFEI
67 // ************************************************************
68 
69 template <typename LocalOrdinalT,typename GlobalOrdinalT>
70 DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::DOFManagerFEI()
71  : numFields_(0), fieldsRegistered_(false), requireOrientations_(false)
72 { }
73 
74 template <typename LocalOrdinalT,typename GlobalOrdinalT>
75 DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::DOFManagerFEI(const Teuchos::RCP<ConnManager<LocalOrdinalT,GlobalOrdinalT> > & connMngr,MPI_Comm mpiComm)
76  : numFields_(0), fieldsRegistered_(false), requireOrientations_(false)
77 {
78  setConnManager(connMngr,mpiComm);
79 }
80 
92 template <typename LocalOrdinalT,typename GlobalOrdinalT>
93 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::setConnManager(const Teuchos::RCP<ConnManager<LocalOrdinalT,GlobalOrdinalT> > & connMngr,MPI_Comm mpiComm)
94 {
95  // make sure you own an MPI comm
96  communicator_ = Teuchos::rcp(new Teuchos::MpiComm<int>(Teuchos::opaqueWrapper(mpiComm)));
97 
98  // this kills any old connection manager as well as the old FEI objects
99  resetIndices();
100 
101  connMngr_ = connMngr;
102 
103  // build fei components
104  feiFactory_ = Teuchos::rcp(new Factory_Trilinos(*communicator_->getRawMpiComm()));
105 
106  // build fei components
107  vectorSpace_ = feiFactory_->createVectorSpace(*communicator_->getRawMpiComm(),"problem_vs");
108  matrixGraph_ = feiFactory_->createMatrixGraph(vectorSpace_,vectorSpace_,"problem_mg");
109 
110  nodeType_ = 0;
111  vectorSpace_->defineIDTypes(1,&nodeType_);
112  edgeType_ = 1;
113  vectorSpace_->defineIDTypes(1,&edgeType_);
114 }
115 
124 template <typename LocalOrdinalT,typename GlobalOrdinalT>
125 Teuchos::RCP<ConnManager<LocalOrdinalT,GlobalOrdinalT> > DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::resetIndices()
126 {
128 
129  connMngr_ = Teuchos::null;
130 
131  // wipe out FEI objects
132  patternNum_.clear();
133  feiFactory_ = Teuchos::null;
134  vectorSpace_.reset();
135  matrixGraph_.reset();
136 
137  ownedGIDHashTable_.clear();
138 
139  return connMngr;
140 }
141 
142 template <typename LocalOrdinalT,typename GlobalOrdinalT>
143 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::addField(const std::string & str,
144  const Teuchos::RCP<const FieldPattern> & pattern)
145 {
146  std::vector<std::string> elementBlockIds;
147  connMngr_->getElementBlockIds(elementBlockIds);
148 
149  // loop over blocks adding field pattern to each
150  for(std::size_t i=0;i<elementBlockIds.size();i++)
151  addField(elementBlockIds[i],str,pattern);
152 }
153 
154 template <typename LocalOrdinalT,typename GlobalOrdinalT>
155 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::addField(const std::string & blockId,const std::string & str,
156  const Teuchos::RCP<const FieldPattern> & pattern)
157 {
158  TEUCHOS_TEST_FOR_EXCEPTION(fieldsRegistered_,std::logic_error,
159  "DOFManagerFEI::addField: addField cannot be called after registerFields or"
160  "buildGlobalUnknowns has been called");
161 
162  fieldStringToPattern_[std::make_pair(blockId,str)] = pattern;
163 }
164 
165 template <typename LocalOrdinalT,typename GlobalOrdinalT>
166 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::registerFields()
167 {
168  numFields_ = 0;
169 
170  // test validity of the field order
171  {
172  // build a unique set of fields, so we can compare validate the ordered list
173  std::set<std::string> fields;
174  for(std::map<std::pair<std::string,std::string>,Teuchos::RCP<const FieldPattern> >::const_iterator
175  fieldItr=fieldStringToPattern_.begin(); fieldItr!=fieldStringToPattern_.end();++fieldItr) {
176  std::string fieldName = fieldItr->first.second;
177  fields.insert(fieldName);
178  }
179 
180  // construct default field order if neccessary
181  if(fieldOrder_.size()==0) {
182  std::set<std::string>::const_iterator itr;
183  for(itr=fields.begin();itr!=fields.end();itr++)
184  fieldOrder_.push_back(*itr);
185  }
186 
187  // check validity of field order: no repeats, and everything is accounted for
188  bool validOrder = validFieldOrder(fieldOrder_,fields);
189  if(!validOrder) {
190  // for outputing
191  std::stringstream ss;
192 
193  ss << "DOFManagerFEI::registerFields - Field order is invalid!\n";
194 
195  ss << " fields = [ ";
196  for(std::set<std::string>::const_iterator itr=fields.begin();
197  itr!=fields.end();++itr)
198  ss << "\"" << *itr << "\" ";
199  ss << " ]\n";
200 
201  ss << " fieldOrder = [ ";
202  for(std::vector<std::string>::const_iterator itr=fieldOrder_.begin();
203  itr!=fieldOrder_.end();++itr)
204  ss << "\"" << *itr << "\" ";
205  ss << " ]\n";
206 
207  TEUCHOS_TEST_FOR_EXCEPTION(!validOrder,std::logic_error,ss.str());
208  }
209  }
210 
211  // build field IDs
212  for(std::size_t fo_index=0;fo_index<fieldOrder_.size();fo_index++) {
213  std::string fieldName = fieldOrder_[fo_index];
214 
215  // field doesn't exist...add it
216  int fieldNum = fo_index;
217  int size = 1; // fields are always size 1
218  vectorSpace_->defineFields(1,&fieldNum,&size);
219 
220  fieldStrToInt_[fieldName] = fieldNum;
221  intToFieldStr_[fieldNum] = fieldName;
222  }
223  numFields_ = fieldOrder_.size();
224 
225  // initialize blockToField_ vector to have at least empty sets
226  // for each element block
227  std::vector<std::string> elementBlockIds;
228  getElementBlockIds(elementBlockIds);
229  for(std::size_t ebi=0;ebi<elementBlockIds.size();ebi++)
230  blockToField_.insert(std::make_pair(elementBlockIds[ebi],std::set<int>()));
231 
232  // associate blocks with particular field ids
233  for(std::map<std::pair<std::string,std::string>,Teuchos::RCP<const FieldPattern> >::const_iterator
234  fieldItr=fieldStringToPattern_.begin(); fieldItr!=fieldStringToPattern_.end();++fieldItr) {
235 
236  std::string blockId = fieldItr->first.first;
237  std::string fieldName = fieldItr->first.second;
238 
239  std::map<std::string,int>::const_iterator itr = fieldStrToInt_.find(fieldName);
240  if(itr!=fieldStrToInt_.end()) {
241  // field already exists!
242  blockToField_[blockId].insert(itr->second);
243  fieldIntToPattern_[std::make_pair(blockId,itr->second)] = fieldItr->second;
244  }
245  else {
246  // this statement should _never_ be executed. The reason is that
247  // the fieldIntToPattern_ was filled before this function was run
248  // directly from the fieldStringToPattern_ map. Possibly check the
249  // order validator for letting something slip through!
250 
251  TEUCHOS_TEST_FOR_EXCEPTION(false,std::logic_error,
252  "DOFManagerFEI::registerFields - Impossible case discoverved!");
253  }
254  }
255 
256  fieldsRegistered_ = true;
257 }
258 
259 template <typename LocalOrdinalT,typename GlobalOrdinalT>
260 int DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getFieldNum(const std::string & str) const
261 {
262  std::map<std::string,int>::const_iterator itr = fieldStrToInt_.find(str);
263 
264  // return based on what was found
265  if(itr==fieldStrToInt_.end()) {
266  // incorrect field name
267  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
268  "DOFManagerFEI::getFieldNum No field with the name \"" + str + "\" has been added");
269  }
270  else {
271  return itr->second;
272  }
273 }
274 
275 template <typename LocalOrdinalT,typename GlobalOrdinalT>
276 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::setFieldOrder(const std::vector<std::string> & fieldOrder)
277 {
278  fieldOrder_ = fieldOrder;
279 }
280 
283 template <typename LocalOrdinalT,typename GlobalOrdinalT>
284 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getFieldOrder(std::vector<std::string> & fieldOrder) const
285 {
286  fieldOrder = fieldOrder_;
287 }
288 
289 template <typename LocalOrdinalT,typename GlobalOrdinalT>
290 int DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getNumFields() const
291 {
292  return vectorSpace_->getNumFields();
293 }
294 
295 // build the global unknown numberings
296 // 1. this builds the pattens
297 // 2. initializes the connectivity
298 // 3. calls initComplete
299 template <typename LocalOrdinalT,typename GlobalOrdinalT>
300 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::buildGlobalUnknowns(const Teuchos::RCP<const FieldPattern> & geomPattern)
301 {
302  // this is a safety check to make sure that nodes are included
303  // in the geometric field pattern when orientations are required
304  if(getOrientationsRequired()) {
305  std::size_t sz = geomPattern->getSubcellIndices(0,0).size();
306 
307  TEUCHOS_TEST_FOR_EXCEPTION(sz==0,std::logic_error,
308  "DOFManagerFEI::buildGlobalUnknowns requires a geometric pattern including "
309  "the nodes when orientations are needed!");
310  }
311 
312  if(!fieldsRegistered_)
313  registerFields();
314 
315  std::vector<std::string> fieldOrder;
316  getFieldOrder(fieldOrder);
317 
319  geomPattern_ = geomPattern;
320 
321  // get element blocks
322  std::vector<std::string> elementBlockIds;
323  connMngr->getElementBlockIds(elementBlockIds);
324 
325  // setup connectivity mesh
326  patternNum_.resize(connMngr->numElementBlocks());
327  std::vector<std::string>::const_iterator blockItr;
328  for(blockItr=elementBlockIds.begin();blockItr!=elementBlockIds.end();++blockItr) {
329  std::string blockId = *blockItr;
330  std::size_t blockIndex = blockIdToIndex(blockId);
331 
332  // build the pattern
333  bool patternBuilt = buildPattern(fieldOrder,blockId);
334 
335  if(patternBuilt) {
336  // note that condition "patternBuilt==true" implies "fieldAggPattern_[blockId]!=Teuchos::null"
337 
338  // figure out what IDs are active for this pattern
339  const std::vector<int> & numFieldsPerID = fieldAggPattern_[blockId]->numFieldsPerId();
340  std::vector<int> activeIds;
341  for(std::size_t i=0;i<numFieldsPerID.size();i++)
342  if(numFieldsPerID[i]>0)
343  activeIds.push_back(i);
344  std::vector<int> reduceConn(activeIds.size()); // which IDs to use
345 
346  // grab elements for this block
347  const std::vector<LocalOrdinal> & elements = connMngr->getElementBlock(blockId);
348 
349  // build graph for this block
350  matrixGraph_->initConnectivityBlock(blockIndex,elements.size(),patternNum_[blockIndex]);
351  for(std::size_t e=0;e<elements.size();e++) {
352  const GlobalOrdinal * conn = connMngr->getConnectivity(elements[e]);
353  for(std::size_t i=0;i<activeIds.size();i++)
354  reduceConn[i] = conn[activeIds[i]];
355 
356  matrixGraph_->initConnectivity(blockIndex,elements[e],&reduceConn[0]);
357  }
358  }
359  // else: no fields on this block, don't try to do anything with it.
360  // basically no field has been added that is associated with this
361  // element block. This is OK, but we need to correctly ignore it.
362  }
363  matrixGraph_->initComplete();
364 
365  // build owned map
366  std::vector<GlobalOrdinal> ownedIndices;
367  getOwnedIndices(ownedIndices);
368  ownedGIDHashTable_.insert(ownedIndices.begin(),ownedIndices.end());
369 
370  // now that everything is built, build the global Orientations
371  if(getOrientationsRequired())
372  buildUnknownsOrientation();
373 
374  // build local IDs (calling the base class)
375  this->buildLocalIds();
376 }
377 
378 // build the global unknown numberings
379 // 1. this builds the pattens
380 // 2. initializes the connectivity
381 // 3. calls initComplete
382 template <typename LocalOrdinalT,typename GlobalOrdinalT>
383 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::buildGlobalUnknowns()
384 {
385  if(!fieldsRegistered_)
386  registerFields();
387 
388  // build the pattern for the ID layout on the mesh
389  std::vector<RCP<const FieldPattern> > patVector;
390  RCP<GeometricAggFieldPattern> aggFieldPattern = Teuchos::rcp(new GeometricAggFieldPattern);;
391  std::map<std::pair<std::string,int>,Teuchos::RCP<const FieldPattern> >::iterator f2p_itr;
392  for(f2p_itr=fieldIntToPattern_.begin();f2p_itr!=fieldIntToPattern_.end();f2p_itr++)
393  patVector.push_back(f2p_itr->second);
394 
395  // if you need orientations, be sure to extend your
396  // geometry pattern to include the nodes this is done using
397  // NodeFieldPattern class (and is basically the sole reason for
398  // its existance).
399  if(getOrientationsRequired())
400  patVector.push_back(Teuchos::rcp(new NodalFieldPattern(patVector[0]->getCellTopology())));
401 
402  // build aggregate field pattern
403  aggFieldPattern->buildPattern(patVector);
404 
405  // setup connectivity mesh
406  connMngr_->buildConnectivity(*aggFieldPattern);
407 
408  // using new geometric pattern, build global unknowns
409  buildGlobalUnknowns(aggFieldPattern);
410 }
411 
412 template <typename LocalOrdinalT,typename GlobalOrdinalT>
413 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::buildUnknownsOrientation()
414 {
415  orientation_.clear(); // clean up previous work
416 
417  std::vector<std::string> elementBlockIds;
418  connMngr_->getElementBlockIds(elementBlockIds);
419 
420  // figure out how many total elements are owned by this processor (why is this so hard!)
421  std::size_t myElementCount = 0;
422  for(std::vector<std::string>::const_iterator blockItr=elementBlockIds.begin();
423  blockItr!=elementBlockIds.end();++blockItr)
424  myElementCount += connMngr_->getElementBlock(*blockItr).size();
425 
426  // allocate for each block
427  orientation_.resize(myElementCount);
428 
429  // loop over all element blocks
430  for(std::vector<std::string>::const_iterator blockItr=elementBlockIds.begin();
431  blockItr!=elementBlockIds.end();++blockItr) {
432  const std::string & blockName = *blockItr;
433 
434  // this block has no unknowns (or elements)
435  std::map<std::string,Teuchos::RCP<FieldAggPattern> >::const_iterator fap = fieldAggPattern_.find(blockName);
436  if(fap==fieldAggPattern_.end() || fap->second==Teuchos::null)
437  continue;
438 
439  // grab field patterns, will be necessary to compute orientations
440  const FieldPattern & fieldPattern = *fap->second;
441 
442  std::vector<std::pair<int,int> > topEdgeIndices;
443  orientation_helpers::computePatternEdgeIndices(*geomPattern_,topEdgeIndices);
444 
445  std::vector<std::vector<int> > topFaceIndices;
446  if(geomPattern_->getDimension()==3)
447  orientation_helpers::computePatternFaceIndices(*geomPattern_,topFaceIndices);
448 
449  std::size_t numGIDs = getElementBlockGIDCount(blockName);
450  const std::vector<LocalOrdinal> & elmts = getElementBlock(blockName);
451  for(std::size_t e=0;e<elmts.size();e++) {
452  // this is the vector of orientations to fill: initialize it correctly
453  std::vector<char> & eOrientation = orientation_[elmts[e]];
454  eOrientation.resize(numGIDs);
455  for(std::size_t s=0;s<eOrientation.size();s++)
456  eOrientation[s] = 1; // put in 1 by default
457 
458  // get geometry ids
459  LocalOrdinalT connSz = connMngr_->getConnectivitySize(elmts[e]);
460  const GlobalOrdinalT * connPtr = connMngr_->getConnectivity(elmts[e]);
461  const std::vector<GlobalOrdinalT> connectivity(connPtr,connPtr+connSz);
462 
463  orientation_helpers::computeCellEdgeOrientations(topEdgeIndices, connectivity, fieldPattern, eOrientation);
464 
465  // compute face orientations in 3D
466  if(geomPattern_->getDimension()==3)
467  orientation_helpers::computeCellFaceOrientations(topFaceIndices, connectivity, fieldPattern, eOrientation);
468  }
469  }
470 }
471 
472 template <typename LocalOrdinalT,typename GlobalOrdinalT>
473 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getOrderedBlock(const std::vector<std::string> & fieldOrder,
474  const std::string & blockId,
475  std::vector<int> & orderedBlock) const
476 {
477  const std::set<int> & fieldSet = this->getFields(blockId);
478  orderedBlock.clear();
479 
480  std::vector<std::string>::const_iterator itr;
481  for(itr=fieldOrder.begin();itr!=fieldOrder.end();++itr) {
482  int fieldNum = this->getFieldNum(*itr);
483 
484  // if field in in a particular block add it
485  if(fieldSet.find(fieldNum)!=fieldSet.end())
486  orderedBlock.push_back(fieldNum);
487  }
488 }
489 
490 // build the pattern associated with this manager
491 template <typename LocalOrdinalT,typename GlobalOrdinalT>
492 bool DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::buildPattern(const std::vector<std::string> & fieldOrder,
493  const std::string & blockId)
494 {
495  using Teuchos::rcp;
496  using Teuchos::RCP;
497 
498  // use some generic field ordering if the current one is empty
499  std::vector<std::pair<int,Teuchos::RCP<const FieldPattern> > > blockPatterns;
500  std::vector<int> orderedBlock;
501  getOrderedBlock(fieldOrder,blockId,orderedBlock);
502 
503  // get a map of field patterns
504  std::vector<int>::const_iterator itr;
505  for(itr=orderedBlock.begin();itr!=orderedBlock.end();++itr) {
506  Teuchos::RCP<const FieldPattern> fp = fieldIntToPattern_[std::make_pair(blockId,*itr)];
507  blockPatterns.push_back(std::make_pair(*itr,fp));
508  }
509 
510  std::size_t blockIndex = blockIdToIndex(blockId);
511  if(blockPatterns.size()<=0) {
512  patternNum_[blockIndex] = -1; // this should cause an error
513  // if this is accidently visited
514  return false;
515  }
516 
517  // smash together all fields...do interlacing
518  fieldAggPattern_[blockId] = rcp(new FieldAggPattern(blockPatterns,geomPattern_));
519 
520  // build FEI pattern
521  const std::vector<int> & fields = fieldAggPattern_[blockId]->fieldIds();
522  const std::vector<int> & numFieldsPerID = fieldAggPattern_[blockId]->numFieldsPerId();
523 
524  std::vector<int> reduceNumFieldsPerID;
525  for(std::size_t i=0;i<numFieldsPerID.size();i++)
526  if(numFieldsPerID[i]>0)
527  reduceNumFieldsPerID.push_back(numFieldsPerID[i]);
528 
529  int idsPerElement = reduceNumFieldsPerID.size();
530 
531  patternNum_[blockIndex]
532  = matrixGraph_->definePattern(idsPerElement,nodeType_,&reduceNumFieldsPerID[0],&fields[0]);
533 
534  return true;
535 }
536 
537 // "Get" functions
539 
540 namespace {
541 // hide these functions
542 
543 template <typename LocalOrdinalT,typename GlobalOrdinalT>
544 inline void getGIDsFromMatrixGraph(int blockIndex,int dof,LocalOrdinalT localElmtId,
545  fei::MatrixGraph & mg,std::vector<GlobalOrdinalT> & gids)
546 {
547  std::vector<int> indices(dof);
548 
549  // get elements indices
550  int localSize = -1;
551  mg.getConnectivityIndices(blockIndex,localElmtId,dof,&indices[0],localSize);
552 
553  // copy the indices
554  gids.resize(dof);
555  for(std::size_t i=0;i<indices.size();i++)
556  gids[i] = (GlobalOrdinalT) indices[i];
557 }
558 
559 template <typename LocalOrdinalT>
560 inline void getGIDsFromMatrixGraph(int blockIndex,int dof,LocalOrdinalT localElmtId,
561  fei::MatrixGraph & mg,std::vector<int> & gids)
562 {
563  // get elements indices
564  gids.resize(dof);
565  int localSize = -1;
566  mg.getConnectivityIndices(blockIndex,localElmtId,dof,&gids[0],localSize);
567 }
568 
569 }
570 
571 template <typename LocalOrdinalT,typename GlobalOrdinalT>
572 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getElementGIDs(LocalOrdinalT localElmtId,std::vector<GlobalOrdinalT> & gids,const std::string & blockIdHint) const
573 {
574  // this short circuits any lookup, and improves efficiency
575  std::string blockId;
576  if(blockIdHint!="")
577  blockId = blockIdHint;
578  else
579  blockId = connMngr_->getBlockId(localElmtId);
580 
581  // get information about number of indicies
582  std::size_t blockIndex = blockIdToIndex(blockId);
583  int dof = getElementBlockGIDCount(blockIndex);
584 
585  // getConnectivityNumIndices returns -1 if no block is found or
586  // has been initialized. So if this DOFManagerFEI has no fields on
587  // the block it should be ignored (hence dof>0)
588  if(dof>0) {
589  getGIDsFromMatrixGraph(blockIndex,dof,localElmtId,*matrixGraph_,gids);
590  }
591  else
592  gids.resize(0); // no DOFs available, so shrink it
593 }
594 
597 template <typename LocalOrdinalT,typename GlobalOrdinalT>
598 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::
599 getElementOrientation(LocalOrdinalT localElmtId,std::vector<double> & gidsOrientation) const
600 {
601  // TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,"DOFManagerFEI::getElementOrientation not implemented yet!");
602 
603  TEUCHOS_TEST_FOR_EXCEPTION(orientation_.size()==0,std::logic_error,
604  "DOFManagerFEI::getElementOrientations: Orientations were not constructed!");
605 
606  const std::vector<char> & local_o = orientation_[localElmtId];
607  gidsOrientation.resize(local_o.size());
608  for(std::size_t i=0;i<local_o.size();i++) {
609  gidsOrientation[i] = double(local_o[i]);
610  }
611 }
612 
613 template <typename LocalOrdinalT,typename GlobalOrdinalT>
614 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::printFieldInformation(std::ostream & os) const
615 {
616  os << "DOFManagerFEI Field Information: " << std::endl;
617 
618  if(fieldsRegistered_) {
619  std::map<std::string,Teuchos::RCP<FieldAggPattern> >::const_iterator iter;
620  for(iter=fieldAggPattern_.begin();iter!=fieldAggPattern_.end();++iter) {
621  os << "Element Block = " << iter->first << std::endl;
622  iter->second->print(os);
623 
624  // output field information
625  std::set<int>::const_iterator itr_fieldIds = blockToField_.find(iter->first)->second.begin();
626  std::set<int>::const_iterator end_fieldIds = blockToField_.find(iter->first)->second.end();
627  os << " Field String to Field Id:\n";
628  for( /*empty*/ ;itr_fieldIds!=end_fieldIds;++itr_fieldIds)
629  os << " \"" << getFieldString(*itr_fieldIds) << "\" is field ID " << *itr_fieldIds << std::endl;
630  }
631  }
632  else {
633  // fields are not registered
634  os << "Fields not yet registered! Unknowns not built (call buildGlobalUnknowns)" << std::endl;
635  }
636 }
637 
638 template <typename LocalOrdinalT,typename GlobalOrdinalT>
639 Teuchos::RCP<const FieldPattern> DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getFieldPattern(const std::string & blockId, int fieldNum) const
640 {
641  std::map<std::pair<std::string,int>,Teuchos::RCP<const FieldPattern> >::const_iterator itr;
642  itr = fieldIntToPattern_.find(std::make_pair(blockId,fieldNum));
643 
644  if(itr==fieldIntToPattern_.end()) {
645  // could not find requiested field pattern...return null
646  return Teuchos::null;
647  }
648 
649  return itr->second;
650 }
651 
652 template <typename LocalOrdinalT,typename GlobalOrdinalT>
653 Teuchos::RCP<const FieldPattern> DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::
654 getFieldPattern(const std::string & blockId, const std::string & fieldName) const
655 {
656  // return null even if field doesn't exist in manager
657  int fieldNum = -1;
658  try {
659  fieldNum = getFieldNum(fieldName);
660  }
661  catch(const std::logic_error & le) {
662  return Teuchos::null;
663  }
664 
665  return getFieldPattern(blockId,fieldNum);
666 }
667 
668 template <typename LocalOrdinalT,typename GlobalOrdinalT>
669 std::size_t DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::blockIdToIndex(const std::string & blockId) const
670 {
671  // use lazy evaluation to build block indices
672  if(blockIdToIndex_==Teuchos::null) {
673 
674  std::vector<std::string> elementBlockIds;
675  connMngr_->getElementBlockIds(elementBlockIds);
676 
677  // build ID to Index map
678  blockIdToIndex_ = Teuchos::rcp(new std::map<std::string,std::size_t>);
679  for(std::size_t i=0;i<elementBlockIds.size();i++)
680  (*blockIdToIndex_)[elementBlockIds[i]] = i;
681  }
682 
683  return (*blockIdToIndex_)[blockId];
684 }
685 
686 template <typename LocalOrdinalT,typename GlobalOrdinalT>
687 const std::map<std::string,std::size_t> & DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::blockIdToIndexMap() const
688 {
689  // use lazy evaluation to build block indices
690  if(blockIdToIndex_==Teuchos::null) {
691 
692  std::vector<std::string> elementBlockIds;
693  connMngr_->getElementBlockIds(elementBlockIds);
694 
695  // build ID to Index map
696  blockIdToIndex_ = Teuchos::rcp(new std::map<std::string,std::size_t>);
697  for(std::size_t i=0;i<elementBlockIds.size();i++)
698  (*blockIdToIndex_)[elementBlockIds[i]] = i;
699  }
700 
701  return *blockIdToIndex_;
702 }
703 
704 template <typename LocalOrdinalT,typename GlobalOrdinalT>
705 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::ownedIndices(const std::vector<GlobalOrdinalT> & indices,std::vector<bool> & isOwned) const
706 {
707  // verify size is correct
708  if(indices.size()!=isOwned.size())
709  isOwned.resize(indices.size(),false);
710 
711  // use unordered set to check for ownership of the ID
712  typename std::unordered_set<GlobalOrdinal>::const_iterator endItr = ownedGIDHashTable_.end();
713  for(std::size_t i=0;i<indices.size();i++)
714  isOwned[i] = (ownedGIDHashTable_.find(indices[i])!=endItr);
715 }
716 
717 // These two functions are "helpers" for DOFManagerFEI::getOwnedIndices
719 template <typename OrdinalType>
720 static void getOwnedIndices_T(const fei::SharedPtr<fei::VectorSpace> & vs,std::vector<OrdinalType> & indices)
721 {
722  int numIndices, ni;
723  numIndices = vs->getNumIndices_Owned();
724  indices.resize(numIndices);
725  std::vector<int> int_Indices; // until FEI is templated
726 
727  // get the number of locally owned degrees of freedom...allocate space
728  int_Indices.resize(numIndices);
729 
730  // get the global indices
731  vs->getIndices_Owned(numIndices,&int_Indices[0],ni);
732 
733  for(std::size_t i=0;i<int_Indices.size();i++)
734  indices[i] = (OrdinalType) int_Indices[i];
735 }
736 
737 template <typename LocalOrdinalT,typename GlobalOrdinalT>
738 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getOwnedIndices(std::vector<GlobalOrdinalT> & indices) const
739 {
740  getOwnedIndices_T<GlobalOrdinalT>(vectorSpace_,indices);
741 }
742 
751 template <typename LocalOrdinalT,typename GlobalOrdinalT>
752 bool DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::validFieldOrder(const std::vector<std::string> & fieldOrder_ut,const std::set<std::string> & fields) const
753 {
754  if(fields.size()!=fieldOrder_ut.size()) // something is wrong!
755  return false;
756 
757  std::set<std::string> fieldOrderSet;
758 
759  // first check the size by shoving everything into a set
760  std::vector<std::string>::const_iterator itr;
761  for(itr=fieldOrder_ut.begin();itr!=fieldOrder_ut.end();++itr)
762  fieldOrderSet.insert(*itr);
763 
764  if(fieldOrderSet.size()!=fieldOrder_ut.size()) // there are repeat fields!
765  return false;
766 
767  // check to make sure each field is represented
768  std::set<std::string>::const_iterator itr_ut = fieldOrderSet.begin();
769  std::set<std::string>::const_iterator itr_src = fields.begin();
770  while(itr_ut!=fieldOrderSet.end()) {
771  if(*itr_ut!=*itr_src)
772  return false;
773 
774  itr_ut++;
775  itr_src++;
776  }
777 
778  return true;
779 }
780 
782 
783 // These two functions are "helpers" for DOFManagerFEI::getOwnedAndSharedIndices
785 template <typename OrdinalType>
786 static void getOwnedAndSharedIndices_T(const fei::SharedPtr<fei::VectorSpace> & vs,std::vector<OrdinalType> & indices)
787 {
788  std::vector<int> int_Indices; // until FEI is templated
789 
790  // get the global indices
791  vs->getIndices_SharedAndOwned(int_Indices);
792 
793  indices.resize(int_Indices.size());
794  for(std::size_t i=0;i<int_Indices.size();i++)
795  indices[i] = (OrdinalType) int_Indices[i];
796 }
797 
798 template <typename LocalOrdinalT,typename GlobalOrdinalT>
799 void DOFManagerFEI<LocalOrdinalT,GlobalOrdinalT>::getOwnedAndSharedIndices(std::vector<GlobalOrdinalT> & indices) const
800 {
801  getOwnedAndSharedIndices_T<GlobalOrdinalT>(vectorSpace_,indices);
802 }
804 
805 }
806 
807 #endif
808 #endif
RCP< const T > getConst() const
void computeCellFaceOrientations(const std::vector< std::pair< int, int > > &topEdgeIndices, const std::vector< GlobalOrdinalT > &topology, const FieldPattern &fieldPattern, std::vector< char > &orientation)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void computeCellEdgeOrientations(const std::vector< std::pair< int, int > > &topEdgeIndices, const std::vector< GlobalOrdinalT > &topology, const FieldPattern &fieldPattern, std::vector< char > &orientation)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
PHX::MDField< const ScalarT > dof
void computePatternFaceIndices(const FieldPattern &pattern, std::vector< std::vector< int > > &faceIndices)
virtual const std::vector< int > & getSubcellIndices(int dim, int cellIndex) const =0
void computePatternEdgeIndices(const FieldPattern &pattern, std::vector< std::pair< int, int > > &edgeIndices)