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