Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_ScatterDirichletResidual_Epetra_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_SCATTER_DIRICHLET_RESIDUAL_EPETRA_IMPL_HPP
12#define PANZER_SCATTER_DIRICHLET_RESIDUAL_EPETRA_IMPL_HPP
13
14#include "Teuchos_RCP.hpp"
15#include "Teuchos_Assert.hpp"
16
17#include "Phalanx_DataLayout.hpp"
18
19#include "Epetra_Map.h"
20#include "Epetra_Vector.h"
21#include "Epetra_CrsMatrix.h"
22
24#include "Panzer_PureBasis.hpp"
29
30#include "Phalanx_DataLayout_MDALayout.hpp"
31
32#include "Teuchos_FancyOStream.hpp"
33
34// **********************************************************************
35// Specialization: Residual
36// **********************************************************************
37
38
39template<typename TRAITS,typename LO,typename GO>
41ScatterDirichletResidual_Epetra(const Teuchos::RCP<const GlobalIndexer> & indexer,
42 const Teuchos::RCP<const panzer::GlobalIndexer> & /* cIndexer */,
43 const Teuchos::ParameterList& p)
44 : globalIndexer_(indexer)
45 , globalDataKey_("Residual Scatter Container")
46{
47 std::string scatterName = p.get<std::string>("Scatter Name");
48 scatterHolder_ =
49 Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
50
51 // get names to be evaluated
52 const std::vector<std::string>& names =
53 *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
54
55 // grab map from evaluated names to field names
56 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
57
58 // determine if we are scattering an initial condition
59 scatterIC_ = p.isParameter("Scatter Initial Condition") ? p.get<bool>("Scatter Initial Condition") : false;
60
61 Teuchos::RCP<PHX::DataLayout> dl = (!scatterIC_) ?
62 p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional :
63 p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
64 if (!scatterIC_) {
65 side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
66 local_side_id_ = p.get<int>("Local Side ID");
67 }
68
69 // build the vector of fields that this is dependent on
70 scatterFields_.resize(names.size());
71 for (std::size_t eq = 0; eq < names.size(); ++eq) {
72 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
73
74 // tell the field manager that we depend on this field
75 this->addDependentField(scatterFields_[eq]);
76 }
77
78 checkApplyBC_ = p.isParameter("Check Apply BC") ? p.get<bool>("Check Apply BC") : false;
79 if (checkApplyBC_) {
80 applyBC_.resize(names.size());
81 for (std::size_t eq = 0; eq < names.size(); ++eq) {
82 applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
83 this->addDependentField(applyBC_[eq]);
84 }
85 }
86
87 // this is what this evaluator provides
88 this->addEvaluatedField(*scatterHolder_);
89
90 if (p.isType<std::string>("Global Data Key"))
91 globalDataKey_ = p.get<std::string>("Global Data Key");
92
93 this->setName(scatterName+" Scatter Residual");
94}
95
96// **********************************************************************
97template<typename TRAITS,typename LO,typename GO>
99postRegistrationSetup(typename TRAITS::SetupData /* d */,
101{
102 fieldIds_.resize(scatterFields_.size());
103
104 // load required field numbers for fast use
105 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
106 // get field ID from DOF manager
107 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
108 fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
109 }
110
111 // get the number of nodes (Should be renamed basis)
112 num_nodes = scatterFields_[0].extent(1);
113}
114
115// **********************************************************************
116template<typename TRAITS,typename LO,typename GO>
118preEvaluate(typename TRAITS::PreEvalData d)
119{
120 // extract linear object container
121 epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
122
123 if(epetraContainer_==Teuchos::null) {
124 // extract linear object container
125 Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
126 epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc);
127
128 dirichletCounter_ = Teuchos::null;
129 }
130 else {
131 // extract dirichlet counter from container
132 Teuchos::RCP<EpetraLinearObjContainer> epetraContainer
133 = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject("Dirichlet Counter"),true);
134
135 dirichletCounter_ = epetraContainer->get_f();
136 TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
137 }
138}
139
140// **********************************************************************
141template<typename TRAITS,typename LO,typename GO>
143evaluateFields(typename TRAITS::EvalData workset)
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::RCP<Epetra_Vector> r = (!scatterIC_) ?
151 epetraContainer->get_f() :
152 epetraContainer->get_x();
153 // NOTE: A reordering of these loops will likely improve performance
154 // The "getGIDFieldOffsets may be expensive. However the
155 // "getElementGIDs" can be cheaper. However the lookup for LIDs
156 // may be more expensive!
157
158 // scatter operation for each cell in workset
159 auto LIDs = globalIndexer_->getLIDs();
160 auto LIDs_h = Kokkos::create_mirror_view(LIDs);
161 Kokkos::deep_copy(LIDs_h, LIDs);
162
163
164 // loop over each field to be scattered
165 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
166 int fieldNum = fieldIds_[fieldIndex];
167 auto field = PHX::as_view(scatterFields_[fieldIndex]);
168 auto field_h = Kokkos::create_mirror_view(field);
169 Kokkos::deep_copy(field_h, field);
170
171 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
172 std::size_t cellLocalId = localCellIds[worksetCellIndex];
173
174 if (!scatterIC_) {
175 // this call "should" get the right ordering according to the Intrepid2 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_h(cellLocalId, offset);
185 if(lid<0) // not on this processor!
186 continue;
187
188 int basisId = basisIdMap[basis];
189
190 if (checkApplyBC_)
191 if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
192 continue;
193
194 (*r)[lid] = field_h(worksetCellIndex,basisId);
195
196 // record that you set a dirichlet condition
197 if(dirichletCounter_!=Teuchos::null)
198 (*dirichletCounter_)[lid] = 1.0;
199 }
200 } else {
201 // this call "should" get the right ordering according to the Intrepid2 basis
202 const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
203
204 // loop over basis functions
205 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
206 int offset = elmtOffset[basis];
207 int lid = LIDs_h(cellLocalId, offset);
208 if(lid<0) // not on this processor!
209 continue;
210
211 (*r)[lid] = field_h(worksetCellIndex,basis);
212
213 // record that you set a dirichlet condition
214 if(dirichletCounter_!=Teuchos::null)
215 (*dirichletCounter_)[lid] = 1.0;
216 }
217 }
218 }
219 }
220}
221
222// **********************************************************************
223// Specialization: Tangent
224// **********************************************************************
225
226
227template<typename TRAITS,typename LO,typename GO>
229ScatterDirichletResidual_Epetra(const Teuchos::RCP<const GlobalIndexer> & indexer,
230 const Teuchos::RCP<const panzer::GlobalIndexer> & /* cIndexer */,
231 const Teuchos::ParameterList& p)
232 : globalIndexer_(indexer)
233 , globalDataKey_("Residual Scatter Container")
234{
235 std::string scatterName = p.get<std::string>("Scatter Name");
236 scatterHolder_ =
237 Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
238
239 // get names to be evaluated
240 const std::vector<std::string>& names =
241 *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
242
243 // grab map from evaluated names to field names
244 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
245
246 // determine if we are scattering an initial condition
247 scatterIC_ = p.isParameter("Scatter Initial Condition") ? p.get<bool>("Scatter Initial Condition") : false;
248
249 Teuchos::RCP<PHX::DataLayout> dl = (!scatterIC_) ?
250 p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional :
251 p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
252 if (!scatterIC_) {
253 side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
254 local_side_id_ = p.get<int>("Local Side ID");
255 }
256
257 // build the vector of fields that this is dependent on
258 scatterFields_.resize(names.size());
259 for (std::size_t eq = 0; eq < names.size(); ++eq) {
260 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
261
262 // tell the field manager that we depend on this field
263 this->addDependentField(scatterFields_[eq]);
264 }
265
266 checkApplyBC_ = p.isParameter("Check Apply BC") ? p.get<bool>("Check Apply BC") : false;
267 if (checkApplyBC_) {
268 applyBC_.resize(names.size());
269 for (std::size_t eq = 0; eq < names.size(); ++eq) {
270 applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
271 this->addDependentField(applyBC_[eq]);
272 }
273 }
274
275 // this is what this evaluator provides
276 this->addEvaluatedField(*scatterHolder_);
277
278 if (p.isType<std::string>("Global Data Key"))
279 globalDataKey_ = p.get<std::string>("Global Data Key");
280
281 this->setName(scatterName+" Scatter Tangent");
282}
283
284// **********************************************************************
285template<typename TRAITS,typename LO,typename GO>
287postRegistrationSetup(typename TRAITS::SetupData /* d */,
289{
290 fieldIds_.resize(scatterFields_.size());
291
292 // load required field numbers for fast use
293 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
294 // get field ID from DOF manager
295 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
296 fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
297 }
298
299 // get the number of nodes (Should be renamed basis)
300 num_nodes = scatterFields_[0].extent(1);
301}
302
303// **********************************************************************
304template<typename TRAITS,typename LO,typename GO>
306preEvaluate(typename TRAITS::PreEvalData d)
307{
308 // extract linear object container
309 epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
310
311 if(epetraContainer_==Teuchos::null) {
312 // extract linear object container
313 Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
314 epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc);
315
316 dirichletCounter_ = Teuchos::null;
317 }
318 else {
319 // extract dirichlet counter from container
320 Teuchos::RCP<EpetraLinearObjContainer> epetraContainer
321 = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject("Dirichlet Counter"),true);
322
323 dirichletCounter_ = epetraContainer->get_f();
324 TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
325 }
326
327 using Teuchos::RCP;
328 using Teuchos::rcp_dynamic_cast;
329
330 // this is the list of parameters and their names that this scatter has to account for
331 std::vector<std::string> activeParameters =
332 rcp_dynamic_cast<ParameterList_GlobalEvaluationData>(d.gedc->getDataObject("PARAMETER_NAMES"))->getActiveParameters();
333
334 // ETP 02/03/16: This code needs to be updated to properly handle scatterIC_
335 TEUCHOS_ASSERT(!scatterIC_);
336 dfdp_vectors_.clear();
337 for(std::size_t i=0;i<activeParameters.size();i++) {
338 RCP<Epetra_Vector> vec = rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(activeParameters[i]),true)->get_f();
339 dfdp_vectors_.push_back(vec);
340 }
341}
342
343// **********************************************************************
344template<typename TRAITS,typename LO,typename GO>
346evaluateFields(typename TRAITS::EvalData workset)
347{
348 // for convenience pull out some objects from workset
349 std::string blockId = this->wda(workset).block_id;
350 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
351
352 Teuchos::RCP<const EpetraLinearObjContainer> epetraContainer = epetraContainer_;
353 Teuchos::RCP<Epetra_Vector> r = (!scatterIC_) ?
354 epetraContainer->get_f() :
355 epetraContainer->get_x();
356 // NOTE: A reordering of these loops will likely improve performance
357 // The "getGIDFieldOffsets may be expensive. However the
358 // "getElementGIDs" can be cheaper. However the lookup for LIDs
359 // may be more expensive!
360
361 // loop over each field to be scattered
362 auto LIDs = globalIndexer_->getLIDs();
363 auto LIDs_h = Kokkos::create_mirror_view(LIDs);
364 Kokkos::deep_copy(LIDs_h, LIDs);
365 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
366 int fieldNum = fieldIds_[fieldIndex];
367 auto scatterField_h = Kokkos::create_mirror_view(scatterFields_[fieldIndex].get_static_view());
368 Kokkos::deep_copy(scatterField_h, scatterFields_[fieldIndex].get_static_view());
369
370 // scatter operation for each cell in workset
371 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
372 std::size_t cellLocalId = localCellIds[worksetCellIndex];
373
374 if (!scatterIC_) {
375 // this call "should" get the right ordering according to the Intrepid2 basis
376 const std::pair<std::vector<int>,std::vector<int> > & indicePair
377 = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
378 const std::vector<int> & elmtOffset = indicePair.first;
379 const std::vector<int> & basisIdMap = indicePair.second;
380
381 // loop over basis functions
382 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
383 int offset = elmtOffset[basis];
384 int lid = LIDs_h(cellLocalId, offset);
385 if(lid<0) // not on this processor!
386 continue;
387
388 int basisId = basisIdMap[basis];
389
390 if (checkApplyBC_)
391 if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
392 continue;
393
394 ScalarT value = scatterField_h(worksetCellIndex,basisId);
395 // (*r)[lid] = (scatterFields_[fieldIndex])(worksetCellIndex,basisId).val();
396
397 // then scatter the sensitivity vectors
398 if(value.size()==0)
399 for(std::size_t d=0;d<dfdp_vectors_.size();d++)
400 (*dfdp_vectors_[d])[lid] = 0.0;
401 else
402 for(int d=0;d<value.size();d++) {
403 (*dfdp_vectors_[d])[lid] = value.fastAccessDx(d);
404 }
405
406 // record that you set a dirichlet condition
407 if(dirichletCounter_!=Teuchos::null)
408 (*dirichletCounter_)[lid] = 1.0;
409 }
410 } else {
411 // this call "should" get the right ordering according to the Intrepid2 basis
412 const std::vector<int> & elmtOffset = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
413
414 // loop over basis functions
415 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
416 int offset = elmtOffset[basis];
417 int lid = LIDs_h(cellLocalId, offset);
418 if(lid<0) // not on this processor!
419 continue;
420
421 ScalarT value = scatterField_h(worksetCellIndex,basis);
422 // (*r)[lid] = (scatterFields_[fieldIndex])(worksetCellIndex,basis).val();
423
424 // then scatter the sensitivity vectors
425 if(value.size()==0)
426 for(std::size_t d=0;d<dfdp_vectors_.size();d++)
427 (*dfdp_vectors_[d])[lid] = 0.0;
428 else
429 for(int d=0;d<value.size();d++) {
430 (*dfdp_vectors_[d])[lid] = value.fastAccessDx(d);
431 }
432
433 // record that you set a dirichlet condition
434 if(dirichletCounter_!=Teuchos::null)
435 (*dirichletCounter_)[lid] = 1.0;
436 }
437 }
438 }
439 }
440}
441
442// **********************************************************************
443// Specialization: Jacobian
444// **********************************************************************
445
446template<typename TRAITS,typename LO,typename GO>
448ScatterDirichletResidual_Epetra(const Teuchos::RCP<const GlobalIndexer> & indexer,
449 const Teuchos::RCP<const panzer::GlobalIndexer> & cIndexer,
450 const Teuchos::ParameterList& p)
451 : globalIndexer_(indexer)
452 , colGlobalIndexer_(cIndexer)
453 , globalDataKey_("Residual Scatter Container")
454 , preserveDiagonal_(false)
455{
456 std::string scatterName = p.get<std::string>("Scatter Name");
457 scatterHolder_ =
458 Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
459
460 // get names to be evaluated
461 const std::vector<std::string>& names =
462 *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
463
464 // grab map from evaluated names to field names
465 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
466
467 Teuchos::RCP<PHX::DataLayout> dl =
468 p.get< Teuchos::RCP<panzer::PureBasis> >("Basis")->functional;
469
470 side_subcell_dim_ = p.get<int>("Side Subcell Dimension");
471 local_side_id_ = p.get<int>("Local Side ID");
472
473 // build the vector of fields that this is dependent on
474 scatterFields_.resize(names.size());
475 for (std::size_t eq = 0; eq < names.size(); ++eq) {
476 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
477
478 // tell the field manager that we depend on this field
479 this->addDependentField(scatterFields_[eq]);
480 }
481
482 checkApplyBC_ = p.get<bool>("Check Apply BC");
483 if (checkApplyBC_) {
484 applyBC_.resize(names.size());
485 for (std::size_t eq = 0; eq < names.size(); ++eq) {
486 applyBC_[eq] = PHX::MDField<const bool,Cell,NODE>(std::string("APPLY_BC_")+fieldMap_->find(names[eq])->second,dl);
487 this->addDependentField(applyBC_[eq]);
488 }
489 }
490
491 // this is what this evaluator provides
492 this->addEvaluatedField(*scatterHolder_);
493
494 if (p.isType<std::string>("Global Data Key"))
495 globalDataKey_ = p.get<std::string>("Global Data Key");
496
497 if (p.isType<bool>("Preserve Diagonal"))
498 preserveDiagonal_ = p.get<bool>("Preserve Diagonal");
499
500 this->setName(scatterName+" Scatter Residual (Jacobian)");
501}
502
503// **********************************************************************
504template<typename TRAITS,typename LO,typename GO>
506postRegistrationSetup(typename TRAITS::SetupData /* d */,
508{
509 fieldIds_.resize(scatterFields_.size());
510
511 // load required field numbers for fast use
512 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
513 // get field ID from DOF manager
514 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
515 fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
516 }
517
518 // get the number of nodes (Should be renamed basis)
519 num_nodes = scatterFields_[0].extent(1);
520 num_eq = scatterFields_.size();
521}
522
523// **********************************************************************
524template<typename TRAITS,typename LO,typename GO>
526preEvaluate(typename TRAITS::PreEvalData d)
527{
528 // extract linear object container
529 epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(d.gedc->getDataObject(globalDataKey_));
530
531 if(epetraContainer_==Teuchos::null) {
532 // extract linear object container
533 Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),true)->getGhostedLOC();
534 epetraContainer_ = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(loc,true);
535
536 dirichletCounter_ = Teuchos::null;
537 }
538 else {
539 // extract dirichlet counter from container
540 Teuchos::RCP<GlobalEvaluationData> dataContainer = d.gedc->getDataObject("Dirichlet Counter");
541 Teuchos::RCP<EpetraLinearObjContainer> epetraContainer = Teuchos::rcp_dynamic_cast<EpetraLinearObjContainer>(dataContainer,true);
542
543 dirichletCounter_ = epetraContainer->get_f();
544 TEUCHOS_ASSERT(!Teuchos::is_null(dirichletCounter_));
545 }
546}
547
548// **********************************************************************
549template<typename TRAITS,typename LO,typename GO>
551evaluateFields(typename TRAITS::EvalData workset)
552{
553 Kokkos::View<const int*, Kokkos::LayoutRight, PHX::Device> cLIDs, rLIDs;
554 int gidCount(0);
555 bool useColumnIndexer = colGlobalIndexer_!=Teuchos::null;
556 const Teuchos::RCP<const panzer::GlobalIndexer>&
557 colGlobalIndexer = useColumnIndexer ? colGlobalIndexer_ : globalIndexer_;
558
559 // for convenience pull out some objects from workset
560 std::string blockId = this->wda(workset).block_id;
561 const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
562
563 Teuchos::RCP<const EpetraLinearObjContainer> epetraContainer = epetraContainer_;
564 TEUCHOS_ASSERT(epetraContainer!=Teuchos::null);
565 Teuchos::RCP<Epetra_Vector> r = epetraContainer->get_f();
566 Teuchos::RCP<Epetra_CrsMatrix> Jac = epetraContainer->get_A();
567 // NOTE: A reordering of these loops will likely improve performance
568 // The "getGIDFieldOffsets may be expensive. However the
569 // "getElementGIDs" can be cheaper. However the lookup for LIDs
570 // may be more expensive!
571
572 // scatter operation for each cell in workset
573
574 auto LIDs = globalIndexer_->getLIDs();
575 auto colLIDs = colGlobalIndexer->getLIDs();
576 auto LIDs_h = Kokkos::create_mirror_view(LIDs);
577 auto colLIDs_h = Kokkos::create_mirror_view(colLIDs);
578 Kokkos::deep_copy(LIDs_h, LIDs);
579 Kokkos::deep_copy(colLIDs_h, colLIDs);
580
581 std::vector<typename decltype(scatterFields_[0].get_static_view())::host_mirror_type> scatterFields_h;
582 for ( std::size_t i=0; i< scatterFields_.size(); ++i) {
583 scatterFields_h.push_back(Kokkos::create_mirror_view(scatterFields_[i].get_static_view()));
584 Kokkos::deep_copy(scatterFields_h[i], scatterFields_[i].get_static_view());
585 }
586
587 for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
588 std::size_t cellLocalId = localCellIds[worksetCellIndex];
589
590 gidCount = colGlobalIndexer->getElementBlockGIDCount(blockId);
591
592 // loop over each field to be scattered
593 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
594 int fieldNum = fieldIds_[fieldIndex];
595
596 // this call "should" get the right ordering according to the Intrepid2 basis
597 const std::pair<std::vector<int>,std::vector<int> > & indicePair
598 = globalIndexer_->getGIDFieldOffsets_closure(blockId,fieldNum, side_subcell_dim_, local_side_id_);
599 const std::vector<int> & elmtOffset = indicePair.first;
600 const std::vector<int> & basisIdMap = indicePair.second;
601
602 // loop over basis functions
603 for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
604 int offset = elmtOffset[basis];
605 int row = LIDs_h(cellLocalId, offset);
606 if(row<0) // not on this processor
607 continue;
608
609 int basisId = basisIdMap[basis];
610
611 if (checkApplyBC_)
612 if (!applyBC_[fieldIndex](worksetCellIndex,basisId))
613 continue;
614
615 // zero out matrix row
616 {
617 int numEntries = 0;
618 int * rowIndices = 0;
619 double * rowValues = 0;
620
621 Jac->ExtractMyRowView(row,numEntries,rowValues,rowIndices);
622
623 for(int i=0;i<numEntries;i++) {
624 if(preserveDiagonal_) {
625 if(row!=rowIndices[i])
626 rowValues[i] = 0.0;
627 }
628 else
629 rowValues[i] = 0.0;
630 }
631 }
632
633 // int gid = GIDs[offset];
634 const ScalarT scatterField = (scatterFields_h[fieldIndex])(worksetCellIndex,basisId);
635
636 if(r!=Teuchos::null)
637 (*r)[row] = scatterField.val();
638 if(dirichletCounter_!=Teuchos::null) {
639 // std::cout << "Writing " << row << " " << dirichletCounter_->MyLength() << std::endl;
640 (*dirichletCounter_)[row] = 1.0; // mark row as dirichlet
641 }
642
643 // loop over the sensitivity indices: all DOFs on a cell
644 std::vector<double> jacRow(scatterField.size(),0.0);
645
646 if(!preserveDiagonal_) {
647 int err = Jac->ReplaceMyValues(row, gidCount, scatterField.dx(),
648 &colLIDs_h(cellLocalId,0));
649 TEUCHOS_ASSERT(err==0);
650 }
651 }
652 }
653 }
654}
655
656// **********************************************************************
657
658#endif
PHX::MDField< ScalarT, panzer::Cell, panzer::BASIS > field
A field to which we'll contribute, or in which we'll store, the result of computing this integral.
Pushes residual values into the residual vector for a Newton-based solve.