11#ifndef PANZER_SCATTER_RESIDUAL_TPETRA_IMPL_HPP
12#define PANZER_SCATTER_RESIDUAL_TPETRA_IMPL_HPP
14#include "Teuchos_RCP.hpp"
15#include "Teuchos_Assert.hpp"
17#include "Phalanx_DataLayout.hpp"
26#include "Phalanx_DataLayout_MDALayout.hpp"
28#include "Teuchos_FancyOStream.hpp"
30#include "Tpetra_Vector.hpp"
31#include "Tpetra_Map.hpp"
32#include "Tpetra_CrsMatrix.hpp"
38template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
41 const Teuchos::ParameterList& p)
42 : globalIndexer_(indexer)
43 , globalDataKey_(
"Residual Scatter Container")
45 std::string scatterName = p.get<std::string>(
"Scatter Name");
47 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
50 const std::vector<std::string>& names =
51 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
54 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
56 Teuchos::RCP<PHX::DataLayout> dl =
57 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
60 scatterFields_.resize(names.size());
61 scratch_offsets_.resize(names.size());
62 for (std::size_t eq = 0; eq < names.size(); ++eq) {
63 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
66 this->addDependentField(scatterFields_[eq]);
70 this->addEvaluatedField(*scatterHolder_);
72 if (p.isType<std::string>(
"Global Data Key"))
73 globalDataKey_ = p.get<std::string>(
"Global Data Key");
75 this->setName(scatterName+
" Scatter Residual");
79template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
84 fieldIds_.resize(scatterFields_.size());
85 const Workset & workset_0 = (*d.worksets_)[0];
86 std::string blockId = this->wda(workset_0).
block_id;
90 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
92 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
93 fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
95 const std::vector<int> &
offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldIds_[fd]);
96 scratch_offsets_[fd] = PHX::View<int*>(
"offsets",
offsets.size());
97 Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(
offsets.data(),
offsets.size()));
99 scratch_lids_ = PHX::View<LO**>(
"lids",scatterFields_[0].extent(0),
100 globalIndexer_->getElementBlockGIDCount(blockId));
105template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
112 tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
114 if(tpetraContainer_==Teuchos::null) {
116 Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),
true)->getGhostedLOC();
117 tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
126template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
129 const Teuchos::ParameterList& p)
130 : globalIndexer_(indexer)
131 , globalDataKey_(
"Residual Scatter Container")
134 std::string scatterName = p.get<std::string>(
"Scatter Name");
136 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
139 const std::vector<std::string>& names =
140 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
143 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
145 Teuchos::RCP<PHX::DataLayout> dl =
146 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
149 scatterFields_.resize(names.size());
150 scratch_offsets_.resize(names.size());
151 for (std::size_t eq = 0; eq < names.size(); ++eq) {
152 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
155 this->addDependentField(scatterFields_[eq]);
159 this->addEvaluatedField(*scatterHolder_);
161 if (p.isType<std::string>(
"Global Data Key"))
162 globalDataKey_ = p.get<std::string>(
"Global Data Key");
164 this->setName(scatterName+
" Scatter Tangent");
168template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
173 fieldIds_.resize(scatterFields_.size());
174 const Workset & workset_0 = (*d.worksets_)[0];
175 std::string blockId = this->wda(workset_0).
block_id;
178 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
180 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
181 fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
183 const std::vector<int> &
offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldIds_[fd]);
184 scratch_offsets_[fd] = PHX::View<int*>(
"offsets",
offsets.size());
185 Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(
offsets.data(),
offsets.size()));
187 scratch_lids_ = PHX::View<LO**>(
"lids",scatterFields_[0].extent(0),
188 globalIndexer_->getElementBlockGIDCount(blockId));
192template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
197 using Teuchos::rcp_dynamic_cast;
202 std::vector<std::string> activeParameters =
203 rcp_dynamic_cast<ParameterList_GlobalEvaluationData>(d.gedc->getDataObject(
"PARAMETER_NAMES"))->getActiveParameters();
205 dfdpFieldsVoV_.
initialize(
"ScatterResidual_Tpetra<Tangent>::dfdpFieldsVoV_",activeParameters.size());
207 for(std::size_t i=0;i<activeParameters.size();i++) {
208 RCP<typename LOC::VectorType> vec =
209 rcp_dynamic_cast<LOC>(d.gedc->getDataObject(activeParameters[i]),
true)->get_f();
210 auto dfdp_view = vec->getLocalViewDevice(Tpetra::Access::ReadWrite);
212 dfdpFieldsVoV_.addView(dfdp_view,i);
215 dfdpFieldsVoV_.syncHostToDevice();
218 tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
220 if(tpetraContainer_==Teuchos::null) {
222 Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),
true)->getGhostedLOC();
223 tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
231template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
234 const Teuchos::ParameterList& p)
235 : globalIndexer_(indexer)
236 , globalDataKey_(
"Residual Scatter Container")
237 , my_derivative_size_(0)
238 , other_derivative_size_(0)
240 std::string scatterName = p.get<std::string>(
"Scatter Name");
242 Teuchos::rcp(
new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(
new PHX::MDALayout<Dummy>(0))));
245 const std::vector<std::string>& names =
246 *(p.get< Teuchos::RCP< std::vector<std::string> > >(
"Dependent Names"));
249 fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >(
"Dependent Map");
251 Teuchos::RCP<PHX::DataLayout> dl =
252 p.get< Teuchos::RCP<const panzer::PureBasis> >(
"Basis")->functional;
255 scatterFields_.resize(names.size());
256 scratch_offsets_.resize(names.size());
257 for (std::size_t eq = 0; eq < names.size(); ++eq) {
258 scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
261 this->addDependentField(scatterFields_[eq]);
265 this->addEvaluatedField(*scatterHolder_);
267 if (p.isType<std::string>(
"Global Data Key"))
268 globalDataKey_ = p.get<std::string>(
"Global Data Key");
270 this->setName(scatterName+
" Scatter Residual (Jacobian)");
274template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
279 fieldIds_.resize(scatterFields_.size());
281 const Workset & workset_0 = (*d.worksets_)[0];
282 std::string blockId = this->wda(workset_0).
block_id;
285 for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
287 std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
288 fieldIds_[fd] = globalIndexer_->getFieldNum(fieldName);
290 int fieldNum = fieldIds_[fd];
291 const std::vector<int> &
offsets = globalIndexer_->getGIDFieldOffsets(blockId,fieldNum);
292 scratch_offsets_[fd] = PHX::View<int*>(
"offsets",
offsets.size());
293 Kokkos::deep_copy(scratch_offsets_[fd], Kokkos::View<const int*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(
offsets.data(),
offsets.size()));
296 my_derivative_size_ = globalIndexer_->getElementBlockGIDCount(blockId);
297 if (Teuchos::nonnull(workset_0.
other)) {
298 auto otherBlockId = workset_0.
other->block_id;
299 other_derivative_size_ = globalIndexer_->getElementBlockGIDCount(otherBlockId);
301 scratch_lids_ = Kokkos::View<LO**, Kokkos::LayoutRight, PHX::Device>(
302 "lids", scatterFields_[0].extent(0), my_derivative_size_ + other_derivative_size_ );
303 scratch_vals_ = Kokkos::View<typename Sacado::ScalarType<ScalarT>::type**, Kokkos::LayoutRight, PHX::Device>(
304 "vals", scatterFields_[0].extent(0), my_derivative_size_ + other_derivative_size_ );
308template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
315 tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(d.gedc->getDataObject(globalDataKey_));
317 if(tpetraContainer_==Teuchos::null) {
319 Teuchos::RCP<LinearObjContainer> loc = Teuchos::rcp_dynamic_cast<LOCPair_GlobalEvaluationData>(d.gedc->getDataObject(globalDataKey_),
true)->getGhostedLOC();
320 tpetraContainer_ = Teuchos::rcp_dynamic_cast<LOC>(loc);
329template <
typename ScalarT,
typename LO,
typename GO,
typename NodeT,
typename LocalMatrixT>
330class ScatterResidual_Jacobian_Functor {
332 typedef typename PHX::Device execution_space;
333 typedef PHX::MDField<const ScalarT,Cell,NODE>
FieldType;
336 Kokkos::View<double**, Kokkos::LayoutLeft,PHX::Device>
r_data;
339 Kokkos::View<const LO**, Kokkos::LayoutRight, PHX::Device>
lids;
340 Kokkos::View<typename Sacado::ScalarType<ScalarT>::type**, Kokkos::LayoutRight, PHX::Device>
vals;
345 KOKKOS_INLINE_FUNCTION
346 void operator()(
const unsigned int cell)
const
348 int numIds =
lids.extent(1);
351 for(std::size_t basis=0; basis <
offsets.extent(0); basis++) {
352 typename FieldType::array_type::reference_type scatterField =
field(cell,basis);
354 LO lid =
lids(cell,offset);
358 Kokkos::atomic_add(&
r_data(lid,0), scatterField.val());
361 for(
int sensIndex=0;sensIndex<numIds;++sensIndex)
362 vals(cell,sensIndex) = scatterField.fastAccessDx(sensIndex);
365 jac.sumIntoValues(lid, &
lids(cell,0), numIds, &
vals(cell,0),
true,
true);
370template <
typename ScalarT,
typename LO,
typename GO,
typename NodeT>
371class ScatterResidual_Residual_Functor {
373 typedef typename PHX::Device execution_space;
374 typedef PHX::MDField<const ScalarT,Cell,NODE>
FieldType;
376 Kokkos::View<double**, Kokkos::LayoutLeft,PHX::Device>
r_data;
378 PHX::View<const LO**>
lids;
382 KOKKOS_INLINE_FUNCTION
383 void operator()(
const unsigned int cell)
const
387 for(std::size_t basis=0; basis <
offsets.extent(0); basis++) {
389 LO lid =
lids(cell,offset);
390 Kokkos::atomic_add(&
r_data(lid,0),
field(cell,basis));
396template <
typename ScalarT,
typename LO,
typename GO,
typename NodeT>
397class ScatterResidual_Tangent_Functor {
399 typedef typename PHX::Device execution_space;
400 typedef PHX::MDField<const ScalarT,Cell,NODE>
FieldType;
403 Kokkos::View<double**, Kokkos::LayoutLeft,PHX::Device>
r_data;
405 Kokkos::View<const LO**>
lids;
410 Kokkos::View<Kokkos::View<double**,Kokkos::LayoutLeft,PHX::Device>*>
dfdp_fields;
412 KOKKOS_INLINE_FUNCTION
413 void operator()(
const unsigned int cell)
const
417 for(std::size_t basis=0; basis <
offsets.extent(0); basis++) {
418 typename FieldType::array_type::reference_type scatterField =
field(cell,basis);
420 LO lid =
lids(cell,offset);
424 Kokkos::atomic_add(&
r_data(lid,0), scatterField.val());
427 for(
int i_param=0; i_param<
num_params; i_param++)
428 dfdp_fields(i_param)(lid,0) += scatterField.fastAccessDx(i_param);
438template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
445 std::string blockId = this->wda(workset).block_id;
447 Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->
get_f();
449 globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,scratch_lids_);
451 ScatterResidual_Residual_Functor<ScalarT,LO,GO,NodeT> functor;
452 functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite);
453 functor.lids = scratch_lids_;
456 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
457 functor.offsets = scratch_offsets_[fieldIndex];
458 functor.field = scatterFields_[fieldIndex];
460 Kokkos::parallel_for(workset.num_cells,functor);
465template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
471 typedef typename LOC::CrsMatrixType::local_matrix_device_type LocalMatrixT;
474 std::string blockId = this->wda(workset).block_id;
476 Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->
get_f();
477 Teuchos::RCP<typename LOC::CrsMatrixType> Jac = tpetraContainer_->get_A();
482 if (Teuchos::nonnull(workset.other)) {
483 auto my_scratch_lids = Kokkos::subview(scratch_lids_,Kokkos::ALL,std::make_pair(0,my_derivative_size_));
484 globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,my_scratch_lids);
485 auto other_scratch_lids = Kokkos::subview(scratch_lids_,Kokkos::ALL,std::make_pair(my_derivative_size_,my_derivative_size_ + other_derivative_size_));
486 globalIndexer_->getElementLIDs(workset.other->cell_local_ids_k,other_scratch_lids);
489 globalIndexer_->getElementLIDs(this->wda(workset).cell_local_ids_k,scratch_lids_);
492 ScatterResidual_Jacobian_Functor<ScalarT,LO,GO,NodeT,LocalMatrixT> functor;
493 functor.fillResidual = (r!=Teuchos::null);
494 if(functor.fillResidual)
495 functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite);
496 functor.jac = Jac->getLocalMatrixDevice();
497 functor.lids = scratch_lids_;
498 functor.vals = scratch_vals_;
501 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
502 functor.offsets = scratch_offsets_[fieldIndex];
503 functor.field = scatterFields_[fieldIndex];
505 Kokkos::parallel_for(workset.num_cells,functor);
511template<
typename TRAITS,
typename LO,
typename GO,
typename NodeT>
518 std::string blockId = this->wda(workset).block_id;
520 Teuchos::RCP<typename LOC::VectorType> r = tpetraContainer_->
get_f();
522 globalIndexer_->getElementLIDs(this->wda(workset).getLocalCellIDs(),scratch_lids_);
524 ScatterResidual_Tangent_Functor<ScalarT,LO,GO,NodeT> functor;
525 functor.fillResidual = (r!=Teuchos::null);
526 if(functor.fillResidual)
527 functor.r_data = r->getLocalViewDevice(Tpetra::Access::ReadWrite);
528 functor.lids = scratch_lids_;
529 functor.dfdp_fields = dfdpFieldsVoV_.getViewDevice();
532 for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
533 functor.offsets = scratch_offsets_[fieldIndex];
534 functor.field = scatterFields_[fieldIndex];
535 functor.num_params = Kokkos::dimension_scalar(scatterFields_[fieldIndex].get_view())-1;
537 Kokkos::parallel_for(workset.num_cells,functor);
PHX::View< const int * > offsets
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.
Kokkos::View< Kokkos::View< double **, Kokkos::LayoutLeft, PHX::Device > * > dfdp_fields
PHX::View< const LO ** > lids
Kokkos::View< double **, Kokkos::LayoutLeft, PHX::Device > r_data
Kokkos::View< typename Sacado::ScalarType< ScalarT >::type **, Kokkos::LayoutRight, PHX::Device > vals
Pushes residual values into the residual vector for a Newton-based solve.
virtual void initialize()
const Teuchos::RCP< VectorType > get_f() const
std::string block_id
DEPRECATED - use: getElementBlock()
Teuchos::RCP< WorksetDetails > other
FieldType
The type of discretization to use for a field pattern.