Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ReorderADValues_Evaluator_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_ReorderADValues_Evaluator_impl_hpp__
44 #define __Panzer_ReorderADValues_Evaluator_impl_hpp__
45 
46 
47 #include "Teuchos_RCP.hpp"
48 #include "Teuchos_Assert.hpp"
49 #include "Teuchos_FancyOStream.hpp"
50 
51 #include "Panzer_GlobalIndexer.hpp"
52 
53 #include "Phalanx_DataLayout.hpp"
54 
55 template<typename EvalT,typename TRAITS>
57 ReorderADValues_Evaluator(const std::string & outPrefix,
58  const std::vector<std::string> & inFieldNames,
59  const std::vector<Teuchos::RCP<PHX::DataLayout> > & fieldLayouts,
60  const std::string & /* elementBlock */,
61  const GlobalIndexer & /* indexerSrc */,
62  const GlobalIndexer & /* indexerDest */)
63 {
64  TEUCHOS_ASSERT(inFieldNames.size()==fieldLayouts.size());
65 
66  // build the vector of fields that this is dependent on
67  for (std::size_t eq = 0; eq < inFieldNames.size(); ++eq) {
68  inFields_.push_back(PHX::MDField<const ScalarT>(inFieldNames[eq],fieldLayouts[eq]));
69  outFields_.push_back(PHX::MDField<ScalarT>(outPrefix+inFieldNames[eq],fieldLayouts[eq]));
70 
71  // tell the field manager that we depend on this field
72  this->addDependentField(inFields_[eq]);
73  this->addEvaluatedField(outFields_[eq]);
74  }
75 
76  this->setName(outPrefix+" Reorder AD Values");
77 }
78 
79 // **********************************************************************
80 template<typename EvalT,typename TRAITS>
82 ReorderADValues_Evaluator(const std::string & outPrefix,
83  const std::vector<std::string> & inFieldNames,
84  const std::vector<std::string> & inDOFs,
85  const std::vector<std::string> & outDOFs,
86  const std::vector<Teuchos::RCP<PHX::DataLayout> > & fieldLayouts,
87  const std::string & /* elementBlock */,
88  const GlobalIndexer & /* indexerSrc */,
89  const GlobalIndexer & /* indexerDest */)
90 {
91  TEUCHOS_ASSERT(inFieldNames.size()==fieldLayouts.size());
92  TEUCHOS_ASSERT(inDOFs.size()==outDOFs.size());
93 
94  // build the vector of fields that this is dependent on
95  for (std::size_t eq = 0; eq < inFieldNames.size(); ++eq) {
96  inFields_.push_back(PHX::MDField<const ScalarT>(inFieldNames[eq],fieldLayouts[eq]));
97  outFields_.push_back(PHX::MDField<ScalarT>(outPrefix+inFieldNames[eq],fieldLayouts[eq]));
98 
99  // tell the field manager that we depend on this field
100  this->addDependentField(inFields_[eq]);
101  this->addEvaluatedField(outFields_[eq]);
102  }
103 
104  this->setName("Reorder AD Values");
105 }
106 
107 // **********************************************************************
108 template<typename EvalT,typename TRAITS>
110 evaluateFields(typename TRAITS::EvalData /* workset */)
111 {
112  for(std::size_t i = 0; i < inFields_.size(); ++i)
113  outFields_[i].deep_copy(inFields_[i]);
114 }
115 
116 // **********************************************************************
117 // Jacobian
118 // **********************************************************************
119 
120 template<typename TRAITS>
122 ReorderADValues_Evaluator(const std::string & outPrefix,
123  const std::vector<std::string> & inFieldNames,
124  const std::vector<Teuchos::RCP<PHX::DataLayout> > & fieldLayouts,
125  const std::string & elementBlock,
126  const GlobalIndexer & indexerSrc,
127  const GlobalIndexer & indexerDest)
128 {
129  TEUCHOS_ASSERT(inFieldNames.size()==fieldLayouts.size());
130 
131  // build the vector of fields that this is dependent on
132  inFields_.resize(inFieldNames.size());
133  outFields_.resize(inFieldNames.size());
134  for (std::size_t eq = 0; eq < inFieldNames.size(); ++eq) {
135  inFields_[eq] = PHX::MDField<const ScalarT>(inFieldNames[eq],fieldLayouts[eq]);
136  outFields_[eq] = PHX::MDField<ScalarT>(outPrefix+inFieldNames[eq],fieldLayouts[eq]);
137 
138  // tell the field manager that we depend on this field
139  this->addDependentField(inFields_[eq]);
140  this->addEvaluatedField(outFields_[eq]);
141  }
142 
143  buildSrcToDestMap(elementBlock,
144  indexerSrc,
145  indexerDest);
146 
147  this->setName(outPrefix+" Reorder AD Values");
148 }
149 
150 // **********************************************************************
151 
152 template<typename TRAITS>
154 ReorderADValues_Evaluator(const std::string & outPrefix,
155  const std::vector<std::string> & inFieldNames,
156  const std::vector<std::string> & inDOFs,
157  const std::vector<std::string> & outDOFs,
158  const std::vector<Teuchos::RCP<PHX::DataLayout> > & fieldLayouts,
159  const std::string & elementBlock,
160  const GlobalIndexer & indexerSrc,
161  const GlobalIndexer & indexerDest)
162 {
163  TEUCHOS_ASSERT(inFieldNames.size()==fieldLayouts.size());
164  TEUCHOS_ASSERT(inDOFs.size()==outDOFs.size());
165 
166  // build the vector of fields that this is dependent on
167  std::map<int,int> fieldNumberMaps;
168  for (std::size_t eq = 0; eq < inFieldNames.size(); ++eq) {
169  inFields_.push_back(PHX::MDField<const ScalarT>(inFieldNames[eq],fieldLayouts[eq]));
170  outFields_.push_back(PHX::MDField<ScalarT>(outPrefix+inFieldNames[eq],fieldLayouts[eq]));
171 
172  // tell the field manager that we depend on this field
173  this->addDependentField(inFields_[eq]);
174  this->addEvaluatedField(outFields_[eq]);
175  // Don't share so we can avoid zeroing out off blck Jacobian entries
176  this->addUnsharedField(outFields_[eq].fieldTag().clone());
177  }
178 
179  // build a int-int map that associates fields
180  for(std::size_t i=0;i<inDOFs.size();i++) {
181  int srcFieldNum = indexerSrc.getFieldNum(inDOFs[i]);
182  int dstFieldNum = indexerDest.getFieldNum(outDOFs[i]);
183  TEUCHOS_ASSERT(srcFieldNum>=0);
184  TEUCHOS_ASSERT(dstFieldNum>=0);
185 
186  fieldNumberMaps[srcFieldNum] = dstFieldNum;
187  }
188 
189  buildSrcToDestMap(elementBlock,
190  fieldNumberMaps,
191  indexerSrc,
192  indexerDest);
193 
194  this->setName("Reorder AD Values");
195 }
196 
197 // **********************************************************************
198 template<typename TRAITS>
200 evaluateFields(typename TRAITS::EvalData workset)
201 {
202  // for AD data do a reordering
203  for(std::size_t fieldIndex = 0; fieldIndex < inFields_.size(); ++fieldIndex) {
204 
205  const auto & inField_v = inFields_[fieldIndex].get_view();
206  const auto & outField_v = outFields_[fieldIndex].get_view();
207  const auto & dstFromSrcMap_v = dstFromSrcMapView_;
208 
209  if(inField_v.size()>0) {
210 
211  const auto rank = inField_v.rank();
212  if (rank==1) {
213  Kokkos::parallel_for("ReorderADValues: Jacobian rank 2",workset.num_cells,KOKKOS_LAMBDA(const int& i){
214  outField_v(i).val() = inField_v(i).val();
215  for (size_t dx = 0; dx < dstFromSrcMap_v.size(); ++dx)
216  outField_v(i).fastAccessDx(dx) = inField_v(i).fastAccessDx(dstFromSrcMap_v(dx));
217  });
218  }
219  else if (rank==2) {
220  Kokkos::MDRangePolicy<PHX::Device,Kokkos::Rank<2>> policy({0,0},{static_cast<int64_t>(workset.num_cells),static_cast<int64_t>(inField_v.extent(1))});
221  Kokkos::parallel_for("ReorderADValues: Jacobian rank 2",policy,KOKKOS_LAMBDA(const int& i, const int& j){
222  outField_v(i,j).val() = inField_v(i,j).val();
223  for (size_t dx = 0; dx < dstFromSrcMap_v.size(); ++dx)
224  outField_v(i,j).fastAccessDx(dx) = inField_v(i,j).fastAccessDx(dstFromSrcMap_v(dx));
225  });
226  }
227  else if (rank==3) {
228  Kokkos::MDRangePolicy<PHX::Device,Kokkos::Rank<3>> policy({0,0,0},{static_cast<int64_t>(workset.num_cells),
229  static_cast<int64_t>(inField_v.extent(1)),static_cast<int64_t>(inField_v.extent(2))});
230  Kokkos::parallel_for("ReorderADValues: Jacobian rank 2",policy,KOKKOS_LAMBDA(const int& i, const int& j, const int& k){
231  outField_v(i,j,k).val() = inField_v(i,j,k).val();
232  for (size_t dx = 0; dx < dstFromSrcMap_v.size(); ++dx)
233  outField_v(i,j,k).fastAccessDx(dx) = inField_v(i,j,k).fastAccessDx(dstFromSrcMap_v(dx));
234  });
235  }
236  else if (rank==4) {
237  Kokkos::MDRangePolicy<PHX::Device,Kokkos::Rank<4>> policy({0,0,0,0},{static_cast<int64_t>(workset.num_cells),
238  static_cast<int64_t>(inField_v.extent(1)),static_cast<int64_t>(inField_v.extent(2)),
239  static_cast<int64_t>(inField_v.extent(3))});
240  Kokkos::parallel_for("ReorderADValues: Jacobian rank 2",policy,KOKKOS_LAMBDA(const int& i, const int& j, const int& k, const int& l){
241  outField_v(i,j,k,l).val() = inField_v(i,j,k,l).val();
242  for (size_t dx = 0; dx < dstFromSrcMap_v.size(); ++dx)
243  outField_v(i,j,k,l).fastAccessDx(dx) = inField_v(i,j,k,l).fastAccessDx(dstFromSrcMap_v(dx));
244  });
245  }
246  else if (rank==5) {
247  Kokkos::MDRangePolicy<PHX::Device,Kokkos::Rank<5>> policy({0,0,0,0,0},{static_cast<int64_t>(workset.num_cells),
248  static_cast<int64_t>(inField_v.extent(1)),static_cast<int64_t>(inField_v.extent(2)),
249  static_cast<int64_t>(inField_v.extent(3)),static_cast<int64_t>(inField_v.extent(4))});
250  Kokkos::parallel_for("ReorderADValues: Jacobian rank 2",policy,KOKKOS_LAMBDA(const int& i, const int& j, const int& k, const int& l, const int& m){
251  outField_v(i,j,k,l,m).val() = inField_v(i,j,k,l,m).val();
252  for (size_t dx = 0; dx < dstFromSrcMap_v.size(); ++dx)
253  outField_v(i,j,k,l,m).fastAccessDx(dx) = inField_v(i,j,k,l,m).fastAccessDx(dstFromSrcMap_v(dx));
254  });
255  }
256  else {
257  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,"ERROR AD Reorder, rank size " << rank << " not supported!");
258  }
259  }
260  }
261 }
262 
263 // **********************************************************************
264 template<typename TRAITS>
266 buildSrcToDestMap(const std::string & elementBlock,
267  const GlobalIndexer & indexerSrc,
268  const GlobalIndexer & indexerDest)
269 {
270  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
271  out.setOutputToRootOnly(0);
272 
273  TEUCHOS_ASSERT(indexerSrc.getComm()!=Teuchos::null);
274  TEUCHOS_ASSERT(indexerDest.getComm()!=Teuchos::null);
275 
276  const std::vector<int> & dstFieldsNum = indexerDest.getBlockFieldNumbers(elementBlock);
277 
278  // build a map between destination field numbers and source field numbers
279  std::map<int,int> fieldNumberMaps;
280  for(std::size_t i=0;i<dstFieldsNum.size();i++) {
281  std::string fieldName = indexerDest.getFieldString(dstFieldsNum[i]);
282 
283  int srcFieldNum = indexerSrc.getFieldNum(fieldName);
284  if(srcFieldNum>=0)
285  fieldNumberMaps[srcFieldNum] = dstFieldsNum[i];
286  else
287  out << "Warning: Reorder AD Values can't find field \"" << fieldName << "\"" << std::endl;
288  }
289 
290  buildSrcToDestMap(elementBlock,fieldNumberMaps,indexerSrc,indexerDest);
291 }
292 
293 // **********************************************************************
294 template<typename TRAITS>
296 buildSrcToDestMap(const std::string & elementBlock,
297  const std::map<int,int> & fieldNumberMaps,
298  const GlobalIndexer & indexerSrc,
299  const GlobalIndexer & indexerDest)
300 {
301  int maxDest = -1;
302  std::map<int,int> offsetMap; // map from source to destination offsets
303  for(std::map<int,int>::const_iterator itr=fieldNumberMaps.begin();
304  itr!=fieldNumberMaps.end();++itr) {
305  int srcField = itr->first;
306  int dstField = itr->second;
307 
308  const std::vector<int> & srcOffsets = indexerSrc.getGIDFieldOffsets(elementBlock,srcField);
309  const std::vector<int> & dstOffsets = indexerDest.getGIDFieldOffsets(elementBlock,dstField);
310 
311  // field should be the same size
312  TEUCHOS_ASSERT(srcOffsets.size()==dstOffsets.size());
313  for(std::size_t i=0;i<srcOffsets.size();i++) {
314  offsetMap[srcOffsets[i]] = dstOffsets[i];
315 
316  // provides a size for allocating an array below: we will be able
317  // to index into dstFromSrcMap_ in a simple way
318  maxDest = dstOffsets[i]>maxDest ? dstOffsets[i] : maxDest;
319  }
320  }
321 
322  // Build map
323  TEUCHOS_ASSERT(maxDest>0);
324  std::vector<int> dstFromSrcMap(maxDest+1,-1);
325  for(std::map<int,int>::const_iterator itr=offsetMap.begin();
326  itr!=offsetMap.end();++itr) {
327  dstFromSrcMap[itr->second] = itr->first;
328  }
329 
330  dstFromSrcMapView_ = Kokkos::View<int*>("dstFromSrcMapView_",dstFromSrcMap.size());
331  auto dfsm_host = Kokkos::create_mirror_view(Kokkos::HostSpace(),dstFromSrcMapView_);
332  for (size_t i=0; i < dstFromSrcMapView_.size(); ++i)
333  dfsm_host(i) = dstFromSrcMap[i];
334 
335  Kokkos::deep_copy(dstFromSrcMapView_,dfsm_host);
336 }
337 
338 // **********************************************************************
339 
340 #endif
virtual const std::string & getFieldString(int num) const =0
Reverse lookup of the field string from a field number.
virtual Teuchos::RCP< Teuchos::Comm< int > > getComm() const =0
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::vector< PHX::MDField< ScalarT > > outFields_
std::vector< PHX::MDField< const ScalarT > > inFields_
virtual int getFieldNum(const std::string &str) const =0
Get the number used for access to this field.
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Reorders the ad values of a specified field to match a different unique global indexer.
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 const std::vector< int > & getBlockFieldNumbers(const std::string &blockId) const =0
ReorderADValues_Evaluator(const std::string &outPrefix, const std::vector< std::string > &inFieldNames, const std::vector< Teuchos::RCP< PHX::DataLayout > > &fieldLayouts, const std::string &elementBlock, const GlobalIndexer &indexerSrc, const GlobalIndexer &indexerDest)
#define TEUCHOS_ASSERT(assertion_test)