Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterDirichletResidual_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_DIRICHLET_RESIDUAL_EPETRA_SG_IMPL_HPP
44 #define PANZER_SCATTER_DIRICHLET_RESIDUAL_EPETRA_SG_IMPL_HPP
45 
46 #include "Panzer_config.hpp"
47 #ifdef HAVE_STOKHOS
48 
50 #include "Phalanx_DataLayout_MDALayout.hpp"
51 
52 // **********************************************************************
53 // Specialization: SGResidual
54 // **********************************************************************
55 
56 template<typename TRAITS,typename LO,typename GO>
59  const Teuchos::ParameterList& p)
60  : globalIndexer_(indexer)
61  , globalDataKey_("Residual Scatter Container")
62 {
63  std::string scatterName = p.get<std::string>("Scatter Name");
64  scatterHolder_ =
65  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
66 
67  // get names to be evaluated
68  const std::vector<std::string>& names =
69  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
70 
71  // grab map from evaluated names to field names
72  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
73 
75  p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional;
76 
77  side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
78  local_side_id_ = p.get<int>("Local Side ID");
79 
80 
81  // build the vector of fields that this is dependent on
82  scatterFields_.resize(names.size());
83  for (std::size_t eq = 0; eq < names.size(); ++eq) {
84  scatterFields_[eq] = PHX::MDField<ScalarT,Cell,NODE>(names[eq],dl);
85 
86  // tell the field manager that we depend on this field
87  this->addDependentField(scatterFields_[eq]);
88  }
89 
90  // this is what this evaluator provides
91  this->addEvaluatedField(*scatterHolder_);
92 
93  if (p.isType<std::string>("Global Data Key"))
94  globalDataKey_ = p.get<std::string>("Global Data Key");
95 
96  this->setName(scatterName+" Scatter Residual (SGResidual)");
97 }
98 
99 // **********************************************************************
100 template<typename TRAITS,typename LO,typename GO>
102 postRegistrationSetup(typename TRAITS::SetupData d,
104 {
105  fieldIds_.resize(scatterFields_.size());
106 
107  // load required field numbers for fast use
108  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
109  // get field ID from DOF manager
110  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
111  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
112 
113  // fill field data object
114  this->utils.setFieldData(scatterFields_[fd],fm);
115  }
116 
117  // get the number of nodes (Should be renamed basis)
118  num_nodes = scatterFields_[0].dimension(1);
119 }
120 
121 // **********************************************************************
122 template<typename TRAITS,typename LO,typename GO>
124 preEvaluate(typename TRAITS::PreEvalData d)
125 {
126  // extract dirichlet counter from container
128  = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc.getDataObject("Dirichlet Counter"),true);
129 
130  dirichletCounter_ = epetraContainer->get_f();
131  TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
132 
133  // extract linear object container
134  sgEpetraContainer_ = Teuchos::rcp_dynamic_cast<SGEpetraLinearObjContainer>(d.gedc.getDataObject(globalDataKey_));
135 }
136 
137 // **********************************************************************
138 template<typename TRAITS,typename LO,typename GO>
140 evaluateFields(typename TRAITS::EvalData workset)
141 {
142  std::vector<GO> GIDs;
143  std::vector<int> LIDs;
144 
145  // for convenience pull out some objects from workset
146  std::string blockId = this->wda(workset).block_id;
147  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
148 
149  Teuchos::RCP<Epetra_Vector> r_template = (*sgEpetraContainer_->begin())->get_f();
150  const Epetra_BlockMap & map = r_template->Map();
151 
152  // NOTE: A reordering of these loops will likely improve performance
153  // The "getGIDFieldOffsets may be expensive. However the
154  // "getElementGIDs" can be cheaper. However the lookup for LIDs
155  // may be more expensive!
156 
157  // scatter operation for each cell in workset
158  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
159  std::size_t cellLocalId = localCellIds[worksetCellIndex];
160 
161  globalIndexer_->getElementGIDs(cellLocalId,GIDs);
162 
163  // caculate the local IDs for this element
164  LIDs.resize(GIDs.size());
165  for(std::size_t i=0;i<GIDs.size();i++)
166  LIDs[i] = map.LID(GIDs[i]);
167 
168  std::vector<bool> is_owned(GIDs.size(), false);
169  globalIndexer_->ownedIndices(GIDs,is_owned);
170 
171  // loop over each field to be scattered
172  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
173  int fieldNum = fieldIds_[fieldIndex];
174 
175  // this call "should" get the right ordering according to the Intrepid basis
176  const std::pair<std::vector<int>,std::vector<int> > & indicePair
177  = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
178  const std::vector<int> & elmtOffset = indicePair.first;
179  const std::vector<int> & basisIdMap = indicePair.second;
180 
181  // loop over basis functions
182  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
183  int offset = elmtOffset[basis];
184  int lid = LIDs[offset];
185  if(lid<0) // not on this processor!
186  continue;
187 
188  int basisId = basisIdMap[basis];
189  const ScalarT field = (scatterFields_[fieldIndex])(worksetCellIndex,basisId);
190 
191  // loop over stochastic basis scatter field values to residual vectors
192  int stochIndex = 0;
194  for(itr=sgEpetraContainer_->begin();itr!=sgEpetraContainer_->end();++itr,++stochIndex)
195  (*(*itr)->get_f())[lid] = field.coeff(stochIndex);
196 
197  // dirichlet condition application
198  (*dirichletCounter_)[lid] = 1.0;
199  }
200  }
201  }
202 }
203 
204 // **********************************************************************
205 // Specialization: SGJacobian
206 // **********************************************************************
207 
208 template<typename TRAITS,typename LO,typename GO>
211  const Teuchos::ParameterList& p)
212  : globalIndexer_(indexer)
213  , globalDataKey_("Residual Scatter Container")
214 {
215  std::string scatterName = p.get<std::string>("Scatter Name");
216  scatterHolder_ =
217  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
218 
219  // get names to be evaluated
220  const std::vector<std::string>& names =
221  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
222 
223  // grab map from evaluated names to field names
224  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
225 
227  p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional;
228 
229  side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
230  local_side_id_ = p.get<int>("Local Side ID");
231 
232  // build the vector of fields that this is dependent on
233  scatterFields_.resize(names.size());
234  for (std::size_t eq = 0; eq < names.size(); ++eq) {
235  scatterFields_[eq] = PHX::MDField<ScalarT,Cell,NODE>(names[eq],dl);
236 
237  // tell the field manager that we depend on this field
238  this->addDependentField(scatterFields_[eq]);
239  }
240 
241  // this is what this evaluator provides
242  this->addEvaluatedField(*scatterHolder_);
243 
244  if (p.isType<std::string>("Global Data Key"))
245  globalDataKey_ = p.get<std::string>("Global Data Key");
246 
247  this->setName(scatterName+" Scatter Residual (SGJacobian)");
248 }
249 
250 // **********************************************************************
251 template<typename TRAITS,typename LO,typename GO>
253 postRegistrationSetup(typename TRAITS::SetupData d,
255 {
256  // globalIndexer_ = d.globalIndexer_;
257 
258  fieldIds_.resize(scatterFields_.size());
259  // load required field numbers for fast use
260  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
261  // get field ID from DOF manager
262  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
263  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
264 
265  // fill field data object
266  this->utils.setFieldData(scatterFields_[fd],fm);
267  }
268 
269  // get the number of nodes (Should be renamed basis)
270  num_nodes = scatterFields_[0].dimension(1);
271  num_eq = scatterFields_.size();
272 }
273 
274 // **********************************************************************
275 template<typename TRAITS,typename LO,typename GO>
277 preEvaluate(typename TRAITS::PreEvalData d)
278 {
279  // extract dirichlet counter from container
281  = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc.getDataObject("Dirichlet Counter"),true);
282 
283  dirichletCounter_ = epetraContainer->get_f();
284  TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
285 
286  // extract linear object container
287  sgEpetraContainer_ = Teuchos::rcp_dynamic_cast<SGEpetraLinearObjContainer>(d.gedc.getDataObject(globalDataKey_));
288 }
289 
290 // **********************************************************************
291 template<typename TRAITS,typename LO,typename GO>
293 evaluateFields(typename TRAITS::EvalData workset)
294 {
295  std::vector<GO> GIDs;
296  std::vector<int> LIDs;
297 
298  // for convenience pull out some objects from workset
299  std::string blockId = this->wda(workset).block_id;
300  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
301 
302  Teuchos::RCP<Epetra_CrsMatrix> Jac_template = (*sgEpetraContainer_->begin())->get_A();
303  const Epetra_BlockMap & map = Jac_template->RowMap();
304 
305  // NOTE: A reordering of these loops will likely improve performance
306  // The "getGIDFieldOffsets may be expensive. However the
307  // "getElementGIDs" can be cheaper. However the lookup for LIDs
308  // may be more expensive!
309 
310  // scatter operation for each cell in workset
311  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
312  std::size_t cellLocalId = localCellIds[worksetCellIndex];
313 
314  globalIndexer_->getElementGIDs(cellLocalId,GIDs);
315 
316  // caculate the local IDs for this element
317  LIDs.resize(GIDs.size());
318  for(std::size_t i=0;i<GIDs.size();i++)
319  LIDs[i] = map.LID(GIDs[i]);
320 
321  std::vector<bool> is_owned(GIDs.size(), false);
322  globalIndexer_->ownedIndices(GIDs,is_owned);
323 
324  // loop over each field to be scattered
325  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
326  int fieldNum = fieldIds_[fieldIndex];
327 
328  // this call "should" get the right ordering according to the Intrepid basis
329  const std::pair<std::vector<int>,std::vector<int> > & indicePair
330  = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
331  const std::vector<int> & elmtOffset = indicePair.first;
332  const std::vector<int> & basisIdMap = indicePair.second;
333 
334  // loop over basis functions
335  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
336  int offset = elmtOffset[basis];
337  int lid = LIDs[offset];
338  int gid = GIDs[offset];
339  int basisId = basisIdMap[basis];
340  if(lid<0) // not on this processor
341  continue;
342 
343  const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,basisId);
344 
345  // loop over stochastic basis scatter field values to residual vectors
346  int stochIndex = 0;
348  for(itr=sgEpetraContainer_->begin();itr!=sgEpetraContainer_->end();++itr,++stochIndex) {
349  Teuchos::RCP<Epetra_Vector> r = (*itr)->get_f();
350  Teuchos::RCP<Epetra_CrsMatrix> Jac = (*itr)->get_A();
351 
352  // zero out matrix row
353  {
354  int numEntries = 0;
355  int * rowIndices = 0;
356  double * rowValues = 0;
357 
358  Jac->ExtractMyRowView(lid,numEntries,rowValues,rowIndices);
359 
360  for(int i=0;i<numEntries;i++)
361  rowValues[i] = 0.0;
362  }
363 
364  (*r)[lid] = scatterField.val().coeff(stochIndex);
365 
366  // loop over the sensitivity indices: all DOFs on a cell
367  std::vector<double> jacRow(scatterField.size(),0.0);
368 
369  for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
370  jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex).coeff(stochIndex);
371 
372  int err = Jac->ReplaceGlobalValues(gid, scatterField.size(), &jacRow[0],&GIDs[0]);
373  TEUCHOS_ASSERT(err==0);
374  }
375 
376  // dirichlet condition application
377  (*dirichletCounter_)[lid] = 1.0;
378  }
379  }
380  }
381 }
382 
383 // **********************************************************************
384 #endif
385 
386 #endif
virtual int ReplaceGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
std::vector< PHX::MDField< const ScalarT, panzer::Cell, panzer::Point > > scatterFields_
T & get(const std::string &name, T def_value)
bool is_null(const std::shared_ptr< T > &p)
PHX::MDField< ScalarT, Cell, IP > field
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const
const Epetra_Map & RowMap() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const Teuchos::RCP< Epetra_Vector > get_f() const
int LID(int GID) const
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)
Pushes residual values into the residual vector for a Newton-based solve.