Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterResidual_EpetraSG_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_SCATTER_RESIDUAL_EPETRA_SG_IMPL_HPP
44 #define PANZER_SCATTER_RESIDUAL_EPETRA_SG_IMPL_HPP
45 
46 #include "Panzer_config.hpp"
47 #ifdef HAVE_STOKHOS
48 
51 #include "Phalanx_DataLayout_MDALayout.hpp"
52 
53 #include "Epetra_Vector.h"
54 #include "Epetra_Map.h"
55 #include "Epetra_CrsMatrix.h"
56 
57 // **********************************************************************
58 // Specialization: SGResidual
59 // **********************************************************************
60 
61 template<typename TRAITS,typename LO,typename GO>
64  const Teuchos::RCP<const panzer::UniqueGlobalIndexer<LO,GO> > & cIndexer,
65  const Teuchos::ParameterList& p,bool useDiscreteAdjoint)
66  : globalIndexer_(indexer)
67  , globalDataKey_("Residual Scatter Container")
68  , useDiscreteAdjoint_(useDiscreteAdjoint)
69 {
70  TEUCHOS_ASSERT(cIndexer==Teuchos::null);
71 
72  std::string scatterName = p.get<std::string>("Scatter Name");
73  scatterHolder_ =
74  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
75 
76  // get names to be evaluated
77  const std::vector<std::string>& names =
78  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
79 
80  // grab map from evaluated names to field names
81  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
82 
84  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
85 
86  // build the vector of fields that this is dependent on
87  scatterFields_.resize(names.size());
88  for (std::size_t eq = 0; eq < names.size(); ++eq) {
89  scatterFields_[eq] = PHX::MDField<ScalarT,Cell,NODE>(names[eq],dl);
90 
91  // tell the field manager that we depend on this field
92  this->addDependentField(scatterFields_[eq]);
93  }
94 
95  // this is what this evaluator provides
96  this->addEvaluatedField(*scatterHolder_);
97 
98  if (p.isType<std::string>("Global Data Key"))
99  globalDataKey_ = p.get<std::string>("Global Data Key");
100 
101  this->setName(scatterName+" Scatter Residual (SGResidual)");
102 }
103 
104 // **********************************************************************
105 template<typename TRAITS,typename LO,typename GO>
107 preEvaluate(typename TRAITS::PreEvalData d)
108 {
109  // extract linear object container
110  sgEpetraContainer_ = Teuchos::rcp_dynamic_cast<SGEpetraLinearObjContainer>(d.gedc.getDataObject(globalDataKey_));
111 
112  TEUCHOS_ASSERT(sgEpetraContainer_!=Teuchos::null);
113 }
114 
115 // **********************************************************************
116 template<typename TRAITS,typename LO,typename GO>
118 postRegistrationSetup(typename TRAITS::SetupData d,
120 {
121  fieldIds_.resize(scatterFields_.size());
122  // load required field numbers for fast use
123  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
124  // get field ID from DOF manager
125  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
126  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
127 
128  // fill field data object
129  this->utils.setFieldData(scatterFields_[fd],fm);
130  }
131 }
132 
133 // **********************************************************************
134 template<typename TRAITS,typename LO,typename GO>
136 evaluateFields(typename TRAITS::EvalData workset)
137 {
138  std::vector<GO> GIDs;
139  std::vector<int> LIDs;
140 
141  // for convenience pull out some objects from workset
142  std::string blockId = this->wda(workset).block_id;
143  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
144 
145  Teuchos::RCP<SGEpetraLinearObjContainer> sgEpetraContainer = sgEpetraContainer_;
146  Teuchos::RCP<Epetra_Vector> r_template = (*sgEpetraContainer->begin())->get_f();
147  const Epetra_BlockMap & map = r_template->Map();
148 
149  // NOTE: A reordering of these loops will likely improve performance
150  // The "getGIDFieldOffsets may be expensive. However the
151  // "getElementGIDs" can be cheaper. However the lookup for LIDs
152  // may be more expensive!
153 
154  // scatter operation for each cell in workset
155  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
156  std::size_t cellLocalId = localCellIds[worksetCellIndex];
157 
158  globalIndexer_->getElementGIDs(cellLocalId,GIDs,blockId);
159 
160  // caculate the local IDs for this element
161  LIDs.resize(GIDs.size());
162  for(std::size_t i=0;i<GIDs.size();i++)
163  LIDs[i] = map.LID(GIDs[i]);
164 
165  // loop over each field to be scattered
166  for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
167  int fieldNum = fieldIds_[fieldIndex];
168  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
169 
170  // loop over basis functions
171  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
172  int offset = elmtOffset[basis];
173  int lid = LIDs[offset];
174 
175  const ScalarT field = (scatterFields_[fieldIndex])(worksetCellIndex,basis);
176 
177  // loop over stochastic basis scatter field values to residual vectors
178  int stochIndex = 0;
180  for(itr=sgEpetraContainer->begin();itr!=sgEpetraContainer->end();++itr,++stochIndex)
181  (*(*itr)->get_f())[lid] += field.coeff(stochIndex);
182  }
183  }
184  }
185 }
186 
187 // **********************************************************************
188 // Specialization: SGJacobian
189 // **********************************************************************
190 
191 template<typename TRAITS,typename LO,typename GO>
194  const Teuchos::RCP<const panzer::UniqueGlobalIndexer<LO,GO> > & cIndexer,
195  const Teuchos::ParameterList& p,bool useDiscreteAdjoint)
196  : globalIndexer_(indexer)
197  , globalDataKey_("Residual Scatter Container")
198  , useDiscreteAdjoint_(useDiscreteAdjoint)
199 {
200  TEUCHOS_ASSERT(cIndexer==Teuchos::null);
201 
202  std::string scatterName = p.get<std::string>("Scatter Name");
203  scatterHolder_ =
204  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
205 
206  // get names to be evaluated
207  const std::vector<std::string>& names =
208  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
209 
210  // grab map from evaluated names to field names
211  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
212 
214  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
215 
216  // build the vector of fields that this is dependent on
217  scatterFields_.resize(names.size());
218  for (std::size_t eq = 0; eq < names.size(); ++eq) {
219  scatterFields_[eq] = PHX::MDField<ScalarT,Cell,NODE>(names[eq],dl);
220 
221  // tell the field manager that we depend on this field
222  this->addDependentField(scatterFields_[eq]);
223  }
224 
225  // this is what this evaluator provides
226  this->addEvaluatedField(*scatterHolder_);
227 
228  if (p.isType<std::string>("Global Data Key"))
229  globalDataKey_ = p.get<std::string>("Global Data Key");
230  if (p.isType<bool>("Use Discrete Adjoint"))
231  useDiscreteAdjoint = p.get<bool>("Use Discrete Adjoint");
232 
233  TEUCHOS_ASSERT(cIndexer==Teuchos::null); // SG does not work with a cIndexer!
234 
235  // discrete adjoint does not work with non-square matrices
236  if(useDiscreteAdjoint)
237  { TEUCHOS_ASSERT(cIndexer==Teuchos::null); }
238 
239  this->setName(scatterName+" Scatter Residual (SGJacobian)");
240 }
241 
242 // **********************************************************************
243 template<typename TRAITS,typename LO,typename GO>
245 preEvaluate(typename TRAITS::PreEvalData d)
246 {
247  // extract linear object container
248  sgEpetraContainer_ = Teuchos::rcp_dynamic_cast<SGEpetraLinearObjContainer>(d.gedc.getDataObject(globalDataKey_));
249 
250  TEUCHOS_ASSERT(sgEpetraContainer_!=Teuchos::null);
251 }
252 
253 // **********************************************************************
254 template<typename TRAITS,typename LO,typename GO>
256 postRegistrationSetup(typename TRAITS::SetupData d,
258 {
259  fieldIds_.resize(scatterFields_.size());
260  // load required field numbers for fast use
261  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
262  // get field ID from DOF manager
263  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
264  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
265 
266  // fill field data object
267  this->utils.setFieldData(scatterFields_[fd],fm);
268  }
269 }
270 
271 // **********************************************************************
272 template<typename TRAITS,typename LO,typename GO>
274 evaluateFields(typename TRAITS::EvalData workset)
275 {
276  std::vector<int> rLIDs, cLIDs;
277  std::vector<double> jacRow;
278 
279  // for convenience pull out some objects from workset
280  std::string blockId = this->wda(workset).block_id;
281  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
282 
283  Teuchos::RCP<SGEpetraLinearObjContainer> sgEpetraContainer = sgEpetraContainer_;
284  Teuchos::RCP<Epetra_CrsMatrix> Jac_template = (*sgEpetraContainer->begin())->get_A();
285 
286  // NOTE: A reordering of these loops will likely improve performance
287  // The "getGIDFieldOffsets" may be expensive. However the
288  // "getElementGIDs" can be cheaper. However the lookup for LIDs
289  // may be more expensive!
290 
291  // scatter operation for each cell in workset
292  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
293  std::size_t cellLocalId = localCellIds[worksetCellIndex];
294 
295  rLIDs = globalIndexer_->getElementLIDs(cellLocalId);
296  cLIDs = rLIDs;
297 
298  // loop over each field to be scattered
299  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
300  int fieldNum = fieldIds_[fieldIndex];
301  const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
302 
303  // loop over the basis functions (currently they are nodes)
304  for(std::size_t rowBasisNum = 0; rowBasisNum < elmtOffset.size(); rowBasisNum++) {
305  const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,rowBasisNum);
306  int rowOffset = elmtOffset[rowBasisNum];
307  int row = rLIDs[rowOffset];
308 
309  // loop over stochastic basis scatter field values to residual vectors
310  int stochIndex = 0;
312  for(itr=sgEpetraContainer->begin();itr!=sgEpetraContainer->end();++itr,++stochIndex) {
313  Teuchos::RCP<Epetra_Vector> r = (*itr)->get_f();
314  Teuchos::RCP<Epetra_CrsMatrix> Jac = (*itr)->get_A();
315 
316  // Sum residual
317  if(r!=Teuchos::null)
318  r->SumIntoMyValue(row,0,scatterField.val().coeff(stochIndex));
319 
320  // loop over the sensitivity indices: all DOFs on a cell
321  jacRow.resize(scatterField.size());
322 
323  if(useDiscreteAdjoint_) {
324  // loop over the sensitivity indices: all DOFs on a cell
325  jacRow.resize(scatterField.size());
326 
327  for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
328  jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex).coeff(stochIndex);
329 
330  int err = 0;
331  for(std::size_t c=0;c<cLIDs.size();c++)
332  err += std::abs(Jac->SumIntoMyValues(cLIDs[c], 1, &jacRow[c],&row));
333  TEUCHOS_ASSERT_EQUALITY(err,0); // do the check only once!
334  }
335  else {
336  for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
337  jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex).coeff(stochIndex);
338 
339  // Sum SGJacobian
340  int err = Jac->SumIntoMyValues(row, scatterField.size(), &jacRow[0],
341  panzer::ptrFromStlVector(cLIDs));
343  }
344  }
345  } // end rowBasisNum
346  } // end fieldIndex
347  }
348 }
349 
350 // **********************************************************************
351 
352 #endif
353 
354 #endif
std::vector< PHX::MDField< const ScalarT, panzer::Cell, panzer::Point > > scatterFields_
T & get(const std::string &name, T def_value)
PHX::MDField< ScalarT, Cell, IP > field
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
T * ptrFromStlVector(std::vector< T > &v)
Pushes residual values into the residual vector for a Newton-based solve.
int LID(int GID) const
int SumIntoMyValues(int MyRow, int NumEntries, const double *Values, const int *Indices)
Teuchos::RCP< const panzer::PureBasis > basis
Interpolates basis DOF values to IP DOF values.
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)