Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_UniqueGlobalIndexer_Utilities_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 #include <vector>
44 #include <map>
45 
46 #include "Teuchos_FancyOStream.hpp"
47 #include "Teuchos_ArrayView.hpp"
48 #include "Teuchos_CommHelpers.hpp"
49 
50 #include "Tpetra_Map.hpp"
51 #include "Tpetra_Vector.hpp"
52 #include "Tpetra_Import.hpp"
53 
54 #include <sstream>
55 #include <cmath>
56 
57 namespace panzer {
58 
59 template <typename LocalOrdinalT,typename GlobalOrdinalT>
60 std::vector<Teuchos::RCP<const UniqueGlobalIndexer<LocalOrdinalT,GlobalOrdinalT> > >
62 {
63  std::vector<Teuchos::RCP<const UniqueGlobalIndexer<LocalOrdinalT,GlobalOrdinalT> > > vec;
64 
65  for(std::size_t blk=0;blk<ugis.size();blk++)
66  vec.push_back(ugis[blk]);
67 
68  return vec;
69 }
70 
71 template <typename LocalOrdinalT,typename GlobalOrdinalT>
72 int getFieldBlock(const std::string & fieldName,
73  const std::vector<Teuchos::RCP<const UniqueGlobalIndexer<LocalOrdinalT,GlobalOrdinalT> > > & ugis)
74 {
75  int fieldNum = -1;
76  for(std::size_t blk=0;blk<ugis.size();blk++) {
77  fieldNum = ugis[blk]->getFieldNum(fieldName);
78  if(fieldNum>=0)
79  return blk;
80  }
81 
82  return fieldNum;
83 }
84 
85 template <typename LocalOrdinalT,typename GlobalOrdinalT>
86 int getFieldBlock(const std::string & fieldName,
88 {
89  int fieldNum = -1;
90  for(std::size_t blk=0;blk<ugis.size();blk++) {
91  fieldNum = ugis[blk]->getFieldNum(fieldName);
92  if(fieldNum>=0)
93  return fieldNum;
94  }
95 
96  return fieldNum;
97 }
98 
99 template <typename LocalOrdinalT,typename GlobalOrdinalT>
100 void computeBlockOffsets(const std::string & blockId,
102  std::vector<int> & blockOffsets)
103 {
104  blockOffsets.resize(ugis.size()+1); // number of fields, plus a sentinnel
105 
106  int offset = 0;
107  for(std::size_t blk=0;blk<ugis.size();blk++) {
108  blockOffsets[blk] = offset;
109  offset += ugis[blk]->getElementBlockGIDCount(blockId);
110  }
111  blockOffsets[ugis.size()] = offset;
112 }
113 
114 template <typename LocalOrdinalT,typename GlobalOrdinalT>
115 void computeBlockOffsets(const std::string & blockId,
116  const std::vector<Teuchos::RCP<const UniqueGlobalIndexer<LocalOrdinalT,GlobalOrdinalT> > > & ugis,
117  std::vector<int> & blockOffsets)
118 {
119  blockOffsets.resize(ugis.size()+1); // number of fields, plus a sentinnel
120 
121  int offset = 0;
122  for(std::size_t blk=0;blk<ugis.size();blk++) {
123  blockOffsets[blk] = offset;
124  offset += ugis[blk]->getElementBlockGIDCount(blockId);
125  }
126  blockOffsets[ugis.size()] = offset;
127 }
128 
129 template <typename LocalOrdinalT,typename GlobalOrdinalT>
130 std::string
132 {
133  std::vector<GlobalOrdinalT> owned;
134  ugi.getOwnedIndices(owned);
135 
136  std::size_t myOwnedCount = owned.size();
137 
138  std::size_t sum=0,min=0,max=0;
139 
140  // get min,max and sum
141  Teuchos::reduceAll(*ugi.getComm(),Teuchos::REDUCE_SUM,1,&myOwnedCount,&sum);
142  Teuchos::reduceAll(*ugi.getComm(),Teuchos::REDUCE_MIN,1,&myOwnedCount,&min);
143  Teuchos::reduceAll(*ugi.getComm(),Teuchos::REDUCE_MAX,1,&myOwnedCount,&max);
144 
145  // compute mean and variance
146  double dev2 = (double(myOwnedCount)-double(sum)/double(ugi.getComm()->getSize()));
147  dev2 *= dev2;
148 
149  double variance = 0.0;
150  Teuchos::reduceAll(*ugi.getComm(),Teuchos::REDUCE_SUM,1,&dev2,&variance);
151 
152  double mean = sum / double(ugi.getComm()->getSize());
153  variance = variance / double(ugi.getComm()->getSize());
154 
155  // now print to a string stream
156  std::stringstream ss;
157  ss << "Max, Min, Mean, StdDev = " << max << ", " << min << ", " << mean << ", " << std::sqrt(variance);
158 
159  return ss.str();
160 }
161 
162 template <typename LocalOrdinalT,typename GlobalOrdinalT>
163 void
165 {
166  std::vector<std::string> block_ids;
167 
168  ugi.getElementBlockIds(block_ids);
169  for(std::size_t b=0;b<block_ids.size();b++) {
170  // extract the elemnts in each element block
171  const std::vector<LocalOrdinalT> & elements = ugi.getElementBlock(block_ids[b]);
172 
173  os << "Element Block: \"" << block_ids[b] << "\"" << std::endl;
174 
175  // loop over element in this element block, write out to
176  for(std::size_t e=0;e<elements.size();e++) {
177  // extract LIDs, this is returned by reference nominally for performance
178  Kokkos::View<const int*, PHX::Device> lids = ugi.getElementLIDs(elements[e]);
179 
180  // extract GIDs, this array is filled
181  std::vector<GlobalOrdinalT> gids;
182  ugi.getElementGIDs(elements[e],gids);
183 
184  os << " local element id = " << elements[e] << ", ";
185 
186  os << " gids =";
187  for(std::size_t i=0;i<gids.size();i++)
188  os << " " << gids[i];
189 
190  os << ", lids =";
191  for(std::size_t i=0;i<gids.size();i++)
192  os << " " << lids[i];
193  os << std::endl;
194  }
195  }
196 }
197 
198 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
201 {
202  typedef Tpetra::Map<int,GlobalOrdinalT,Node> Map;
203  typedef Tpetra::Vector<int,int,GlobalOrdinalT,Node> IntVector;
204 
205  std::vector<GlobalOrdinalT> indices;
206  std::vector<std::string> blocks;
207 
208  ugi.getOwnedAndGhostedIndices(indices);
209  ugi.getElementBlockIds(blocks);
210 
211  std::vector<int> fieldNumbers(indices.size(),-1);
212 
213  Teuchos::RCP<Map> ghostedMap
214  = Teuchos::rcp(new Map(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(), Teuchos::arrayViewFromVector(indices),
216 
217  // build a map from local ids to a field number
218  for(std::size_t blk=0;blk<blocks.size();blk++) {
219  std::string blockId = blocks[blk];
220 
221  const std::vector<LocalOrdinalT> & elements = ugi.getElementBlock(blockId);
222  const std::vector<int> & fields = ugi.getBlockFieldNumbers(blockId);
223 
224  // loop over all elements, and set field number in output array
225  std::vector<GlobalOrdinalT> gids(fields.size());
226  for(std::size_t e=0;e<elements.size();e++) {
227  ugi.getElementGIDs(elements[e],gids);
228 
229  for(std::size_t f=0;f<fields.size();f++) {
230  int fieldNum = fields[f];
231  GlobalOrdinalT gid = gids[f];
232  std::size_t lid = ghostedMap->getLocalElement(gid); // hash table lookup
233 
234  fieldNumbers[lid] = fieldNum;
235  }
236  }
237  }
238 
239  // produce a reduced vector containing only fields known by this processor
240  std::vector<GlobalOrdinalT> reducedIndices;
241  std::vector<int> reducedFieldNumbers;
242  for(std::size_t i=0;i<fieldNumbers.size();i++) {
243  if(fieldNumbers[i]>-1) {
244  reducedIndices.push_back(indices[i]);
245  reducedFieldNumbers.push_back(fieldNumbers[i]);
246  }
247  }
248 
249  Teuchos::RCP<Map> reducedMap
250  = Teuchos::rcp(new Map(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(), Teuchos::arrayViewFromVector(reducedIndices),
252  return Teuchos::rcp(new IntVector(reducedMap,Teuchos::arrayViewFromVector(reducedFieldNumbers)));
253 }
254 
255 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
257  std::vector<int> & fieldNumbers,
258  const Teuchos::RCP<const Tpetra::Vector<int,int,GlobalOrdinalT,Node> > & reducedVec)
259 {
260  typedef Tpetra::Vector<int,int,GlobalOrdinalT,Node> IntVector;
261 
262  Teuchos::RCP<const IntVector> dest = buildGhostedFieldVector<LocalOrdinalT,GlobalOrdinalT,Node>(ugi,reducedVec);
263 
264  fieldNumbers.resize(dest->getLocalLength());
265  dest->get1dCopy(Teuchos::arrayViewFromVector(fieldNumbers));
266 }
267 
268 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
271  const Teuchos::RCP<const Tpetra::Vector<int,int,GlobalOrdinalT,Node> > & reducedVec)
272 {
273  typedef Tpetra::Map<int,GlobalOrdinalT,Node> Map;
274  typedef Tpetra::Vector<int,int,GlobalOrdinalT,Node> IntVector;
275  typedef Tpetra::Import<int,GlobalOrdinalT,Node> Importer;
276 
277  // first step: get a reduced field number vector and build a map to
278  // contain the full field number vector
280 
281  Teuchos::RCP<Map> destMap;
282  {
283  std::vector<GlobalOrdinalT> indices;
284  ugi.getOwnedAndGhostedIndices(indices);
285  destMap = Teuchos::rcp(new Map(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(), Teuchos::arrayViewFromVector(indices),
287  }
288 
289  Teuchos::RCP<const IntVector> source = reducedVec;
290  if(source==Teuchos::null)
291  source = buildGhostedFieldReducedVector<LocalOrdinalT,GlobalOrdinalT,Node>(ugi);
292  Teuchos::RCP<const Map> sourceMap = source->getMap();
293 
294  // second step: perform the global communciation required to fix the
295  // interface conditions (where this processor doesn't know what field
296  // some indices are)
298  Teuchos::RCP<IntVector> dest = Teuchos::rcp(new IntVector(destMap));
299  Importer importer(sourceMap,destMap);
300 
301  dest->doImport(*source,importer,Tpetra::INSERT);
302 
303  return dest;
304 }
305 
306 template <typename ScalarT,typename ArrayT,typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
307 void updateGhostedDataReducedVector(const std::string & fieldName,const std::string blockId,
309  const ArrayT & data,Tpetra::MultiVector<ScalarT,int,GlobalOrdinalT,Node> & dataVector)
310 {
311  typedef Tpetra::Map<int,GlobalOrdinalT,Node> Map;
312 
313  TEUCHOS_TEST_FOR_EXCEPTION(!ugi.fieldInBlock(fieldName,blockId),std::runtime_error,
314  "panzer::updateGhostedDataReducedVector: field name = \""+fieldName+"\" is not in element block = \"" +blockId +"\"!");
315 
316  Teuchos::RCP<const Map> dataMap = dataVector.getMap();
317 
318  int fieldNum = ugi.getFieldNum(fieldName);
319  const std::vector<LocalOrdinalT> & elements = ugi.getElementBlock(blockId);
320  const std::vector<int> & fieldOffsets = ugi.getGIDFieldOffsets(blockId,fieldNum);
321 
322  TEUCHOS_TEST_FOR_EXCEPTION(data.extent(0)!=elements.size(),std::runtime_error,
323  "panzer::updateGhostedDataReducedVector: data cell dimension does not match up with block cell count");
324 
325  int rank = data.rank();
326 
327  if(rank==2) {
328  // loop over elements distributing relevent data to vector
329  std::vector<GlobalOrdinalT> gids;
330  for(std::size_t e=0;e<elements.size();e++) {
331  ugi.getElementGIDs(elements[e],gids);
332 
333  for(std::size_t f=0;f<fieldOffsets.size();f++) {
334  std::size_t localIndex = dataMap->getLocalElement(gids[fieldOffsets[f]]); // hash table lookup
335  dataVector.replaceLocalValue(localIndex,0,data(e,f));
336  }
337  }
338  }
339  else if(rank==3) {
340  std::size_t entries = data.extent(2);
341 
342  TEUCHOS_TEST_FOR_EXCEPTION(dataVector.getNumVectors()!=entries,std::runtime_error,
343  "panzer::updateGhostedDataReducedVector: number of columns in data vector inconsistent with data array");
344 
345  // loop over elements distributing relevent data to vector
346  std::vector<GlobalOrdinalT> gids;
347  for(std::size_t e=0;e<elements.size();e++) {
348  ugi.getElementGIDs(elements[e],gids);
349 
350  for(std::size_t f=0;f<fieldOffsets.size();f++) {
351  std::size_t localIndex = dataMap->getLocalElement(gids[fieldOffsets[f]]); // hash table lookup
352  for(std::size_t v=0;v<entries;v++)
353  dataVector.replaceLocalValue(localIndex,v,data(e,f,v));
354  }
355  }
356  }
357  else
358  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
359  "panzer::updateGhostedDataReducedVector: data array rank must be 2 or 3");
360 }
361 
364 template <typename GlobalOrdinalT,typename Node>
366 getFieldMap(int fieldNum,const Tpetra::Vector<int,int,GlobalOrdinalT,Node> & fieldTVector)
367 {
368  Teuchos::RCP<const Tpetra::Map<int,GlobalOrdinalT,Node> > origMap = fieldTVector.getMap();
369  std::vector<int> fieldVector(fieldTVector.getLocalLength());
370  fieldTVector.get1dCopy(Teuchos::arrayViewFromVector(fieldVector));
371 
372  std::vector<GlobalOrdinalT> mapVector;
373  for(std::size_t i=0;i<fieldVector.size();i++) {
374  if(fieldVector[i]==fieldNum)
375  mapVector.push_back(origMap->getGlobalElement(i));
376  }
377 
379  = Teuchos::rcp(new Tpetra::Map<int,GlobalOrdinalT,Node>(
380  Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(), Teuchos::arrayViewFromVector(mapVector),
381  Teuchos::OrdinalTraits<GlobalOrdinalT>::zero(), origMap->getComm()));
382 
383  return finalMap;
384 }
385 
386 namespace orientation_helpers {
387 
388 template <typename GlobalOrdinalT>
389 void computeCellEdgeOrientations(const std::vector<std::pair<int,int> > & topEdgeIndices,
390  const std::vector<GlobalOrdinalT> & topology,
391  const FieldPattern & fieldPattern,
392  std::vector<signed char> & orientation)
393 {
394  // LOCAL element orientations are always set so that they flow in the positive
395  // direction along an edge from node 0 to node 1. As a result if the GID of
396  // node 0 is larger then node 1 then the GLOBAL orientation is -1 (and positive
397  // otherwise). The local definition of the edge direction is defined by
398  // the shards cell topology.
399 
400  TEUCHOS_ASSERT(orientation.size()==std::size_t(fieldPattern.numberIds()));
401 
402  int edgeDim = 1;
403 
404  for(std::size_t e=0;e<topEdgeIndices.size();e++) {
405  // grab topological nodes
406  const std::pair<int,int> nodes = topEdgeIndices[e];
407 
408  // extract global values of topological nodes
409  GlobalOrdinalT v0 = topology[nodes.first];
410  GlobalOrdinalT v1 = topology[nodes.second];
411 
412  // using simple rule make a decision about orientation
413  signed char edgeOrientation = 1;
414  if(v1>v0)
415  edgeOrientation = 1;
416  else if(v0>v1)
417  edgeOrientation = -1;
418  else
419  { TEUCHOS_ASSERT(false); }
420 
421  // grab edgeIndices to be set to compute orientation
422  const std::vector<int> & edgeIndices = fieldPattern.getSubcellIndices(edgeDim,e);
423  for(std::size_t s=0;s<edgeIndices.size();s++)
424  orientation[edgeIndices[s]] = edgeOrientation;
425  }
426 }
427 
428 template <typename GlobalOrdinalT>
429 void computeCellFaceOrientations(const std::vector<std::vector<int> > & topFaceIndices,
430  const std::vector<GlobalOrdinalT> & topology,
431  const FieldPattern & fieldPattern,
432  std::vector<signed char> & orientation)
433 {
434  // LOCAL element orientations are always set so that they flow in the positive
435  // direction away from the cell (counter clockwise rotation of the face). To determine
436  // the face orientation we use the fact that Shards (and thus the field pattern) always
437  // locally orders faces in a counter clockwise direction. A local rule for each element
438  // will take advantage of this ensuring both elements agree on the orientation. This rule
439  // is to first find the smallest node GID on the face. Then look at the GIDs of the nodes
440  // immediately preceding and following that one. If the node following has smaller GID than
441  // the preceding node then the face is oriented counter clockwise and thus the orientation
442  // is +1. If the node preceding is larger, then the orientation is clockwise and the set to
443  // a value of -1.
444 
445  // this only works for 3D field patterns
446  TEUCHOS_ASSERT(fieldPattern.getDimension()==3);
447 
448  TEUCHOS_ASSERT(orientation.size()==std::size_t(fieldPattern.numberIds()));
449 
450  int faceDim = 2;
451 
452  for(std::size_t f=0;f<topFaceIndices.size();f++) {
453  // grab topological nodes
454  const std::vector<int> & nodes = topFaceIndices[f];
455  std::vector<GlobalOrdinalT> globals(nodes.size());
456  for(std::size_t n=0;n<nodes.size();n++)
457  globals[n] = topology[nodes[n]];
458 
459  typename std::vector<GlobalOrdinalT>::const_iterator itr
460  = std::min_element(globals.begin(),globals.end());
461 
462  TEUCHOS_TEST_FOR_EXCEPTION(itr==globals.end(),std::out_of_range,
463  "panzer::orientation_helpers::computeCellFaceOrientations: A face index array "
464  "was empty.");
465 
466  // extract global values of topological nodes
467  // The face nodes go in counter clockwise order, let v_min be the
468  // value with the minimum element then
469  // vbefore => itr => vafter
470  // note that the nonsense with the beginning and end has to do with
471  // if this iterator was the first or last in the array
472  GlobalOrdinalT vbefore = itr==globals.begin() ? *(globals.end()-1) : *(itr-1);
473  GlobalOrdinalT vafter = (itr+1)==globals.end() ? *globals.begin() : *(itr+1);
474 
475 /*
476  // sanity check in debug mode (uncomment these lines)
477  TEUCHOS_ASSERT(std::find(globals.begin(),globals.end(),vbefore)!=globals.end());
478  TEUCHOS_ASSERT(std::find(globals.begin(),globals.end(),vafter)!=globals.end());
479 
480  // print out information about the found nodes and also what
481  // order they were in originally
482  std::cout << "\nFace Order = ";
483  for(std::size_t l=0;l<globals.size();l++)
484  std::cout << globals[l] << " ";
485  std::cout << std::endl;
486  std::cout << "(before,min,after) " << f << ": " << vbefore << " => " << *itr << " => " << vafter << std::endl;
487 */
488 
489  // note by assumption
490  // vbefore < *itr and *itr < vafter
491 
492  // Based on the next lowest global id starting from the minimum
493  signed char faceOrientation = 1;
494  if(vafter>vbefore) // means smaller in clockwise direction
495  faceOrientation = -1;
496  else if(vbefore>vafter) // means smaller in counter clockwise direction
497  faceOrientation = 1;
498  else
499  { TEUCHOS_ASSERT(false); } // we got an equality somehow!
500 
501  // grab faceIndices to be set to compute orientation
502  const std::vector<int> & faceIndices = fieldPattern.getSubcellIndices(faceDim,f);
503  for(std::size_t s=0;s<faceIndices.size();s++)
504  orientation[faceIndices[s]] = faceOrientation;
505  }
506 }
507 
508 } // end orientation helpers
509 
510 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
513  : ugi_(ugi)
514 {
515  gh_reducedFieldVector_ = buildGhostedFieldReducedVector<LocalOrdinalT,GlobalOrdinalT,Node>(*ugi_);
516  gh_fieldVector_ = buildGhostedFieldVector<LocalOrdinalT,GlobalOrdinalT,Node>(*ugi_,gh_reducedFieldVector_);
517 }
518 
519 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
520 template <typename ScalarT,typename ArrayT>
523  getGhostedDataVector(const std::string & fieldName,const std::map<std::string,ArrayT> & data) const
524 {
525  TEUCHOS_ASSERT(data.size()>0); // there must be at least one "data" item
526 
527  int fieldNum = ugi_->getFieldNum(fieldName);
528  std::vector<std::string> blockIds;
529  ugi_->getElementBlockIds(blockIds);
530 
531  // get rank of first data array, determine column count
532  int rank = data.begin()->second.rank();
533  int numCols = 0;
534  if(rank==2)
535  numCols = 1;
536  else if(rank==3)
537  numCols = data.begin()->second.extent(2);
538  else {
539  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,
540  "ArrayToFieldVector::getGhostedDataVector: data array must have rank 2 or 3. This array has rank " << rank << ".");
541  }
542 
543 
544  // first build and fill in final reduced field vector
546 
547  // build field maps as needed
548  Teuchos::RCP<const Map> reducedMap = gh_reducedFieldMaps_[fieldNum];
549  if(gh_reducedFieldMaps_[fieldNum]==Teuchos::null) {
550  reducedMap = panzer::getFieldMap(fieldNum,*gh_reducedFieldVector_);
551  gh_reducedFieldMaps_[fieldNum] = reducedMap;
552  }
553 
555  = Teuchos::rcp(new Tpetra::MultiVector<ScalarT,int,GlobalOrdinalT,Node>(reducedMap,numCols));
556  for(std::size_t b=0;b<blockIds.size();b++) {
557  std::string block = blockIds[b];
558 
559  // make sure field is in correct block
560  if(!ugi_->fieldInBlock(fieldName,block))
561  continue;
562 
563  // extract data vector
564  typename std::map<std::string,ArrayT>::const_iterator blockItr = data.find(block);
565  TEUCHOS_TEST_FOR_EXCEPTION(blockItr==data.end(),std::runtime_error,
566  "ArrayToFieldVector::getDataVector: can not find block \""+block+"\".");
567 
568  const ArrayT & d = blockItr->second;
569  updateGhostedDataReducedVector<ScalarT,ArrayT,LocalOrdinalT,GlobalOrdinalT,Node>(fieldName,block,*ugi_,d,*finalReducedVec);
570  }
571 
572  // build final (not reduced vector)
574 
575  Teuchos::RCP<const Map> map = gh_fieldMaps_[fieldNum];
576  if(gh_fieldMaps_[fieldNum]==Teuchos::null) {
577  map = panzer::getFieldMap(fieldNum,*gh_fieldVector_);
578  gh_fieldMaps_[fieldNum] = map;
579  }
580 
582  = Teuchos::rcp(new Tpetra::MultiVector<ScalarT,int,GlobalOrdinalT,Node>(map,numCols));
583 
584  // do import from finalReducedVec
585  Tpetra::Import<int,GlobalOrdinalT,Node> importer(reducedMap,map);
586  finalVec->doImport(*finalReducedVec,importer,Tpetra::INSERT);
587 
588  return finalVec;
589 }
590 
591 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
592 template <typename ScalarT,typename ArrayT>
595  getDataVector(const std::string & fieldName,const std::map<std::string,ArrayT> & data) const
596 {
597  // if neccessary build field vector
598  if(fieldVector_==Teuchos::null)
599  buildFieldVector(*gh_fieldVector_);
600 
602  = getGhostedDataVector<ScalarT,ArrayT>(fieldName,data);
603 
604  // use lazy construction for each field
605  int fieldNum = ugi_->getFieldNum(fieldName);
606  Teuchos::RCP<const Map> destMap = fieldMaps_[fieldNum];
607  if(fieldMaps_[fieldNum]==Teuchos::null) {
608  destMap = panzer::getFieldMap(fieldNum,*fieldVector_);
609  fieldMaps_[fieldNum] = destMap;
610  }
611 
613  = Teuchos::rcp(new Tpetra::MultiVector<ScalarT,int,GlobalOrdinalT,Node>(destMap,sourceVec->getNumVectors()));
614 
615  // do import
616  Tpetra::Import<int,GlobalOrdinalT> importer(sourceVec->getMap(),destMap);
617  destVec->doImport(*sourceVec,importer,Tpetra::INSERT);
618 
619  return destVec;
620 }
621 
622 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
624  buildFieldVector(const Tpetra::Vector<int,int,GlobalOrdinalT,Node> & source) const
625 {
626  // build (unghosted) vector and map
627  std::vector<GlobalOrdinalT> indices;
628  ugi_->getOwnedIndices(indices);
629 
631  = Teuchos::rcp(new Map(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(), Teuchos::arrayViewFromVector(indices),
633  Teuchos::RCP<IntVector> localFieldVector = Teuchos::rcp(new IntVector(destMap));
634 
635  Tpetra::Import<int,GlobalOrdinalT> importer(source.getMap(),destMap);
636  localFieldVector->doImport(source,importer,Tpetra::INSERT);
637 
638  fieldVector_ = localFieldVector;
639 }
640 
641 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
644 getFieldMap(const std::string & fieldName) const
645 {
646  return getFieldMap(ugi_->getFieldNum(fieldName));
647 }
648 
649 template <typename LocalOrdinalT,typename GlobalOrdinalT,typename Node>
652 getFieldMap(int fieldNum) const
653 {
654  if(fieldMaps_[fieldNum]==Teuchos::null) {
655  // if neccessary build field vector
656  if(fieldVector_==Teuchos::null)
657  buildFieldVector(*gh_fieldVector_);
658 
659  fieldMaps_[fieldNum] = panzer::getFieldMap(fieldNum,*fieldVector_);
660  }
661 
662  return fieldMaps_[fieldNum];
663 }
664 
665 } // end namspace panzer
virtual bool fieldInBlock(const std::string &field, const std::string &block) const =0
const Kokkos::View< const LocalOrdinalT *, Kokkos::LayoutRight, PHX::Device > getElementLIDs(LocalOrdinalT localElmtId) const
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.
int getFieldBlock(const std::string &fieldName, const std::vector< Teuchos::RCP< UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > > > &ugis)
virtual int getDimension() const =0
void computeCellEdgeOrientations(const std::vector< std::pair< int, int > > &topEdgeIndices, const std::vector< GlobalOrdinalT > &topology, const FieldPattern &fieldPattern, std::vector< signed char > &orientation)
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
void computeBlockOffsets(const std::string &blockId, const std::vector< Teuchos::RCP< UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > > > &ugis, std::vector< int > &blockOffsets)
Teuchos::RCP< Tpetra::MultiVector< ScalarT, int, GlobalOrdinalT, Node > > getGhostedDataVector(const std::string &fieldName, const std::map< std::string, ArrayT > &data) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void buildFieldVector(const Tpetra::Vector< int, int, GlobalOrdinalT, Node > &source) const
build unghosted field vector from ghosted field vector
Teuchos::RCP< const Tpetra::Map< int, GlobalOrdinalT, Node > > getFieldMap(const std::string &fieldName) const
virtual Teuchos::RCP< Teuchos::Comm< int > > getComm() const =0
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 int numberIds() const
Kokkos::View< const LO **, PHX::Device > lids
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)
std::vector< Teuchos::RCP< const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > > > nc2c_vector(const std::vector< Teuchos::RCP< UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > > > &ugis)
void updateGhostedDataReducedVector(const std::string &fieldName, const std::string blockId, const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi, const ArrayT &data, Tpetra::MultiVector< ScalarT, int, GlobalOrdinalT, Node > &dataVector)
Teuchos::RCP< const Tpetra::Vector< int, int, GlobalOrdinalT, Node > > buildGhostedFieldVector(const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi, const Teuchos::RCP< const Tpetra::Vector< int, int, GlobalOrdinalT, Node > > &reducedVec=Teuchos::null)
std::string printUGILoadBalancingInformation(const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi)
Teuchos::RCP< const IntVector > gh_fieldVector_
ghosted reduced field vector
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
void printMeshTopology(std::ostream &os, const panzer::UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi)
Teuchos::RCP< Tpetra::Vector< int, int, GlobalOrdinalT, Node > > buildGhostedFieldReducedVector(const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > &ugi)
void computeCellFaceOrientations(const std::vector< std::pair< int, int > > &topEdgeIndices, const std::vector< GlobalOrdinalT > &topology, const FieldPattern &fieldPattern, std::vector< signed char > &orientation)
Teuchos::RCP< const UniqueGlobalIndexer< LocalOrdinalT, GlobalOrdinalT > > ugi_
DOF mapping.
virtual int getFieldNum(const std::string &str) const =0
Get the number used for access to this field.
Tpetra::Map< int, GlobalOrdinalT, Node > Map
virtual const std::vector< int > & getSubcellIndices(int dim, int cellIndex) const =0
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)
virtual void getOwnedIndices(std::vector< GlobalOrdinalT > &indices) const =0
Get the set of indices owned by this processor.
Teuchos::RCP< const IntVector > gh_reducedFieldVector_
Teuchos::RCP< Tpetra::MultiVector< ScalarT, int, GlobalOrdinalT, Node > > getDataVector(const std::string &fieldName, const std::map< std::string, ArrayT > &data) const
Tpetra::Vector< int, int, GlobalOrdinalT, Node > IntVector
ArrayToFieldVector()
Maps for each field (as needed)