Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_GlobalIndexer_EpetraUtilities_impl.hpp
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 
11 #ifndef PANZER_UNIQUEGLOBALINDEXER_EPETRAUTILITIES_IMPL_HPP
12 #define PANZER_UNIQUEGLOBALINDEXER_EPETRAUTILITIES_IMPL_HPP
13 
14 #include <vector>
15 #include <map>
16 
17 #include "Teuchos_FancyOStream.hpp"
18 #include "Teuchos_ArrayView.hpp"
19 #include "Teuchos_CommHelpers.hpp"
20 
21 #include "Epetra_Map.h"
22 #include "Epetra_IntVector.h"
23 #include "Epetra_MultiVector.h"
24 #include "Epetra_Import.h"
25 #include "Epetra_MpiComm.h"
26 
27 #include "Epetra_CombineMode.h"
28 #include "Epetra_DataAccess.h"
29 
30 #include <sstream>
31 #include <cmath>
32 
33 namespace panzer {
34 
35 template <typename ScalarT,typename ArrayT>
36 void updateGhostedDataReducedVectorEpetra(const std::string & fieldName,const std::string blockId,
37  const GlobalIndexer & ugi,
38  const ArrayT & data,Epetra_MultiVector & dataVector)
39 {
40  typedef Epetra_BlockMap Map;
41 
42  TEUCHOS_TEST_FOR_EXCEPTION(!ugi.fieldInBlock(fieldName,blockId),std::runtime_error,
43  "panzer::updateGhostedDataReducedVector: field name = \""+fieldName+"\" is not in element block = \"" +blockId +"\"!");
44 
45  Teuchos::RCP<const Map> dataMap = Teuchos::rcpFromRef(dataVector.Map());
46 
47  int fieldNum = ugi.getFieldNum(fieldName);
48  const std::vector<panzer::LocalOrdinal> & elements = ugi.getElementBlock(blockId);
49  const std::vector<int> & fieldOffsets = ugi.getGIDFieldOffsets(blockId,fieldNum);
50 
51  TEUCHOS_TEST_FOR_EXCEPTION(data.extent(0)!=elements.size(),std::runtime_error,
52  "panzer::updateGhostedDataReducedVector: data cell dimension does not match up with block cell count");
53 
54  int rank = data.rank();
55 
56  if(rank==2) {
57  // loop over elements distributing relevent data to vector
58  std::vector<panzer::GlobalOrdinal> gids;
59  for(std::size_t e=0;e<elements.size();e++) {
60  ugi.getElementGIDs(elements[e],gids);
61 
62  for(std::size_t f=0;f<fieldOffsets.size();f++) {
63  std::size_t localIndex = dataMap->LID(gids[fieldOffsets[f]]); // hash table lookup
64  dataVector.ReplaceMyValue(localIndex,0,data(e,f));
65  }
66  }
67  }
68  else if(rank==3) {
69  std::size_t entries = data.extent(2);
70 
71  TEUCHOS_TEST_FOR_EXCEPTION(dataVector.NumVectors()!=static_cast<int>(entries),std::runtime_error,
72  "panzer::updateGhostedDataReducedVector: number of columns in data vector inconsistent with data array");
73 
74  // loop over elements distributing relevent data to vector
75  std::vector<panzer::GlobalOrdinal> gids;
76  for(std::size_t e=0;e<elements.size();e++) {
77  ugi.getElementGIDs(elements[e],gids);
78 
79  for(std::size_t f=0;f<fieldOffsets.size();f++) {
80  std::size_t localIndex = dataMap->LID(gids[fieldOffsets[f]]); // hash table lookup
81  for(std::size_t v=0;v<entries;v++)
82  dataVector.ReplaceMyValue(localIndex,v,data(e,f,v));
83  }
84  }
85  }
86  else
87  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
88  "panzer::updateGhostedDataReducedVector: data array rank must be 2 or 3");
89 }
90 
91 template <typename ScalarT,typename ArrayT>
93 ArrayToFieldVectorEpetra::getGhostedDataVector(const std::string & fieldName,
94  const std::map<std::string,ArrayT> & data) const
95 {
96  TEUCHOS_ASSERT(data.size()>0); // there must be at least one "data" item
97 
98  int fieldNum = ugi_->getFieldNum(fieldName);
99  std::vector<std::string> blockIds;
100  ugi_->getElementBlockIds(blockIds);
101 
102  // get rank of first data array, determine column count
103  int rank = data.begin()->second.rank();
104  int numCols = 0;
105  if(rank==2)
106  numCols = 1;
107  else if(rank==3)
108  numCols = data.begin()->second.extent(2);
109  else {
110  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
111  "ArrayToFieldVectorEpetra::getGhostedDataVector: data array must have rank 2 or 3. This array has rank " << rank << ".");
112  }
113 
114 
115  // first build and fill in final reduced field vector
117 
118  // build field maps as needed
119  Teuchos::RCP<const Map> reducedMap = gh_reducedFieldMaps_[fieldNum];
120  if(gh_reducedFieldMaps_[fieldNum]==Teuchos::null) {
121  reducedMap = panzer::getFieldMapEpetra(fieldNum,*gh_reducedFieldVector_);
122  gh_reducedFieldMaps_[fieldNum] = reducedMap;
123  }
124 
125  Teuchos::RCP<MultiVector> finalReducedVec
126  = Teuchos::rcp(new MultiVector(*reducedMap,numCols));
127  for(std::size_t b=0;b<blockIds.size();b++) {
128  std::string block = blockIds[b];
129 
130  // make sure field is in correct block
131  if(!ugi_->fieldInBlock(fieldName,block))
132  continue;
133 
134  // extract data vector
135  typename std::map<std::string,ArrayT>::const_iterator blockItr = data.find(block);
136  TEUCHOS_TEST_FOR_EXCEPTION(blockItr==data.end(),std::runtime_error,
137  "ArrayToFieldVectorEpetra::getDataVector: can not find block \""+block+"\".");
138 
139  const ArrayT & d = blockItr->second;
140  updateGhostedDataReducedVectorEpetra<ScalarT,ArrayT>(fieldName,block,*ugi_,d,*finalReducedVec);
141  }
142 
143  // build final (not reduced vector)
145 
146  Teuchos::RCP<const Map> map = gh_fieldMaps_[fieldNum];
147  if(gh_fieldMaps_[fieldNum]==Teuchos::null) {
149  gh_fieldMaps_[fieldNum] = map;
150  }
151 
153  = Teuchos::rcp(new MultiVector(*map,numCols));
154 
155  // do import from finalReducedVec
156  Epetra_Import importer(*map,*reducedMap);
157  finalVec->Import(*finalReducedVec,importer,Insert);
158 
159  return finalVec;
160 }
161 
162 template <typename ScalarT,typename ArrayT>
164 ArrayToFieldVectorEpetra::getDataVector(const std::string & fieldName,
165  const std::map<std::string,ArrayT> & data) const
166 {
167  // if neccessary build field vector
168  if(fieldVector_==Teuchos::null)
170 
172  = getGhostedDataVector<ScalarT,ArrayT>(fieldName,data);
173 
174  // use lazy construction for each field
175  int fieldNum = ugi_->getFieldNum(fieldName);
176  Teuchos::RCP<const Map> destMap = fieldMaps_[fieldNum];
177  if(fieldMaps_[fieldNum]==Teuchos::null) {
178  destMap = panzer::getFieldMapEpetra(fieldNum,*fieldVector_);
179  fieldMaps_[fieldNum] = destMap;
180  }
181 
183  = Teuchos::rcp(new MultiVector(*destMap,sourceVec->NumVectors()));
184 
185  // do import
186  Epetra_Import importer(*destMap,sourceVec->Map());
187  destVec->Import(*sourceVec,importer,Insert);
188 
189  return destVec;
190 }
191 
192 } // end namspace panzer
193 
194 #endif
std::map< int, Teuchos::RCP< const Map > > fieldMaps_
(unghosted) field vector (as needed)
Teuchos::RCP< Epetra_MultiVector > getDataVector(const std::string &fieldName, const std::map< std::string, ArrayT > &data) const
Teuchos::RCP< const IntVector > fieldVector_
Maps for each field (as needed)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual const std::vector< panzer::LocalOrdinal > & getElementBlock(const std::string &blockId) const =0
void buildFieldVector(const Epetra_IntVector &source) const
build unghosted field vector from ghosted field vector
std::map< int, Teuchos::RCP< const Map > > gh_fieldMaps_
Maps for each field (as needed)
Teuchos::RCP< const IntVector > gh_fieldVector_
ghosted reduced field vector
virtual bool fieldInBlock(const std::string &field, const std::string &block) const =0
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual int getFieldNum(const std::string &str) const =0
Get the number used for access to this field.
Teuchos::RCP< const GlobalIndexer > ugi_
DOF mapping.
Teuchos::RCP< Epetra_MultiVector > getGhostedDataVector(const std::string &fieldName, const std::map< std::string, ArrayT > &data) const
virtual const std::vector< int > & getGIDFieldOffsets(const std::string &blockId, int fieldNum) const =0
Use the field pattern so that you can find a particular field in the GIDs array.
virtual void getElementGIDs(panzer::LocalOrdinal localElmtId, std::vector< panzer::GlobalOrdinal > &gids, const std::string &blockIdHint="") const =0
Get the global IDs for a particular element. This function overwrites the gids variable.
std::map< int, Teuchos::RCP< const Map > > gh_reducedFieldMaps_
ghosted field vector
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< const Epetra_BlockMap > getFieldMapEpetra(int fieldNum, const Epetra_IntVector &fieldVector)
void updateGhostedDataReducedVectorEpetra(const std::string &fieldName, const std::string blockId, const GlobalIndexer &ugi, const ArrayT &data, Epetra_MultiVector &dataVector)