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