Panzer Version of the Day
Loading...
Searching...
No Matches
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
22namespace panzer {
23
24// **************************************************************
25// Hessian Specialization
26// **************************************************************
27template<typename TRAITS,typename LO,typename GO>
29ScatterDirichletResidual_Epetra(const Teuchos::RCP<const GlobalIndexer> & indexer,
30 const Teuchos::RCP<const panzer::GlobalIndexer> & cIndexer,
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_ =
39 Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
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
48 Teuchos::RCP<PHX::DataLayout> dl =
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
84template<typename TRAITS,typename LO,typename GO>
85void
87postRegistrationSetup(typename TRAITS::SetupData /* d */,
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
104template<typename TRAITS,typename LO,typename GO>
105void
107preEvaluate(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
129template<typename TRAITS,typename LO,typename GO>
130void
132evaluateFields(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
Pushes residual values into the residual vector for a Newton-based solve.
T * ptrFromStlVector(std::vector< T > &v)