Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_GatherSolution_BlockedTpetra_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_GATHER_SOLUTION_BLOCKED_TPETRA_IMPL_HPP
12#define PANZER_GATHER_SOLUTION_BLOCKED_TPETRA_IMPL_HPP
13
14#include "Teuchos_Assert.hpp"
15#include "Phalanx_DataLayout.hpp"
16
19#include "Panzer_PureBasis.hpp"
20#include "Panzer_TpetraLinearObjFactory.hpp"
26
27#include "Teuchos_FancyOStream.hpp"
28
29#include "Thyra_SpmdVectorBase.hpp"
30#include "Thyra_ProductVectorBase.hpp"
31
32#include "Tpetra_Map.hpp"
33
34template <typename EvalT,typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
37 const Teuchos::RCP<const BlockedDOFManager> & indexer,
38 const Teuchos::ParameterList& p)
39{
40 const std::vector<std::string>& names =
41 *(p.get< Teuchos::RCP< std::vector<std::string> > >("DOF Names"));
42
43 Teuchos::RCP<panzer::PureBasis> basis =
44 p.get< Teuchos::RCP<panzer::PureBasis> >("Basis");
45
46 for (std::size_t fd = 0; fd < names.size(); ++fd) {
47 PHX::MDField<ScalarT,Cell,NODE> field = PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->functional);
48 this->addEvaluatedField(field.fieldTag());
49 }
50
51 this->setName("Gather Solution");
52}
53
54// **********************************************************************
55// Specialization: Residual
56// **********************************************************************
57
58template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
61 const Teuchos::RCP<const BlockedDOFManager> & indexer,
62 const Teuchos::ParameterList& p)
63 : globalIndexer_(indexer)
64 , has_tangent_fields_(false)
65{
66 typedef std::vector< std::vector<std::string> > vvstring;
67
69 input.setParameterList(p);
70
71 const std::vector<std::string> & names = input.getDofNames();
72 Teuchos::RCP<const panzer::PureBasis> basis = input.getBasis();
73 const vvstring & tangent_field_names = input.getTangentNames();
74
75 indexerNames_ = input.getIndexerNames();
76 useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
77 globalDataKey_ = input.getGlobalDataKey();
78
79 // allocate fields
80 gatherFields_.resize(names.size());
81 for (std::size_t fd = 0; fd < names.size(); ++fd) {
82 gatherFields_[fd] =
83 PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->functional);
84 this->addEvaluatedField(gatherFields_[fd]);
85 }
86
87 // Setup dependent tangent fields if requested
88 if (tangent_field_names.size()>0) {
89 TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
90
91 has_tangent_fields_ = true;
92 tangentFields_.resize(gatherFields_.size());
93 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
94 tangentFields_[fd].resize(tangent_field_names[fd].size());
95 for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
96 tangentFields_[fd][i] =
97 PHX::MDField<const ScalarT,Cell,NODE>(tangent_field_names[fd][i],basis->functional);
98 this->addDependentField(tangentFields_[fd][i]);
99 }
100 }
101 }
102
103 // figure out what the first active name is
104 std::string firstName = "<none>";
105 if(names.size()>0)
106 firstName = names[0];
107
108 std::string n = "GatherSolution (BlockedTpetra): "+firstName+" (Residual)";
109 this->setName(n);
110}
111
112// **********************************************************************
113template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
115postRegistrationSetup(typename TRAITS::SetupData d,
117{
118 TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
119
120 const Workset & workset_0 = (*d.worksets_)[0];
121 const std::string blockId = this->wda(workset_0).block_id;
122
123 fieldIds_.resize(gatherFields_.size());
124 fieldOffsets_.resize(gatherFields_.size());
125 fieldGlobalIndexers_.resize(gatherFields_.size());
126 productVectorBlockIndex_.resize(gatherFields_.size());
127 int maxElementBlockGIDCount = -1;
128 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
129 // get field ID from DOF manager
130 const std::string& fieldName = indexerNames_[fd];
131 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
132 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
133 fieldGlobalIndexers_[fd] = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
134 fieldIds_[fd] = fieldGlobalIndexers_[fd]->getFieldNum(fieldName); // Field number in the sub-global-indexer
135
136 const std::vector<int>& offsets = fieldGlobalIndexers_[fd]->getGIDFieldOffsets(blockId,fieldIds_[fd]);
137 fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Residual):fieldOffsets",offsets.size());
138 auto hostFieldOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
139 for(std::size_t i=0; i < offsets.size(); ++i)
140 hostFieldOffsets(i) = offsets[i];
141 Kokkos::deep_copy(fieldOffsets_[fd],hostFieldOffsets);
142
143 maxElementBlockGIDCount = std::max(fieldGlobalIndexers_[fd]->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
144 }
145
146 // We will use one workset lid view for all fields, but has to be
147 // sized big enough to hold the largest elementBlockGIDCount in the
148 // ProductVector.
149 worksetLIDs_ = PHX::View<LO**>("GatherSolution_BlockedTpetra(Residual):worksetLIDs",
150 gatherFields_[0].extent(0),
151 maxElementBlockGIDCount);
152
153 indexerNames_.clear(); // Don't need this anymore
154}
155
156// **********************************************************************
157template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
159preEvaluate(typename TRAITS::PreEvalData d)
160{
161 // extract linear object container
162 blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
163}
164
165// **********************************************************************
166template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
168evaluateFields(typename TRAITS::EvalData workset)
169{
170 using Teuchos::RCP;
171 using Teuchos::rcp_dynamic_cast;
172 using Thyra::VectorBase;
174
175 const PHX::View<const int*>& localCellIds = this->wda(workset).cell_local_ids_k;
176
177 RCP<ProductVectorBase<ScalarT>> thyraBlockSolution;
178 if (useTimeDerivativeSolutionVector_)
179 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_dxdt(),true);
180 else
181 thyraBlockSolution = rcp_dynamic_cast<ProductVectorBase<ScalarT>>(blockedContainer_->get_x(),true);
182
183 // Loop over gathered fields
184 int currentWorksetLIDSubBlock = -1;
185 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
186 // workset LIDs only change for different sub blocks
187 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
188 const std::string blockId = this->wda(workset).block_id;
189 const int num_dofs = fieldGlobalIndexers_[fieldIndex]->getElementBlockGIDCount(blockId);
190 fieldGlobalIndexers_[fieldIndex]->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
191 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
192 }
193
194 const auto& tpetraSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<ScalarT,LO,GO,NodeT>>(thyraBlockSolution->getNonconstVectorBlock(productVectorBlockIndex_[fieldIndex]),true))->getTpetraVector());
195 const auto& kokkosSolution = tpetraSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
196
197 // Class data fields for lambda capture
198 const auto& fieldOffsets = fieldOffsets_[fieldIndex];
199 const auto& worksetLIDs = worksetLIDs_;
200 const auto& fieldValues = gatherFields_[fieldIndex];
201
202 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
203 for(int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
204 const int lid = worksetLIDs(cell,fieldOffsets(basis));
205 fieldValues(cell,basis) = kokkosSolution(lid,0);
206 }
207 });
208 }
209
210}
211
212// **********************************************************************
213// Specialization: Tangent
214// **********************************************************************
215
216template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
219 const Teuchos::RCP<const BlockedDOFManager> & indexer,
220 const Teuchos::ParameterList& p)
221 : globalIndexer_(indexer)
222 , has_tangent_fields_(false)
223{
224 typedef std::vector< std::vector<std::string> > vvstring;
225
227 input.setParameterList(p);
228
229 const std::vector<std::string> & names = input.getDofNames();
230 Teuchos::RCP<const panzer::PureBasis> basis = input.getBasis();
231 const vvstring & tangent_field_names = input.getTangentNames();
232
233 indexerNames_ = input.getIndexerNames();
234 useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
235 globalDataKey_ = input.getGlobalDataKey();
236
237 // allocate fields
238 gatherFields_.resize(names.size());
239 for (std::size_t fd = 0; fd < names.size(); ++fd) {
240 gatherFields_[fd] =
241 PHX::MDField<ScalarT,Cell,NODE>(names[fd],basis->functional);
242 this->addEvaluatedField(gatherFields_[fd]);
243 }
244
245 // Setup dependent tangent fields if requested
246 if (tangent_field_names.size()>0) {
247 TEUCHOS_ASSERT(gatherFields_.size() == tangent_field_names.size());
248
249 has_tangent_fields_ = true;
250 tangentFields_.resize(gatherFields_.size());
251 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
252 tangentFields_[fd].resize(tangent_field_names[fd].size());
253 for (std::size_t i=0; i<tangent_field_names[fd].size(); ++i) {
254 tangentFields_[fd][i] =
255 PHX::MDField<const RealT,Cell,NODE>(tangent_field_names[fd][i],basis->functional);
256 this->addDependentField(tangentFields_[fd][i]);
257 }
258 }
259 }
260
261 // figure out what the first active name is
262 std::string firstName = "<none>";
263 if(names.size()>0)
264 firstName = names[0];
265
266 std::string n = "GatherSolution (BlockedTpetra): "+firstName+" (Tangent)";
267 this->setName(n);
268}
269
270// **********************************************************************
271template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
273postRegistrationSetup(typename TRAITS::SetupData d,
275{
276 TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
277
278 const Workset & workset_0 = (*d.worksets_)[0];
279 const std::string blockId = this->wda(workset_0).block_id;
280
281 fieldIds_.resize(gatherFields_.size());
282 fieldOffsets_.resize(gatherFields_.size());
283 productVectorBlockIndex_.resize(gatherFields_.size());
284 int maxElementBlockGIDCount = -1;
285 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
286
287 const std::string fieldName = indexerNames_[fd];
288 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
289 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
290 const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
291 fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName); // Field number in the sub-global-indexer
292
293 const std::vector<int>& offsets = subGlobalIndexer->getGIDFieldOffsets(blockId,fieldIds_[fd]);
294 fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Tangent):fieldOffsets",offsets.size());
295 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
296 for (std::size_t i=0; i < offsets.size(); ++i)
297 hostOffsets(i) = offsets[i];
298 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
299 maxElementBlockGIDCount = std::max(subGlobalIndexer->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
300 }
301
302 // We will use one workset lid view for all fields, but has to be
303 // sized big enough to hold the largest elementBlockGIDCount in the
304 // ProductVector.
305 worksetLIDs_ = PHX::View<LO**>("ScatterResidual_BlockedTpetra(Tangent):worksetLIDs",
306 gatherFields_[0].extent(0),
307 maxElementBlockGIDCount);
308
309 // Set up storage for tangentFields using view of views
310 if (has_tangent_fields_) {
311
312 size_t inner_vector_max_size = 0;
313 for (std::size_t fd = 0; fd < tangentFields_.size(); ++fd)
314 inner_vector_max_size = std::max(inner_vector_max_size,tangentFields_[fd].size());
315 tangentFieldsVoV_.initialize("GatherSolution_BlockedTpetra<Tangent>::tangentFieldsVoV_",gatherFields_.size(),inner_vector_max_size);
316
317 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
318 for (std::size_t i=0; i<tangentFields_[fd].size(); ++i) {
319 tangentFieldsVoV_.addView(tangentFields_[fd][i].get_static_view(),fd,i);
320 }
321 }
322
323 tangentFieldsVoV_.syncHostToDevice();
324 }
325
326 indexerNames_.clear(); // Don't need this anymore
327}
328
329// **********************************************************************
330template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
332preEvaluate(typename TRAITS::PreEvalData d)
333{
334 // extract linear object container
335 blockedContainer_ = Teuchos::rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
336}
337
338// **********************************************************************
339template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
341evaluateFields(typename TRAITS::EvalData workset)
342{
343 using Teuchos::RCP;
344 using Teuchos::ArrayRCP;
345 using Teuchos::ptrFromRef;
346 using Teuchos::rcp_dynamic_cast;
347
348 using Thyra::VectorBase;
349 using Thyra::SpmdVectorBase;
351
352 Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
353 out.setShowProcRank(true);
354 out.setOutputToRootOnly(-1);
355
356 const PHX::View<const int*> & localCellIds = this->wda(workset).getLocalCellIDs();
357
358 Teuchos::RCP<ProductVectorBase<double> > blockedSolution;
359 if (useTimeDerivativeSolutionVector_)
360 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_dxdt());
361 else
362 blockedSolution = rcp_dynamic_cast<ProductVectorBase<double> >(blockedContainer_->get_x());
363
364 // Loop over fields to gather
365 int currentWorksetLIDSubBlock = -1;
366 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
367 // workset LIDs only change if in different sub blocks
368 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
369 const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
370 const std::string blockId = this->wda(workset).block_id;
371 const int num_dofs = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]]->getElementBlockGIDCount(blockId);
372 blockIndexer->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
373 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
374 }
375
376 const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
377 const auto& subblockSolution = *((rcp_dynamic_cast<Thyra::TpetraVector<RealT,LO,GO,NodeT>>(blockedSolution->getNonconstVectorBlock(blockRowIndex),true))->getTpetraVector());
378 const auto kokkosSolution = subblockSolution.getLocalViewDevice(Tpetra::Access::ReadOnly);
379
380 // Class data fields for lambda capture
381 const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
382 const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
383 const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
384
385 if (has_tangent_fields_) {
386 const int numTangents = tangentFields_[fieldIndex].size();
387 const auto tangentFieldsDevice = tangentFieldsVoV_.getViewDevice();
388 const auto kokkosTangents = Kokkos::subview(tangentFieldsDevice,fieldIndex,Kokkos::ALL());
389 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
390 for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
391 const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
392 fieldValues(cell,basis).zero();
393 fieldValues(cell,basis).val() = kokkosSolution(rowLID,0);
394 for (int i_tangent=0; i_tangent<numTangents; ++i_tangent)
395 fieldValues(cell,basis).fastAccessDx(i_tangent) = kokkosTangents(i_tangent)(cell,basis);
396 }
397 });
398 } else {
399 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
400 for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
401 const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
402 fieldValues(cell,basis).zero();
403 fieldValues(cell,basis) = kokkosSolution(rowLID,0);
404 }
405 });
406 }
407 }
408
409}
410
411// **********************************************************************
412// Specialization: Jacobian
413// **********************************************************************
414
415template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
418 const Teuchos::RCP<const BlockedDOFManager> & indexer,
419 const Teuchos::ParameterList& p)
420 : globalIndexer_(indexer)
421{
423 input.setParameterList(p);
424
425 const std::vector<std::string> & names = input.getDofNames();
426 Teuchos::RCP<const panzer::PureBasis> basis = input.getBasis();
427
428 indexerNames_ = input.getIndexerNames();
429 useTimeDerivativeSolutionVector_ = input.useTimeDerivativeSolutionVector();
430 globalDataKey_ = input.getGlobalDataKey();
431
432 disableSensitivities_ = !input.firstSensitivitiesAvailable();
433
434 gatherFields_.resize(names.size());
435 for (std::size_t fd = 0; fd < names.size(); ++fd) {
436 PHX::MDField<ScalarT,Cell,NODE> f(names[fd],basis->functional);
437 gatherFields_[fd] = f;
438 this->addEvaluatedField(gatherFields_[fd]);
439 }
440
441 // figure out what the first active name is
442 std::string firstName = "<none>";
443 if(names.size()>0)
444 firstName = names[0];
445
446 // print out convenience
447 if(disableSensitivities_) {
448 std::string n = "GatherSolution (BlockedTpetra, No Sensitivities): "+firstName+" (Jacobian)";
449 this->setName(n);
450 }
451 else {
452 std::string n = "GatherSolution (BlockedTpetra): "+firstName+" ("+PHX::print<EvalT>()+") ";
453 this->setName(n);
454 }
455}
456
457// **********************************************************************
458template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
460postRegistrationSetup(typename TRAITS::SetupData d,
462{
463 TEUCHOS_ASSERT(gatherFields_.size() == indexerNames_.size());
464
465 const Workset & workset_0 = (*d.worksets_)[0];
466 const std::string blockId = this->wda(workset_0).block_id;
467
468 fieldIds_.resize(gatherFields_.size());
469 fieldOffsets_.resize(gatherFields_.size());
470 productVectorBlockIndex_.resize(gatherFields_.size());
471 int maxElementBlockGIDCount = -1;
472 for (std::size_t fd = 0; fd < gatherFields_.size(); ++fd) {
473
474 const std::string fieldName = indexerNames_[fd];
475 const int globalFieldNum = globalIndexer_->getFieldNum(fieldName); // Field number in the aggregate BlockDOFManager
476 productVectorBlockIndex_[fd] = globalIndexer_->getFieldBlock(globalFieldNum);
477 const auto& subGlobalIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fd]];
478 fieldIds_[fd] = subGlobalIndexer->getFieldNum(fieldName); // Field number in the sub-global-indexer
479
480 const std::vector<int>& offsets = subGlobalIndexer->getGIDFieldOffsets(blockId,fieldIds_[fd]);
481 fieldOffsets_[fd] = PHX::View<int*>("GatherSolution_BlockedTpetra(Jacobian):fieldOffsets",offsets.size());
482 auto hostOffsets = Kokkos::create_mirror_view(fieldOffsets_[fd]);
483 for (std::size_t i=0; i < offsets.size(); ++i)
484 hostOffsets(i) = offsets[i];
485 Kokkos::deep_copy(fieldOffsets_[fd], hostOffsets);
486 maxElementBlockGIDCount = std::max(subGlobalIndexer->getElementBlockGIDCount(blockId),maxElementBlockGIDCount);
487 }
488
489 // We will use one workset lid view for all fields, but has to be
490 // sized big enough to hold the largest elementBlockGIDCount in the
491 // ProductVector.
492 worksetLIDs_ = PHX::View<LO**>("ScatterResidual_BlockedTpetra(Residual):worksetLIDs",
493 gatherFields_[0].extent(0),
494 maxElementBlockGIDCount);
495
496 // Compute the block offsets
497 const auto& blockGlobalIndexers = globalIndexer_->getFieldDOFManagers();
498 const int numBlocks = static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
499 blockOffsets_ = PHX::View<LO*>("GatherSolution_BlockedTpetra(Jacobian):blockOffsets_",
500 numBlocks+1); // Number of blocks, plus a sentinel
501 const auto hostBlockOffsets = Kokkos::create_mirror_view(blockOffsets_);
502 for (int blk=0;blk<numBlocks;++blk) {
503 int blockOffset = globalIndexer_->getBlockGIDOffset(blockId,blk);
504 hostBlockOffsets(blk) = blockOffset;
505 }
506 hostBlockOffsets(numBlocks) = hostBlockOffsets(numBlocks-1) + blockGlobalIndexers[blockGlobalIndexers.size()-1]->getElementBlockGIDCount(blockId);
507 Kokkos::deep_copy(blockOffsets_,hostBlockOffsets);
508
509 indexerNames_.clear(); // Don't need this anymore
510}
511
512template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
514preEvaluate(typename TRAITS::PreEvalData d)
515{
516 using Teuchos::RCP;
517 using Teuchos::rcp_dynamic_cast;
520
521 solutionBlocks_.clear();
522
523 // First try the refactored read-only container, which is how the model
524 // evaluator supplies the solution. Unwrap each block to its Tpetra vector
525 // here so the gather loop never touches Thyra.
526 const std::string post = useTimeDerivativeSolutionVector_ ? " - Xdot" : " - X";
527 if(d.gedc->containsDataObject(globalDataKey_+post)) {
528 RCP<BVROGED> blockedGed = rcp_dynamic_cast<BVROGED>(d.gedc->getDataObject(globalDataKey_+post),true);
529 const int numBlocks = static_cast<int>(globalIndexer_->getFieldDOFManagers().size());
530 for(int blk=0;blk<numBlocks;++blk)
531 solutionBlocks_.push_back(rcp_dynamic_cast<TVROGED>(blockedGed->getGEDBlock(blk),true)->getGhostedVector_Tpetra());
532
533 return;
534 }
535
536 // Otherwise the solution arrives in a linear object container.
537 blockedContainer_ = rcp_dynamic_cast<const ContainerType>(d.gedc->getDataObject(globalDataKey_),true);
538
539 RCP<const Thyra::VectorBase<double> > blockedSolution = useTimeDerivativeSolutionVector_
540 ? blockedContainer_->get_dxdt()
541 : blockedContainer_->get_x();
542 TEUCHOS_TEST_FOR_EXCEPTION(blockedSolution==Teuchos::null,std::logic_error,
543 "GatherSolution_BlockedTpetra: the container under \"" << globalDataKey_ << "\" holds no "
544 << (useTimeDerivativeSolutionVector_ ? "dxdt" : "x") << " vector to gather from.");
545
546 auto prodSolution = rcp_dynamic_cast<const Thyra::ProductVectorBase<double> >(blockedSolution,true);
547 for(int blk=0;blk<prodSolution->productSpace()->numBlocks();++blk)
548 solutionBlocks_.push_back(rcp_dynamic_cast<const Thyra::TpetraVector<S,LO,GO,NodeT> >(prodSolution->getVectorBlock(blk),true)->getConstTpetraVector());
549}
550
551// **********************************************************************
552template <typename TRAITS,typename S,typename LO,typename GO,typename NodeT>
554evaluateFields(typename TRAITS::EvalData workset)
555{
556 using Teuchos::RCP;
557 using Teuchos::rcp_dynamic_cast;
558 using Thyra::VectorBase;
560
561 const auto& localCellIds = this->wda(workset).cell_local_ids_k;
562
563 RealType seedValue = RealType(0.0);
564 if (useTimeDerivativeSolutionVector_)
565 seedValue = workset.alpha;
566 else
567 seedValue = workset.beta;
568
569 // turn off sensitivies: this may be faster if we don't expand the term
570 // but I suspect not because anywhere it is used the full complement of
571 // sensitivies will be needed anyway.
572 if(disableSensitivities_)
573 seedValue = 0.0;
574
575 // Loop over fields to gather
576 int currentWorksetLIDSubBlock = -1;
577 for (std::size_t fieldIndex = 0; fieldIndex < gatherFields_.size(); fieldIndex++) {
578 // workset LIDs only change if in different sub blocks
579 if (productVectorBlockIndex_[fieldIndex] != currentWorksetLIDSubBlock) {
580 const auto& blockIndexer = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]];
581 const std::string blockId = this->wda(workset).block_id;
582 const int num_dofs = globalIndexer_->getFieldDOFManagers()[productVectorBlockIndex_[fieldIndex]]->getElementBlockGIDCount(blockId);
583 blockIndexer->getElementLIDs(localCellIds,worksetLIDs_,num_dofs);
584 currentWorksetLIDSubBlock = productVectorBlockIndex_[fieldIndex];
585 }
586
587 const int blockRowIndex = productVectorBlockIndex_[fieldIndex];
588 const auto kokkosSolution = solutionBlocks_[blockRowIndex]->getLocalViewDevice(Tpetra::Access::ReadOnly);
589
590 // Class data fields for lambda capture
591 const PHX::View<const int*> fieldOffsets = fieldOffsets_[fieldIndex];
592 const PHX::View<const LO**> worksetLIDs = worksetLIDs_;
593 const PHX::View<ScalarT**> fieldValues = gatherFields_[fieldIndex].get_static_view();
594 const PHX::View<const LO*> blockOffsets = blockOffsets_;
595 auto blockOffsets_h = Kokkos::create_mirror_view(blockOffsets);
596 Kokkos::deep_copy(blockOffsets_h, blockOffsets);
597 const int blockStart = blockOffsets_h(blockRowIndex);
598
599 Kokkos::parallel_for(Kokkos::RangePolicy<PHX::Device>(0,workset.num_cells), KOKKOS_LAMBDA (const int& cell) {
600 for (int basis=0; basis < static_cast<int>(fieldOffsets.size()); ++basis) {
601 const int rowLID = worksetLIDs(cell,fieldOffsets(basis));
602 fieldValues(cell,basis).zero();
603 fieldValues(cell,basis).val() = kokkosSolution(rowLID,0);
604 fieldValues(cell,basis).fastAccessDx(blockStart+fieldOffsets(basis)) = seedValue;
605 }
606 });
607
608 }
609}
610
611// **********************************************************************
612
613#endif
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.
This class encapsulates the needs of a gather operation to do a halo exchange for blocked vectors.
Gathers solution values from the Newton solution vector into the nodal fields of the field manager.
void postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager< TRAITS > &vm)
GatherSolution_BlockedTpetra(const Teuchos::RCP< const BlockedDOFManager > &indexer)
std::string getGlobalDataKey() const
Name of the global evaluation data container to use for the source vector (all types)
void setParameterList(const Teuchos::ParameterList &pl)
const std::vector< std::vector< std::string > > & getTangentNames() const
Get the name of the tangent fields (tangent only)
bool firstSensitivitiesAvailable()
Are first derivative sensitivities enabled or disabled? (Jacobian and Hessian)
bool useTimeDerivativeSolutionVector() const
Gather a time derivative vector? (all types)
const std::vector< std::string > & getIndexerNames() const
Teuchos::RCP< const PureBasis > getBasis() const
Basis definiting layout of dof names (all types)
const std::vector< std::string > & getDofNames() const
The names of the DOFs to be gathered (all types)
std::string block_id
DEPRECATED - use: getElementBlock()