Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterDirichletResidual_Epetra_Hessian_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 #ifndef __Panzer_ScatterDirichletResidual_Epetra_Hessian_impl_hpp__
12 #define __Panzer_ScatterDirichletResidual_Epetra_Hessian_impl_hpp__
13 
14 // only do this if required by the user
15 #ifdef Panzer_BUILD_HESSIAN_SUPPORT
16 
18 
19 // the includes for this file come in as a result of the includes in the main
20 // Epetra scatter dirichlet residual file
21 
22 namespace panzer {
23 
24 // **************************************************************
25 // Hessian Specialization
26 // **************************************************************
27 template<typename TRAITS,typename LO,typename GO>
31  const Teuchos::ParameterList& p)
32  : globalIndexer_(indexer)
33  , colGlobalIndexer_(cIndexer)
34  , globalDataKey_("Residual Scatter Container")
35  , preserveDiagonal_(false)
36 {
37  std::string scatterName = p.get<std::string>("Scatter Name");
38  scatterHolder_ =
40 
41  // get names to be evaluated
42  const std::vector<std::string>& names =
43  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
44 
45  // grab map from evaluated names to field names
46  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
47 
49  p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional;
50 
51  side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
52  local_side_id_ = p.get<int>("Local Side ID");
53 
54  // build the vector of fields that this is dependent on
55  scatterFields_.resize(names.size());
56  for (std::size_t eq = 0; eq < names.size(); ++eq) {
57  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
58 
59  // tell the field manager that we depend on this field
60  this->addDependentField(scatterFields_[eq]);
61  }
62 
63  checkApplyBC_ = p.get<bool>("Check Apply BC");
64  if (checkApplyBC_) {
65  applyBC_.resize(names.size());
66  for (std::size_t eq = 0; eq < names.size(); ++eq) {
67  applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
68  this->addDependentField(applyBC_[eq]);
69  }
70  }
71 
72  // this is what this evaluator provides
73  this->addEvaluatedField(*scatterHolder_);
74 
75  if (p.isType<std::string>("Global Data Key"))
76  globalDataKey_ = p.get<std::string>("Global Data Key");
77 
78  if (p.isType<bool>("Preserve Diagonal"))
79  preserveDiagonal_ = p.get<bool>("Preserve Diagonal");
80 
81  this->setName(scatterName+" Scatter Residual (Hessian)");
82 }
83 
84 template<typename TRAITS,typename LO,typename GO>
85 void
87 postRegistrationSetup(typename TRAITS::SetupData /* d */,
88  PHX::FieldManager<TRAITS>& /* fm */)
89 {
90  fieldIds_.resize(scatterFields_.size());
91 
92  // load required field numbers for fast use
93  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
94  // get field ID from DOF manager
95  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
96  fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
97  }
98 
99  // get the number of nodes (Should be renamed basis)
100  num_nodes = scatterFields_[0].extent(1);
101  num_eq = scatterFields_.size();
102 }
103 
104 template<typename TRAITS,typename LO,typename GO>
105 void
107 preEvaluate(typename TRAITS::PreEvalData d)
108 {
109  // extract linear object container
110  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
111 
112  if(epetraContainer_==Teuchos::null) {
113  // extract linear object container
114  Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
115  epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc,true);
116 
117  dirichletCounter_ = Teuchos::null;
118  }
119  else {
120  // extract dirichlet counter from container
121  Teuchos::RCP<GlobalEvaluationData> dataContainer = d.gedc->getDataObject("Dirichlet Counter");
122  Teuchos::RCP<EpetraLinearObjContainer> epetraContainer = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(dataContainer,true);
123 
124  dirichletCounter_ = epetraContainer->get_f();
125  TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
126  }
127 }
128 
129 template<typename TRAITS,typename LO,typename GO>
130 void
132 evaluateFields(typename TRAITS::EvalData workset)
133 {
135  using std::vector;
136 
137  // TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
138  // "ScatterDirichletResidual_Epetra<Hessian> is not yet implemented"); // just in case
139 
140  PHX::View<const int*, Kokkos::LayoutRight, PHX::Device> cLIDs, rLIDs;
141  std::vector<double> jacRow;
142 
143  bool useColumnIndexer = colGlobalIndexer_!=Teuchos::null;
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<const EpetraLinearObjContainer> epetraContainer = epetraContainer_;
150  TEUCHOS_ASSERT(epetraContainer!=Teuchos::null);
151  Teuchos::RCP<Epetra_CrsMatrix> Jac = epetraContainer->get_A();
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  rLIDs = globalIndexer_->getElementLIDs(cellLocalId);
162  if(useColumnIndexer)
163  cLIDs = colGlobalIndexer_->getElementLIDs(cellLocalId);
164  else
165  cLIDs = rLIDs;
166 
167  // loop over each field to be scattered
168  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
169  int fieldNum = fieldIds_[fieldIndex];
170 
171  // this call "should" get the right ordering according to the Intrepid2 basis
172  const std::pair<std::vector<int>,std::vector<int> > & indicePair
173  = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
174  const std::vector<int> & elmtOffset = indicePair.first;
175  const std::vector<int> & basisIdMap = indicePair.second;
176 
177  // loop over basis functions
178  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
179  int offset = elmtOffset[basis];
180  int row = rLIDs[offset];
181  if(row<0) // not on this processor
182  continue;
183 
184  int basisId = basisIdMap[basis];
185 
186  if (checkApplyBC_)
187  if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
188  continue;
189 
190  // zero out matrix row
191  {
192  int numEntries = 0;
193  int * rowIndices = 0;
194  double * rowValues = 0;
195 
196  Jac->ExtractMyRowView(row,numEntries,rowValues,rowIndices);
197 
198  for(int i=0;i<numEntries;i++) {
199  if(preserveDiagonal_) {
200  if(row!=rowIndices[i])
201  rowValues[i] = 0.0;
202  }
203  else
204  rowValues[i] = 0.0;
205  }
206  }
207 
208  // int gid = GIDs[offset];
209  const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,basisId);
210 
211  if(dirichletCounter_!=Teuchos::null) {
212  // std::cout << "Writing " << row << " " << dirichletCounter_->MyLength() << std::endl;
213  (*dirichletCounter_)[row] = 1.0; // mark row as dirichlet
214  }
215 
216  // loop over the sensitivity indices: all DOFs on a cell
217  jacRow.resize(scatterField.size());
218  for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
219  jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex).fastAccessDx(0);
220 
221  if(!preserveDiagonal_) {
222  int err = Jac->ReplaceMyValues(row, cLIDs.size(),
223  ptrFromStlVector(jacRow), &cLIDs[0]);
224  TEUCHOS_ASSERT(err==0);
225  }
226  }
227  }
228  }
229 }
230 
231 }
232 
233 // **************************************************************
234 #endif
235 
236 #endif
T & get(const std::string &name, T def_value)
bool is_null(const std::shared_ptr< T > &p)
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
T * ptrFromStlVector(std::vector< T > &v)
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)
int ReplaceMyValues(int MyRow, int NumEntries, const double *Values, const int *Indices)
Pushes residual values into the residual vector for a Newton-based solve.