Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_UniqueGlobalIndexer_EpetraUtilities_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 #ifndef PANZER_UNIQUEGLOBALINDEXER_EPETRAUTILITIES_IMPL_HPP
43 #define PANZER_UNIQUEGLOBALINDEXER_EPETRAUTILITIES_IMPL_HPP
44 
45 #include <vector>
46 #include <map>
47 
48 #include "Teuchos_FancyOStream.hpp"
49 #include "Teuchos_ArrayView.hpp"
50 #include "Teuchos_CommHelpers.hpp"
51 
52 #include "Epetra_Map.h"
53 #include "Epetra_IntVector.h"
54 #include "Epetra_MultiVector.h"
55 #include "Epetra_Import.h"
56 #include "Epetra_MpiComm.h"
57 
58 #include "Epetra_CombineMode.h"
59 #include "Epetra_DataAccess.h"
60 
61 #include <sstream>
62 #include <cmath>
63 
64 namespace panzer {
65 
66 
67 template <typename LocalOrdinalT,typename GlobalOrdinalT>
70 {
71  typedef Epetra_BlockMap Map;
72  typedef Epetra_IntVector IntVector;
73 
74  std::vector<GlobalOrdinalT> indices;
75  std::vector<std::string> blocks;
76 
77  ugi.getOwnedAndGhostedIndices(indices);
78  ugi.getElementBlockIds(blocks);
79 
80  std::vector<int> fieldNumbers(indices.size(),-1);
81 
82  const Teuchos::RCP<const Teuchos::MpiComm<int> > mpiComm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(ugi.getComm());
84  if (mpiComm != Teuchos::null)
85  comm = Teuchos::rcp(new Epetra_MpiComm(*mpiComm->getRawMpiComm()));
86 
87  Teuchos::RCP<Map> ghostedMap
88  = Teuchos::rcp(new Map(-1, static_cast<int>(indices.size()), Teuchos::arrayViewFromVector(indices).getRawPtr(),
90 
91  // build a map from local ids to a field number
92  for(std::size_t blk=0;blk<blocks.size();blk++) {
93  std::string blockId = blocks[blk];
94 
95  const std::vector<LocalOrdinalT> & elements = ugi.getElementBlock(blockId);
96  const std::vector<int> & fields = ugi.getBlockFieldNumbers(blockId);
97 
98  // loop over all elements, and set field number in output array
99  std::vector<GlobalOrdinalT> gids(fields.size());
100  for(std::size_t e=0;e<elements.size();e++) {
101  ugi.getElementGIDs(elements[e],gids);
102 
103  for(std::size_t f=0;f<fields.size();f++) {
104  int fieldNum = fields[f];
105  GlobalOrdinalT gid = gids[f];
106  std::size_t lid = ghostedMap->LID(gid); // hash table lookup
107 
108  fieldNumbers[lid] = fieldNum;
109  }
110  }
111  }
112 
113  // produce a reduced vector containing only fields known by this processor
114  std::vector<GlobalOrdinalT> reducedIndices;
115  std::vector<int> reducedFieldNumbers;
116  for(std::size_t i=0;i<fieldNumbers.size();i++) {
117  if(fieldNumbers[i]>-1) {
118  reducedIndices.push_back(indices[i]);
119  reducedFieldNumbers.push_back(fieldNumbers[i]);
120  }
121  }
122 
123  Teuchos::RCP<Map> reducedMap
124  = Teuchos::rcp(new Map(-1, static_cast<int>(reducedIndices.size()), Teuchos::arrayViewFromVector(reducedIndices).getRawPtr(),
125  1, Teuchos::OrdinalTraits<int>::zero(), *comm));
126  return Teuchos::rcp(new IntVector(Copy,*reducedMap,Teuchos::arrayViewFromVector(reducedFieldNumbers).getRawPtr()));
127 }
128 
129 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
131  std::vector<int> & fieldNumbers,
132  const Teuchos::RCP<const Epetra_IntVector> & reducedVec)
133 {
134  typedef Epetra_IntVector IntVector;
135 
136  Teuchos::RCP<const IntVector> dest = buildGhostedFieldVectorEpetra<LocalOrdinalT,GlobalOrdinalT,Node>(ugi,reducedVec);
137 
138  fieldNumbers.resize(dest->MyLength());
139  Teuchos::ArrayView<int> av = Teuchos::arrayViewFromVector(fieldNumbers);
140  dest->ExtractCopy(av.getRawPtr());
141 }
142 
143 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
146  const Teuchos::RCP<const Epetra_IntVector> & reducedVec)
147 {
148  typedef Epetra_BlockMap Map;
149  typedef Epetra_IntVector IntVector;
150  typedef Epetra_Import Importer;
151 
152  // first step: get a reduced field number vector and build a map to
153  // contain the full field number vector
155 
156  Teuchos::RCP<Map> destMap;
157  {
158  std::vector<GlobalOrdinalT> indices;
159  ugi.getOwnedAndGhostedIndices(indices);
160 
161  const Teuchos::RCP<const Teuchos::MpiComm<int> > mpiComm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(ugi.getComm());
163  if (mpiComm != Teuchos::null)
164  comm = Teuchos::rcp(new Epetra_MpiComm(*mpiComm->getRawMpiComm()));
165 
166  destMap = Teuchos::rcp(new Map(-1, static_cast<int>(indices.size()), Teuchos::arrayViewFromVector(indices).getRawPtr(),
167  1, Teuchos::OrdinalTraits<int>::zero(), *comm));
168  }
169 
170  Teuchos::RCP<const IntVector> source = reducedVec;
171  if(source==Teuchos::null)
172  source = buildGhostedFieldReducedVectorEpetra<LocalOrdinalT,GlobalOrdinalT>(ugi);
173  Teuchos::RCP<const Map> sourceMap = Teuchos::rcpFromRef(source->Map());
174 
175  // second step: perform the global communciation required to fix the
176  // interface conditions (where this processor doesn't know what field
177  // some indices are)
179  Teuchos::RCP<IntVector> dest = Teuchos::rcp(new IntVector(*destMap));
180  Importer importer(*destMap,*sourceMap);
181 
182  dest->Import(*source,importer,Insert);
183 
184  return dest;
185 }
186 
187 template <typename ScalarT,typename ArrayT,typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
188 void updateGhostedDataReducedVectorEpetra(const std::string & fieldName,const std::string blockId,
190  const ArrayT & data,Epetra_MultiVector & dataVector)
191 {
192  typedef Epetra_BlockMap Map;
193 
194  TEUCHOS_TEST_FOR_EXCEPTION(!ugi.fieldInBlock(fieldName,blockId),std::runtime_error,
195  "panzer::updateGhostedDataReducedVector: field name = \""+fieldName+"\" is not in element block = \"" +blockId +"\"!");
196 
197  Teuchos::RCP<const Map> dataMap = Teuchos::rcpFromRef(dataVector.Map());
198 
199  int fieldNum = ugi.getFieldNum(fieldName);
200  const std::vector<LocalOrdinalT> & elements = ugi.getElementBlock(blockId);
201  const std::vector<int> & fieldOffsets = ugi.getGIDFieldOffsets(blockId,fieldNum);
202 
203  TEUCHOS_TEST_FOR_EXCEPTION(data.extent(0)!=elements.size(),std::runtime_error,
204  "panzer::updateGhostedDataReducedVector: data cell dimension does not match up with block cell count");
205 
206  int rank = data.rank();
207 
208  if(rank==2) {
209  // loop over elements distributing relevent data to vector
210  std::vector<GlobalOrdinalT> gids;
211  for(std::size_t e=0;e<elements.size();e++) {
212  ugi.getElementGIDs(elements[e],gids);
213 
214  for(std::size_t f=0;f<fieldOffsets.size();f++) {
215  std::size_t localIndex = dataMap->LID(gids[fieldOffsets[f]]); // hash table lookup
216  dataVector.ReplaceMyValue(localIndex,0,data(e,f));
217  }
218  }
219  }
220  else if(rank==3) {
221  std::size_t entries = data.extent(2);
222 
223  TEUCHOS_TEST_FOR_EXCEPTION(dataVector.NumVectors()!=static_cast<int>(entries),std::runtime_error,
224  "panzer::updateGhostedDataReducedVector: number of columns in data vector inconsistent with data array");
225 
226  // loop over elements distributing relevent data to vector
227  std::vector<GlobalOrdinalT> gids;
228  for(std::size_t e=0;e<elements.size();e++) {
229  ugi.getElementGIDs(elements[e],gids);
230 
231  for(std::size_t f=0;f<fieldOffsets.size();f++) {
232  std::size_t localIndex = dataMap->LID(gids[fieldOffsets[f]]); // hash table lookup
233  for(std::size_t v=0;v<entries;v++)
234  dataVector.ReplaceMyValue(localIndex,v,data(e,f,v));
235  }
236  }
237  }
238  else
239  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
240  "panzer::updateGhostedDataReducedVector: data array rank must be 2 or 3");
241 }
242 
243 
244 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
247  : ugi_(ugi)
248 {
249  gh_reducedFieldVector_ = buildGhostedFieldReducedVectorEpetra<LocalOrdinalT,GlobalOrdinalT>(*ugi_);
250  gh_fieldVector_ = buildGhostedFieldVectorEpetra<LocalOrdinalT,GlobalOrdinalT,Node>(*ugi_,gh_reducedFieldVector_);
251 }
252 
253 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
254 template <typename ScalarT,typename ArrayT>
257  getGhostedDataVector(const std::string & fieldName,const std::map<std::string,ArrayT> & data) const
258 {
259  TEUCHOS_ASSERT(data.size()>0); // there must be at least one "data" item
260 
261  int fieldNum = ugi_->getFieldNum(fieldName);
262  std::vector<std::string> blockIds;
263  ugi_->getElementBlockIds(blockIds);
264 
265  // get rank of first data array, determine column count
266  int rank = data.begin()->second.rank();
267  int numCols = 0;
268  if(rank==2)
269  numCols = 1;
270  else if(rank==3)
271  numCols = data.begin()->second.extent(2);
272  else {
273  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
274  "ArrayToFieldVectorEpetra::getGhostedDataVector: data array must have rank 2 or 3. This array has rank " << rank << ".");
275  }
276 
277 
278  // first build and fill in final reduced field vector
280 
281  // build field maps as needed
282  Teuchos::RCP<const Map> reducedMap = gh_reducedFieldMaps_[fieldNum];
283  if(gh_reducedFieldMaps_[fieldNum]==Teuchos::null) {
284  reducedMap = panzer::getFieldMapEpetra(fieldNum,*gh_reducedFieldVector_);
285  gh_reducedFieldMaps_[fieldNum] = reducedMap;
286  }
287 
288  Teuchos::RCP<MultiVector> finalReducedVec
289  = Teuchos::rcp(new MultiVector(*reducedMap,numCols));
290  for(std::size_t b=0;b<blockIds.size();b++) {
291  std::string block = blockIds[b];
292 
293  // make sure field is in correct block
294  if(!ugi_->fieldInBlock(fieldName,block))
295  continue;
296 
297  // extract data vector
298  typename std::map<std::string,ArrayT>::const_iterator blockItr = data.find(block);
299  TEUCHOS_TEST_FOR_EXCEPTION(blockItr==data.end(),std::runtime_error,
300  "ArrayToFieldVectorEpetra::getDataVector: can not find block \""+block+"\".");
301 
302  const ArrayT & d = blockItr->second;
303  updateGhostedDataReducedVectorEpetra<ScalarT,ArrayT,LocalOrdinalT,GlobalOrdinalT,Node>(fieldName,block,*ugi_,d,*finalReducedVec);
304  }
305 
306  // build final (not reduced vector)
308 
309  Teuchos::RCP<const Map> map = gh_fieldMaps_[fieldNum];
310  if(gh_fieldMaps_[fieldNum]==Teuchos::null) {
311  map = panzer::getFieldMapEpetra(fieldNum,*gh_fieldVector_);
312  gh_fieldMaps_[fieldNum] = map;
313  }
314 
316  = Teuchos::rcp(new MultiVector(*map,numCols));
317 
318  // do import from finalReducedVec
319  Epetra_Import importer(*map,*reducedMap);
320  finalVec->Import(*finalReducedVec,importer,Insert);
321 
322  return finalVec;
323 }
324 
325 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
326 template <typename ScalarT,typename ArrayT>
329  getDataVector(const std::string & fieldName,const std::map<std::string,ArrayT> & data) const
330 {
331  // if neccessary build field vector
332  if(fieldVector_==Teuchos::null)
333  buildFieldVector(*gh_fieldVector_);
334 
336  = getGhostedDataVector<ScalarT,ArrayT>(fieldName,data);
337 
338  // use lazy construction for each field
339  int fieldNum = ugi_->getFieldNum(fieldName);
340  Teuchos::RCP<const Map> destMap = fieldMaps_[fieldNum];
341  if(fieldMaps_[fieldNum]==Teuchos::null) {
342  destMap = panzer::getFieldMapEpetra(fieldNum,*fieldVector_);
343  fieldMaps_[fieldNum] = destMap;
344  }
345 
347  = Teuchos::rcp(new MultiVector(*destMap,sourceVec->NumVectors()));
348 
349  // do import
350  Epetra_Import importer(*destMap,sourceVec->Map());
351  destVec->Import(*sourceVec,importer,Insert);
352 
353  return destVec;
354 }
355 
356 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
358  buildFieldVector(const Epetra_IntVector & source) const
359 {
360  // build (unghosted) vector and map
361  std::vector<GlobalOrdinalT> indices;
362  ugi_->getOwnedIndices(indices);
363 
364  const Teuchos::RCP<const Teuchos::MpiComm<int> > mpiComm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(ugi_->getComm(),true);
366  if (mpiComm != Teuchos::null)
367  comm = Teuchos::rcp(new Epetra_MpiComm(*mpiComm->getRawMpiComm()));
368 
369  Teuchos::RCP<Map> destMap
370  = Teuchos::rcp(new Map(-1, static_cast<int>(indices.size()),
371  Teuchos::arrayViewFromVector(indices).getRawPtr(),
372  // &indices.begin(),
373  1, Teuchos::OrdinalTraits<int>::zero(), *comm));
374 
375  Teuchos::RCP<IntVector> localFieldVector = Teuchos::rcp(new IntVector(*destMap));
376 
377  Epetra_Import importer(*destMap,source.Map());
378  localFieldVector->Import(source,importer,Insert);
379 
380  fieldVector_ = localFieldVector;
381 }
382 
383 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
386 getFieldMap(const std::string & fieldName) const
387 {
388  return getFieldMap(ugi_->getFieldNum(fieldName));
389 }
390 
391 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
394 getFieldMap(int fieldNum) const
395 {
396  if(fieldMaps_[fieldNum]==Teuchos::null) {
397  // if neccessary build field vector
398  if(fieldVector_==Teuchos::null)
399  buildFieldVector(*gh_fieldVector_);
400 
401  fieldMaps_[fieldNum] = panzer::getFieldMapEpetra(fieldNum,*fieldVector_);
402  }
403 
404  return fieldMaps_[fieldNum];
405 }
406 
407 } // end namspace panzer
408 
409 #endif
virtual bool fieldInBlock(const std::string &field, const std::string &block) const =0
virtual void getElementGIDs(LocalOrdinalT localElmtId, std::vector< GlobalOrdinalT > &gids, const std::string &blockIdHint="") const =0
Get the global IDs for a particular element. This function overwrites the gids variable.
void buildFieldVector(const Epetra_IntVector &source) const
build unghosted field vector from ghosted field vector
Teuchos::RCP< Epetra_MultiVector > getDataVector(const std::string &fieldName, const std::map< std::string, ArrayT > &data) const
ArrayToFieldVectorEpetra()
Maps for each field (as needed)
virtual void getOwnedAndGhostedIndices(std::vector< GlobalOrdinalT > &indices) const =0
Get the set of owned and ghosted indices for this processor.
virtual void getElementBlockIds(std::vector< std::string > &elementBlockIds) const =0
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual Teuchos::RCP< Teuchos::Comm< int > > getComm() const =0
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.
Teuchos::RCP< const Tpetra::Map< int, GlobalOrdinalT, Node > > getFieldMap(int fieldNum, const Tpetra::Vector< int, int, GlobalOrdinalT, Node > &fieldVector)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< Epetra_IntVector > buildGhostedFieldReducedVectorEpetra(const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi)
void updateGhostedDataReducedVectorEpetra(const std::string &fieldName, const std::string blockId, const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi, const ArrayT &data, Epetra_MultiVector &dataVector)
T * getRawPtr() const
Teuchos::RCP< const Epetra_BlockMap > getFieldMapEpetra(int fieldNum, const Epetra_IntVector &fieldTVector)
Teuchos::RCP< const Epetra_IntVector > buildGhostedFieldVectorEpetra(const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi, const Teuchos::RCP< const Epetra_IntVector > &reducedVec=Teuchos::null)
Teuchos::RCP< const IntVector > gh_fieldVector_
ghosted reduced field vector
virtual int getFieldNum(const std::string &str) const =0
Get the number used for access to this field.
Teuchos::RCP< const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > > ugi_
DOF mapping.
virtual const std::vector< int > & getBlockFieldNumbers(const std::string &blockId) const =0
virtual const std::vector< LocalOrdinalT > & getElementBlock(const std::string &blockId) const =0
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< const Epetra_Map > getFieldMap(const std::string &fieldName) const