Panzer Version of the Day
Loading...
Searching...
No Matches
Panzer_TpetraLinearObjFactory_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_TpetraLinearObjFactory_impl_hpp__
12#define __Panzer_TpetraLinearObjFactory_impl_hpp__
13
14// Panzer
16#ifdef PANZER_HAVE_EPETRA_STACK
17#include "Panzer_EpetraVector_Write_GlobalEvaluationData.hpp" // JMG: Remove this eventually.
18#endif
21
22// Thyra
23#include "Thyra_TpetraVectorSpace.hpp"
24#include "Thyra_TpetraLinearOp.hpp"
25
26// Tpetra
27#include "Tpetra_MultiVector.hpp"
28#include "Tpetra_Vector.hpp"
29#include "Tpetra_CrsMatrix.hpp"
30
31namespace panzer {
32
33using Teuchos::RCP;
34
35// ************************************************************
36// class TpetraLinearObjFactory
37// ************************************************************
38
39template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
41TpetraLinearObjFactory(const Teuchos::RCP<const Teuchos::Comm<int> > & comm,
42 const Teuchos::RCP<const GlobalIndexer> & gidProvider,
43 bool useFEAssembly)
44 : comm_(comm), gidProvider_(gidProvider), useFEAssembly_(useFEAssembly)
45{
46 hasColProvider_ = colGidProvider_!=Teuchos::null;
47
48 // build and register the gather/scatter evaluators with
49 // the base class.
51}
52
53template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
55TpetraLinearObjFactory(const Teuchos::RCP<const Teuchos::Comm<int> > & comm,
56 const Teuchos::RCP<const GlobalIndexer> & gidProvider,
57 const Teuchos::RCP<const GlobalIndexer> & colGidProvider,
58 bool useFEAssembly)
59 : comm_(comm), gidProvider_(gidProvider), colGidProvider_(colGidProvider), useFEAssembly_(useFEAssembly)
60{
61 hasColProvider_ = colGidProvider_!=Teuchos::null;
62
63 // build and register the gather/scatter evaluators with
64 // the base class.
66}
67
68template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
72
73// LinearObjectFactory functions
75
76template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
77Teuchos::RCP<LinearObjContainer>
80{
81 Teuchos::RCP<ContainerType> container = Teuchos::rcp(new ContainerType(getColMap(),getMap()));
82
83 return container;
84}
85
86template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
87Teuchos::RCP<LinearObjContainer>
90{
91 Teuchos::RCP<ContainerType> container = Teuchos::rcp(new ContainerType(getGhostedMap(),getGhostedMap()));
92
93 return container;
94}
95
96template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
97void
100 LinearObjContainer & out,int mem) const
101{
102 using Teuchos::is_null;
103 typedef LinearObjContainer LOC;
104
105 const ContainerType & t_in = Teuchos::dyn_cast<const ContainerType>(in);
106 ContainerType & t_out = Teuchos::dyn_cast<ContainerType>(out);
107
108 // Operations occur if the GLOBAL container has the correct targets!
109 // Users set the GLOBAL continer arguments
110 if ( !is_null(t_in.get_x_mv()) && !is_null(t_out.get_x_mv()) && ((mem & LOC::X)==LOC::X))
111 globalToGhostTpetraVector(*t_in.get_x_mv(),*t_out.get_x_mv(),true);
112
113 if ( !is_null(t_in.get_dxdt_mv()) && !is_null(t_out.get_dxdt_mv()) && ((mem & LOC::DxDt)==LOC::DxDt))
114 globalToGhostTpetraVector(*t_in.get_dxdt_mv(),*t_out.get_dxdt_mv(),true);
115
116 if ( !is_null(t_in.get_f_mv()) && !is_null(t_out.get_f_mv()) && ((mem & LOC::F)==LOC::F))
117 globalToGhostTpetraVector(*t_in.get_f_mv(),*t_out.get_f_mv(),false);
118}
119
120template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
121void
124 LinearObjContainer & out,int mem) const
125{
126 using Teuchos::is_null;
127
128 typedef LinearObjContainer LOC;
129
130 const ContainerType & t_in = Teuchos::dyn_cast<const ContainerType>(in);
131 ContainerType & t_out = Teuchos::dyn_cast<ContainerType>(out);
132
133 // Operations occur if the GLOBAL container has the correct targets!
134 // Users set the GLOBAL continer arguments
135 if ( !is_null(t_in.get_x_mv()) && !is_null(t_out.get_x_mv()) && ((mem & LOC::X)==LOC::X))
136 ghostToGlobalTpetraVector(*t_in.get_x_mv(),*t_out.get_x_mv(),true);
137
138 if ( !is_null(t_in.get_f_mv()) && !is_null(t_out.get_f_mv()) && ((mem & LOC::F)==LOC::F))
139 ghostToGlobalTpetraVector(*t_in.get_f_mv(),*t_out.get_f_mv(),false);
140
141 // In FE mode the ghosted and global containers hold the SAME FECrsMatrix, so there is
142 // nothing to export here: the owned+shared -> owned migration is done in place by
143 // endAssembly() (driven from endFill()). Exporting an object into itself would at best
144 // be wasted work and at worst corrupt the values, so skip it. The pointer comparison
145 // deliberately keys off object identity rather than the useFEAssembly_ flag, so a
146 // container the caller populated by hand still behaves predictably.
147 if ( !is_null(t_in.get_A()) && !is_null(t_out.get_A()) && ((mem & LOC::Mat)==LOC::Mat)
148 && t_in.get_A().get()!=t_out.get_A().get())
149 ghostToGlobalTpetraMatrix(*t_in.get_A(),*t_out.get_A());
150}
151
152template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
153void
155ghostToGlobalTpetraVector(const Tpetra::MultiVector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> & in,
156 Tpetra::MultiVector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> & out, bool col) const
157{
158 using Teuchos::RCP;
159
160 // do the global distribution
161 RCP<ExportType> exporter = col ? getGhostedColExport() : getGhostedExport();
162 out.putScalar(0.0);
163 out.doExport(in,*exporter,Tpetra::ADD);
164}
165
166template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
167void
169ghostToGlobalTpetraMatrix(const Tpetra::CrsMatrix<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> & in,
170 Tpetra::CrsMatrix<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> & out) const
171{
172 using Teuchos::RCP;
173
174 // do the global distribution
175 RCP<ExportType> exporter = getGhostedExport();
176
177 out.resumeFill();
178 out.setAllToScalar(0.0);
179 out.doExport(in,*exporter,Tpetra::ADD);
180 out.fillComplete(out.getDomainMap(),out.getRangeMap());
181}
182
183template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
184void
186globalToGhostTpetraVector(const Tpetra::MultiVector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> & in,
187 Tpetra::MultiVector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> & out, bool col) const
188{
189 using Teuchos::RCP;
190
191 // do the global distribution
192 RCP<ImportType> importer = col ? getGhostedColImport() : getGhostedImport();
193 out.putScalar(0.0);
194 out.doImport(in,*importer,Tpetra::INSERT);
195}
196
197template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
198void
201 const LinearObjContainer & globalBCRows,
202 LinearObjContainer & ghostedObjs,
203 bool zeroVectorRows, bool adjustX) const
204{
205 typedef Teuchos::ArrayRCP<const double>::Ordinal Ordinal;
206
207 const ContainerType & t_localBCRows = Teuchos::dyn_cast<const ContainerType>(localBCRows);
208 const ContainerType & t_globalBCRows = Teuchos::dyn_cast<const ContainerType>(globalBCRows);
209 ContainerType & t_ghosted = Teuchos::dyn_cast<ContainerType>(ghostedObjs);
210
211 TEUCHOS_ASSERT(!Teuchos::is_null(t_localBCRows.get_f_mv()));
212 TEUCHOS_ASSERT(!Teuchos::is_null(t_globalBCRows.get_f_mv()));
213
214 // pull out jacobian and vector
215 Teuchos::RCP<CrsMatrixType> A = t_ghosted.get_A();
216 Teuchos::RCP<MultiVectorType> f = t_ghosted.get_f_mv();
217 if(adjustX) f = t_ghosted.get_x_mv();
218 Teuchos::ArrayRCP<double> f_array = f!=Teuchos::null ? f->get1dViewNonConst() : Teuchos::null;
219
220 const MultiVectorType & local_bcs = *(t_localBCRows.get_f_mv());
221 const MultiVectorType & global_bcs = *(t_globalBCRows.get_f_mv());
222 Teuchos::ArrayRCP<const double> local_bcs_array = local_bcs.get1dView();
223 Teuchos::ArrayRCP<const double> global_bcs_array = global_bcs.get1dView();
224
225 TEUCHOS_ASSERT(local_bcs_array.size()==global_bcs_array.size());
226 for(Ordinal i=0;i<local_bcs_array.size();i++) {
227 if(global_bcs_array[i]==0.0)
228 continue;
229
230 if(local_bcs_array[i]==0.0 || zeroVectorRows) {
231 // this boundary condition was NOT set by this processor
232
233 // if they exist put 0.0 in each entry
234 if(!Teuchos::is_null(f))
235 f_array[i] = 0.0;
236 if(!Teuchos::is_null(A)) {
237 std::size_t numEntries = 0;
238 std::size_t sz = A->getNumEntriesInLocalRow(i);
239 typename CrsMatrixType::nonconst_local_inds_host_view_type indices("indices", sz);
240 typename CrsMatrixType::nonconst_values_host_view_type values("values", sz);
241
242 A->getLocalRowCopy(i,indices,values,numEntries);
243
244 for(std::size_t c=0;c<numEntries;c++)
245 values(c) = 0.0;
246
247 A->replaceLocalValues(i,indices,values);
248 }
249 }
250 else {
251 // this boundary condition was set by this processor
252
253 double scaleFactor = global_bcs_array[i];
254
255 // if they exist scale linear objects by scale factor
256 if(!Teuchos::is_null(f))
257 f_array[i] /= scaleFactor;
258 if(!Teuchos::is_null(A)) {
259 std::size_t numEntries = 0;
260 std::size_t sz = A->getNumEntriesInLocalRow(i);
261 typename CrsMatrixType::nonconst_local_inds_host_view_type indices("indices", sz);
262 typename CrsMatrixType::nonconst_values_host_view_type values("values", sz);
263
264 A->getLocalRowCopy(i,indices,values,numEntries);
265
266 for(std::size_t c=0;c<numEntries;c++)
267 values(c) /= scaleFactor;
268
269 A->replaceLocalValues(i,indices,values);
270 }
271 }
272 }
273}
274
275template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
276void
278applyDirichletBCs(const LinearObjContainer & /* counter */,
279 LinearObjContainer & /* result */) const
280{
281 TEUCHOS_ASSERT(false); // not yet implemented
282}
283
285//
286// buildReadOnlyDomainContainer()
287//
289template<typename Traits, typename ScalarT, typename LocalOrdinalT,
290 typename GlobalOrdinalT, typename NodeT>
291Teuchos::RCP<ReadOnlyVector_GlobalEvaluationData>
294{
295 using Teuchos::rcp;
296 using TVROGED = TpetraVector_ReadOnly_GlobalEvaluationData<ScalarT,
297 LocalOrdinalT, GlobalOrdinalT, NodeT>;
298 auto ged = rcp(new TVROGED);
299 ged->initialize(getGhostedColImport(), getGhostedColMap(), getColMap());
300 return ged;
301} // end of buildReadOnlyDomainContainer()
302
303#ifdef PANZER_HAVE_EPETRA_STACK
305//
306// buildWriteDomainContainer()
307//
309template<typename Traits, typename ScalarT, typename LocalOrdinalT,
310 typename GlobalOrdinalT, typename NodeT>
311Teuchos::RCP<WriteVector_GlobalEvaluationData>
314{
315 using std::logic_error;
316 using Teuchos::rcp;
318 auto ged = rcp(new EVWGED);
319 TEUCHOS_TEST_FOR_EXCEPTION(true, logic_error, "NOT IMPLEMENTED YET")
320 return ged;
321} // end of buildWriteDomainContainer()
322#endif // PANZER_HAVE_EPETRA_STACK
323
324template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
326getComm() const
327{
328 return *Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(getTeuchosComm());
329}
330
332template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
333Teuchos::RCP<const Thyra::VectorSpaceBase<ScalarT> >
336{
337 if(domainSpace_==Teuchos::null) {
338 if(!hasColProvider_)
339 domainSpace_ = Thyra::tpetraVectorSpace<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>(getMap());
340 else
341 domainSpace_ = Thyra::tpetraVectorSpace<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>(getColMap());
342 }
343
344 return domainSpace_;
345}
346
348template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
349Teuchos::RCP<const Thyra::VectorSpaceBase<ScalarT> >
352{
353 if(ghostedDomainSpace_==Teuchos::null) {
354 if(!hasColProvider_)
355 ghostedDomainSpace_ = Thyra::tpetraVectorSpace<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>(getGhostedMap());
356 else
357 ghostedDomainSpace_ = Thyra::tpetraVectorSpace<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>(getGhostedColMap());
358 }
359
360 return ghostedDomainSpace_;
361}
362
364template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
365Teuchos::RCP<const Thyra::VectorSpaceBase<ScalarT> >
367getThyraRangeSpace() const
368{
369 if(rangeSpace_==Teuchos::null)
370 rangeSpace_ = Thyra::tpetraVectorSpace<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>(getMap());
371
372 return rangeSpace_;
373}
374
376template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
377Teuchos::RCP<Thyra::LinearOpBase<ScalarT> >
379getThyraMatrix() const
380{
381 return Thyra::tpetraLinearOp<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>(getThyraRangeSpace(),getThyraDomainSpace(),getTpetraMatrix());
382}
383
384// Functions for initalizing a container
386
387template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
388void
390initializeContainer(int mem,LinearObjContainer & loc) const
391{
392 ContainerType & tloc = Teuchos::dyn_cast<ContainerType>(loc);
393 initializeContainer(mem,tloc);
394}
395
396template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
397void
400{
401 typedef LinearObjContainer LOC;
402
403 loc.clear();
404
405 if((mem & LOC::X) == LOC::X)
406 loc.set_x(getTpetraColVector());
407
408 if((mem & LOC::DxDt) == LOC::DxDt)
409 loc.set_dxdt(getTpetraColVector());
410
411 if((mem & LOC::F) == LOC::F)
412 loc.set_f(getTpetraVector());
413
414 if((mem & LOC::Mat) == LOC::Mat)
415 loc.set_A(getTpetraMatrix());
416}
417
418template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
419void
422{
423 ContainerType & tloc = Teuchos::dyn_cast<ContainerType>(loc);
424 initializeGhostedContainer(mem,tloc);
425}
426
427template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
428void
431{
432 typedef LinearObjContainer LOC;
433
434 loc.clear();
435
436 if((mem & LOC::X) == LOC::X)
437 loc.set_x(getGhostedTpetraColVector());
438
439 if((mem & LOC::DxDt) == LOC::DxDt)
440 loc.set_dxdt(getGhostedTpetraColVector());
441
442 if((mem & LOC::F) == LOC::F) {
443 loc.set_f(getGhostedTpetraVector());
445 }
446
447 if((mem & LOC::Mat) == LOC::Mat) {
448 // Under FE assembly the ghosted container owns no matrix; beginFill(ghosted,owned)
449 // points it at the owned container's FECrsMatrix for the duration of the assembly.
450 if(!useFEAssembly_)
451 loc.set_A(getGhostedTpetraMatrix());
453 }
454}
455
456// "Get" functions
458
459// get the map from the matrix
460template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
461const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
463getMap() const
464{
465 if(map_==Teuchos::null) map_ = buildMap();
466
467 return map_;
468}
469
470// get the map from the matrix
471template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
472const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
474getColMap() const
475{
476 if(cMap_==Teuchos::null) cMap_ = buildColMap();
477
478 return cMap_;
479}
480
481template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
482const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
484getGhostedMap() const
485{
486 if(ghostedMap_==Teuchos::null) ghostedMap_ = buildGhostedMap();
487
488 return ghostedMap_;
489}
490
491template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
492const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
494getGhostedColMap() const
495{
496 if(cGhostedMap_==Teuchos::null) cGhostedMap_ = buildGhostedColMap();
497
498 return cGhostedMap_;
499}
500
501// get the graph of the crs matrix
502template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
503const Teuchos::RCP<Tpetra::CrsGraph<LocalOrdinalT,GlobalOrdinalT,NodeT> >
505getGraph() const
506{
507 if(graph_==Teuchos::null) graph_ = buildGraph();
508
509 return graph_;
510}
511
512template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
513const Teuchos::RCP<Tpetra::CrsGraph<LocalOrdinalT,GlobalOrdinalT,NodeT> >
515getGhostedGraph() const
516{
517 if(ghostedGraph_==Teuchos::null) ghostedGraph_ = buildGhostedGraph();
518
519 return ghostedGraph_;
520}
521
522template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
523Teuchos::RCP<typename TpetraLinearObjFactory<Traits,ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>::FECrsGraphType>
525getFEGraph() const
526{
527 TEUCHOS_TEST_FOR_EXCEPTION(!useFEAssembly_,std::logic_error,
528 "TpetraLinearObjFactory::getFEGraph: This factory was not constructed with "
529 "useFEAssembly=true, so FE (Tpetra::FECrsGraph/FECrsMatrix/FEMultiVector) objects "
530 "are not available. Pass useFEAssembly=true to the constructor to opt in.");
531
532 if(feGraph_==Teuchos::null) feGraph_ = buildFEGraph();
533
534 return feGraph_;
535}
536
537template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
538const Teuchos::RCP<Tpetra::Import<LocalOrdinalT,GlobalOrdinalT,NodeT> >
540getGhostedImport() const
541{
542 if(ghostedImporter_==Teuchos::null)
543 ghostedImporter_ = Teuchos::rcp(new ImportType(getMap(),getGhostedMap()));
544
545 return ghostedImporter_;
546}
547
548template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
549const Teuchos::RCP<Tpetra::Import<LocalOrdinalT,GlobalOrdinalT,NodeT> >
552{
553 if(!hasColProvider_)
554 ghostedColImporter_ = getGhostedImport(); // they are the same in this case
555
556 if(ghostedColImporter_==Teuchos::null)
557 ghostedColImporter_ = Teuchos::rcp(new ImportType(getColMap(),getGhostedColMap()));
558
559 return ghostedColImporter_;
560}
561
562template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
563const Teuchos::RCP<Tpetra::Export<LocalOrdinalT,GlobalOrdinalT,NodeT> >
565getGhostedExport() const
566{
567 if(ghostedExporter_==Teuchos::null)
568 ghostedExporter_ = Teuchos::rcp(new ExportType(getGhostedMap(),getMap()));
569
570 return ghostedExporter_;
571}
572
573template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
574const Teuchos::RCP<Tpetra::Export<LocalOrdinalT,GlobalOrdinalT,NodeT> >
577{
578 if(!hasColProvider_)
579 ghostedColExporter_ = getGhostedExport(); // they are the same in this case
580
581 if(ghostedColExporter_==Teuchos::null)
582 ghostedColExporter_ = Teuchos::rcp(new ExportType(getGhostedColMap(),getColMap()));
583
584 return ghostedColExporter_;
585}
586
587// "Build" functions
589
590template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
591const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
593buildMap() const
594{
595 std::vector<GlobalOrdinalT> indices;
596
597 // get the global indices
598 gidProvider_->getOwnedIndices(indices);
599
600 return Teuchos::rcp(new MapType(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(),indices,0,comm_));
601}
602
603template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
604const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
606buildColMap() const
607{
608 if(!hasColProvider_)
609 return buildMap();
610
611 std::vector<GlobalOrdinalT> indices;
612
613 // get the global indices
614 colGidProvider_->getOwnedIndices(indices);
615
616 return Teuchos::rcp(new MapType(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(),indices,0,comm_));
617}
618
619// build the ghosted map
620template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
621const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
623buildGhostedMap() const
624{
625 std::vector<GlobalOrdinalT> indices;
626
627 // get the global indices
628 gidProvider_->getOwnedAndGhostedIndices(indices);
629
630 return Teuchos::rcp(new MapType(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(),indices,0,comm_));
631}
632
633// build the ghosted map
634template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
635const Teuchos::RCP<Tpetra::Map<LocalOrdinalT,GlobalOrdinalT,NodeT> >
637buildGhostedColMap() const
638{
639 if(!hasColProvider_)
640 return buildGhostedMap();
641
642 std::vector<GlobalOrdinalT> indices;
643
644 // get the global indices
645 colGidProvider_->getOwnedAndGhostedIndices(indices);
646
647 return Teuchos::rcp(new MapType(Teuchos::OrdinalTraits<GlobalOrdinalT>::invalid(),indices,0,comm_));
648}
649
650// get the graph of the crs matrix
651template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
652const Teuchos::RCP<Tpetra::CrsGraph<LocalOrdinalT,GlobalOrdinalT,NodeT> >
654buildGraph() const
655{
656 using Teuchos::RCP;
657 using Teuchos::rcp;
658
659 // build the map and allocate the space for the graph and
660 // grab the ghosted graph
661 RCP<MapType> rMap = getMap();
662 RCP<MapType> cMap = getColMap();
663 RCP<CrsGraphType> graph = rcp(new CrsGraphType(rMap,0));
664 RCP<CrsGraphType> oGraph = getGhostedGraph();
665
666 // perform the communication to finish building graph
667 RCP<ExportType> exporter = getGhostedExport();
668 graph->doExport( *oGraph, *exporter, Tpetra::INSERT );
669 graph->fillComplete(cMap,rMap);
670
671 return graph;
672}
673
674template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
675const Teuchos::RCP<Tpetra::CrsGraph<LocalOrdinalT,GlobalOrdinalT,NodeT> >
677buildGhostedGraph() const
678{
679 // build the map and allocate the space for the graph
680 Teuchos::RCP<MapType> rMap = getGhostedMap();
681 Teuchos::RCP<MapType> cMap = getGhostedColMap();
682
683 std::vector<std::string> elementBlockIds;
684 gidProvider_->getElementBlockIds(elementBlockIds);
685
686 const Teuchos::RCP<const GlobalIndexer>
687 colGidProvider = hasColProvider_ ? colGidProvider_ : gidProvider_;
688 const Teuchos::RCP<const ConnManager> conn_mgr = colGidProvider->getConnManager();
689 const bool han = conn_mgr.is_null() ? false : conn_mgr->hasAssociatedNeighbors();
690
691 // graph information about the mesh
692 // Count number of entries per graph row; needed for graph constructor
693 std::vector<size_t> nEntriesPerRow(rMap->getLocalNumElements(), 0);
694
695 std::vector<std::string>::const_iterator blockItr;
696 for(blockItr=elementBlockIds.begin();blockItr!=elementBlockIds.end();++blockItr) {
697 std::string blockId = *blockItr;
698
699 // grab elements for this block
700 const std::vector<LocalOrdinalT> & elements = gidProvider_->getElementBlock(blockId);
701
702 // get information about number of indicies
703 std::vector<GlobalOrdinalT> gids;
704 std::vector<GlobalOrdinalT> col_gids;
705
706 // loop over the elemnts
707 for(std::size_t i=0;i<elements.size();i++) {
708 gidProvider_->getElementGIDs(elements[i],gids);
709
710 colGidProvider->getElementGIDs(elements[i],col_gids);
711 if (han) {
712 const std::vector<LocalOrdinalT>& aes = conn_mgr->getAssociatedNeighbors(elements[i]);
713 for (typename std::vector<LocalOrdinalT>::const_iterator eit = aes.begin();
714 eit != aes.end(); ++eit) {
715 std::vector<GlobalOrdinalT> other_col_gids;
716 colGidProvider->getElementGIDs(*eit, other_col_gids);
717 col_gids.insert(col_gids.end(), other_col_gids.begin(), other_col_gids.end());
718 }
719 }
720
721 for(std::size_t j=0;j<gids.size();j++){
722 LocalOrdinalT lid = rMap->getLocalElement(gids[j]);
723 nEntriesPerRow[lid] += col_gids.size();
724 }
725 }
726 }
727
728 Teuchos::ArrayView<const size_t> nEntriesPerRowView(nEntriesPerRow);
729 Teuchos::RCP<CrsGraphType> graph = Teuchos::rcp(new CrsGraphType(rMap,cMap,
730 nEntriesPerRowView));
731
732 // Now insert entries into the graph
733 for(blockItr=elementBlockIds.begin();blockItr!=elementBlockIds.end();++blockItr) {
734 std::string blockId = *blockItr;
735
736 // grab elements for this block
737 const std::vector<LocalOrdinalT> & elements = gidProvider_->getElementBlock(blockId);
738
739 // get information about number of indicies
740 std::vector<GlobalOrdinalT> gids;
741 std::vector<GlobalOrdinalT> col_gids;
742
743 // loop over the elemnts
744 for(std::size_t i=0;i<elements.size();i++) {
745 gidProvider_->getElementGIDs(elements[i],gids);
746
747 colGidProvider->getElementGIDs(elements[i],col_gids);
748 if (han) {
749 const std::vector<LocalOrdinalT>& aes = conn_mgr->getAssociatedNeighbors(elements[i]);
750 for (typename std::vector<LocalOrdinalT>::const_iterator eit = aes.begin();
751 eit != aes.end(); ++eit) {
752 std::vector<GlobalOrdinalT> other_col_gids;
753 colGidProvider->getElementGIDs(*eit, other_col_gids);
754 col_gids.insert(col_gids.end(), other_col_gids.begin(), other_col_gids.end());
755 }
756 }
757
758 for(std::size_t j=0;j<gids.size();j++)
759 graph->insertGlobalIndices(gids[j],col_gids);
760 }
761 }
762
763 // finish filling the graph
764 graph->fillComplete(cMap,rMap);
765
766 return graph;
767}
768
769// build the FE graph: same element/associated-neighbor traversal as buildGhostedGraph(),
770// but inserted into a single Tpetra::FECrsGraph (V2 constructor) instead of two separate
771// CrsGraph objects joined by a manual doExport.
772//
773// NOTE: Tpetra::FECrsGraph::setup() requires the owned row/domain map's global ids to
774// appear, in the same order, as a leading prefix of the owned+shared row/domain map. This
775// holds by construction for every concrete panzer::GlobalIndexer in the tree (DOFManager
776// and Filtered_GlobalIndexer both build getOwnedAndGhostedIndices() as owned_ followed by
777// ghosted_), so getGhostedMap()/getGhostedColMap() can be used directly here.
778template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
779const Teuchos::RCP<typename TpetraLinearObjFactory<Traits,ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>::FECrsGraphType>
781buildFEGraph() const
782{
783 // row maps are always the unique/ghosted row maps; domain maps must go through
784 // the column-provider-aware accessors so the blocked/rectangular case still works
785 //
786 // NOTE: these must be RCP<const MapType> (not RCP<MapType>). FECrsGraph has both a
787 // "V1" ctor (4th positional arg = importer) and "V2" ctor (4th positional arg =
788 // ownedPlusSharedDomainMap); Teuchos::RCP's converting constructor is an unconstrained
789 // template, so an RCP<MapType> argument is equally "convertible" to RCP<const ImportType>
790 // and RCP<const MapType> as far as overload resolution is concerned, making the call
791 // ambiguous. Typing the locals as RCP<const MapType> makes them bind to the V2 domain-map
792 // parameter with no conversion at all, which resolves the ambiguity in V2's favor.
793 Teuchos::RCP<const MapType> rMap = getMap();
794 Teuchos::RCP<const MapType> ownedAndGhostedRowMap = getGhostedMap();
795 Teuchos::RCP<const MapType> ownedDomainMap = getColMap();
796 Teuchos::RCP<const MapType> ownedAndGhostedDomainMap = getGhostedColMap();
797
798 std::vector<std::string> elementBlockIds;
799 gidProvider_->getElementBlockIds(elementBlockIds);
800
801 const Teuchos::RCP<const GlobalIndexer>
802 colGidProvider = hasColProvider_ ? colGidProvider_ : gidProvider_;
803 const Teuchos::RCP<const ConnManager> conn_mgr = colGidProvider->getConnManager();
804 const bool han = conn_mgr.is_null() ? false : conn_mgr->hasAssociatedNeighbors();
805
806 // count number of entries per ghosted row, exactly as buildGhostedGraph() does
807 std::vector<size_t> nEntriesPerRow(ownedAndGhostedRowMap->getLocalNumElements(), 0);
808
809 std::vector<std::string>::const_iterator blockItr;
810 for(blockItr=elementBlockIds.begin();blockItr!=elementBlockIds.end();++blockItr) {
811 std::string blockId = *blockItr;
812
813 const std::vector<LocalOrdinalT> & elements = gidProvider_->getElementBlock(blockId);
814
815 std::vector<GlobalOrdinalT> gids;
816 std::vector<GlobalOrdinalT> col_gids;
817
818 for(std::size_t i=0;i<elements.size();i++) {
819 gidProvider_->getElementGIDs(elements[i],gids);
820
821 colGidProvider->getElementGIDs(elements[i],col_gids);
822 if (han) {
823 const std::vector<LocalOrdinalT>& aes = conn_mgr->getAssociatedNeighbors(elements[i]);
824 for (typename std::vector<LocalOrdinalT>::const_iterator eit = aes.begin();
825 eit != aes.end(); ++eit) {
826 std::vector<GlobalOrdinalT> other_col_gids;
827 colGidProvider->getElementGIDs(*eit, other_col_gids);
828 col_gids.insert(col_gids.end(), other_col_gids.begin(), other_col_gids.end());
829 }
830 }
831
832 for(std::size_t j=0;j<gids.size();j++){
833 LocalOrdinalT lid = ownedAndGhostedRowMap->getLocalElement(gids[j]);
834 nEntriesPerRow[lid] += col_gids.size();
835 }
836 }
837 }
838
839 size_t maxNumRowEntries = 0;
840 for(std::size_t i=0;i<nEntriesPerRow.size();i++)
841 maxNumRowEntries = std::max(maxNumRowEntries,nEntriesPerRow[i]);
842
843 // V2 constructor: Panzer partitions by element/cell, so we must supply the owned+shared
844 // domain map explicitly to guarantee the ghosted GlobalIndexer's local ids coincide with
845 // the FE graph's column-map local ids (see Tpetra_FECrsGraph_decl.hpp doxygen).
846 Teuchos::RCP<FECrsGraphType> feGraph = Teuchos::rcp(new FECrsGraphType(
847 rMap, ownedAndGhostedRowMap, maxNumRowEntries,
848 ownedAndGhostedDomainMap,
849 Teuchos::null,
850 ownedDomainMap));
851
852 // Panzer's DOFManager does not guarantee a locally owned element has an owned dof, so
853 // Tpetra's debug-only check for that is too strict here; the cost is at most a structurally
854 // empty column. Must be set after construction -- the ctor's validator rejects the option.
855 {
856 Teuchos::RCP<Teuchos::ParameterList> feGraphParams = Teuchos::parameterList();
857 feGraphParams->set("Check Col GIDs In At Least One Owned Row",false);
858 feGraph->setParameterList(feGraphParams);
859 }
860
861 // Now insert entries into the graph
862 feGraph->beginAssembly();
863 for(blockItr=elementBlockIds.begin();blockItr!=elementBlockIds.end();++blockItr) {
864 std::string blockId = *blockItr;
865
866 const std::vector<LocalOrdinalT> & elements = gidProvider_->getElementBlock(blockId);
867
868 std::vector<GlobalOrdinalT> gids;
869 std::vector<GlobalOrdinalT> col_gids;
870
871 for(std::size_t i=0;i<elements.size();i++) {
872 gidProvider_->getElementGIDs(elements[i],gids);
873
874 colGidProvider->getElementGIDs(elements[i],col_gids);
875 if (han) {
876 const std::vector<LocalOrdinalT>& aes = conn_mgr->getAssociatedNeighbors(elements[i]);
877 for (typename std::vector<LocalOrdinalT>::const_iterator eit = aes.begin();
878 eit != aes.end(); ++eit) {
879 std::vector<GlobalOrdinalT> other_col_gids;
880 colGidProvider->getElementGIDs(*eit, other_col_gids);
881 col_gids.insert(col_gids.end(), other_col_gids.begin(), other_col_gids.end());
882 }
883 }
884
885 for(std::size_t j=0;j<gids.size();j++)
886 feGraph->insertGlobalIndices(gids[j],col_gids);
887 }
888 }
889 feGraph->endAssembly();
890
891 return feGraph;
892}
893
894template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
895Teuchos::RCP<Tpetra::Vector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> >
898{
899 Teuchos::RCP<const MapType> tMap = getGhostedMap();
900 return Teuchos::rcp(new VectorType(tMap));
901}
902
903template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
904Teuchos::RCP<Tpetra::Vector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> >
907{
908 Teuchos::RCP<const MapType> tMap = getGhostedColMap();
909 return Teuchos::rcp(new VectorType(tMap));
910}
911
912template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
913Teuchos::RCP<Tpetra::Vector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> >
915getTpetraVector() const
916{
917 Teuchos::RCP<const MapType> tMap = getMap();
918 return Teuchos::rcp(new VectorType(tMap));
919}
920
921template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
922Teuchos::RCP<Tpetra::Vector<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> >
924getTpetraColVector() const
925{
926 Teuchos::RCP<const MapType> tMap = getColMap();
927 return Teuchos::rcp(new VectorType(tMap));
928}
929
930template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
931Teuchos::RCP<Tpetra::CrsMatrix<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> >
933getTpetraMatrix() const
934{
935 // In FE mode hand back an FECrsMatrix. This is what makes the FE path work end-to-end:
936 // panzer::ModelEvaluator::create_W_op() calls getThyraMatrix() -> here, so the operator
937 // NOX/Piro allocates and hands back as W_out IS an FE matrix (wrapped in Thyra).
938 // set_A_th() then dynamic_casts it back down to CrsMatrixType, which succeeds because
939 // FECrsMatrix IS-A CrsMatrix. The ghosted container borrows whichever one it is handed
940 // at beginFill(), giving the "one object, two views" model FECrsMatrix is built around:
941 // endAssembly() migrates owned+shared -> owned in place, with no separate ghost->global
942 // matrix export needed.
943 if(useFEAssembly_)
944 return getFEMatrix();
945
946 Teuchos::RCP<CrsGraphType> tGraph = getGraph();
947 Teuchos::RCP<CrsMatrixType> tMat = Teuchos::rcp(new CrsMatrixType(tGraph));
948 tMat->fillComplete(tMat->getDomainMap(),tMat->getRangeMap());
949
950 return tMat;
951}
952
953template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
954Teuchos::RCP<Tpetra::CrsMatrix<ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT> >
957{
958 // There is no separate ghosted matrix under FE assembly: a ghosted container borrows the
959 // owned container's FECrsMatrix at beginFill(), whose owned+shared view already spans
960 // getGhostedMap(). Returning a standalone matrix here would look usable but silently
961 // drop every ghost contribution, so refuse instead.
962 TEUCHOS_TEST_FOR_EXCEPTION(useFEAssembly_,std::logic_error,
963 "TpetraLinearObjFactory::getGhostedTpetraMatrix: not available under FE assembly. "
964 "The ghosted container shares the owned container's Tpetra::FECrsMatrix, which is "
965 "connected by beginFill(ghosted,owned); use getFEMatrix() to allocate one.");
966
967 Teuchos::RCP<CrsGraphType> tGraph = getGhostedGraph();
968 Teuchos::RCP<CrsMatrixType> tMat = Teuchos::rcp(new CrsMatrixType(tGraph));
969 tMat->fillComplete(tMat->getDomainMap(),tMat->getRangeMap());
970
971 return tMat;
972}
973
974template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
975Teuchos::RCP<typename TpetraLinearObjFactory<Traits,ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>::FECrsMatrixType>
977getFEMatrix() const
978{
979 TEUCHOS_TEST_FOR_EXCEPTION(!useFEAssembly_,std::logic_error,
980 "TpetraLinearObjFactory::getFEMatrix: This factory was not constructed with "
981 "useFEAssembly=true, so FE (Tpetra::FECrsGraph/FECrsMatrix/FEMultiVector) objects "
982 "are not available. Pass useFEAssembly=true to the constructor to opt in.");
983
984 // A fresh matrix per call, like getTpetraMatrix()/getGhostedTpetraMatrix(). The graph
985 // behind them is shared and cached, so this is only the values allocation.
986 return Teuchos::rcp(new FECrsMatrixType(getFEGraph()));
987}
988
989template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
990Teuchos::RCP<typename TpetraLinearObjFactory<Traits,ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>::FEMultiVectorType>
992getFEMultiVector(std::size_t numVectors) const
993{
994 TEUCHOS_TEST_FOR_EXCEPTION(!useFEAssembly_,std::logic_error,
995 "TpetraLinearObjFactory::getFEMultiVector: This factory was not constructed with "
996 "useFEAssembly=true, so FE (Tpetra::FECrsGraph/FECrsMatrix/FEMultiVector) objects "
997 "are not available. Pass useFEAssembly=true to the constructor to opt in.");
998
999 // Built over getGhostedImport() (owned map -> ghosted ROW map), NOT the FE graph's own
1000 // importer. Tpetra's FEMultiVector documentation suggests the graph importer as the
1001 // "canonical" choice, and the Tpetra example does that, but its target is the graph's
1002 // COLUMN map -- which the cross-rank clique merge widens beyond the ghosted row map. A
1003 // residual is indexed by ROW local ids (what GlobalIndexer::getLIDs() yields) and is
1004 // migrated by getGhostedExport(), whose source map is getGhostedMap(); a column-map
1005 // vector matches neither. It only appears to work because the ghosted map is a locally
1006 // fitted prefix of the column map, so row lids happen to land correctly and the extra
1007 // trailing entries are simply never written -- fragile, and wrong for the export.
1008 return Teuchos::rcp(new FEMultiVectorType(getMap(),getGhostedImport(),numVectors));
1009}
1010
1011template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
1012Teuchos::RCP<typename TpetraLinearObjFactory<Traits,ScalarT,LocalOrdinalT,GlobalOrdinalT,NodeT>::FEMultiVectorType>
1014getFEColMultiVector(std::size_t numVectors) const
1015{
1016 TEUCHOS_TEST_FOR_EXCEPTION(!useFEAssembly_,std::logic_error,
1017 "TpetraLinearObjFactory::getFEColMultiVector: This factory was not constructed with "
1018 "useFEAssembly=true, so FE (Tpetra::FECrsGraph/FECrsMatrix/FEMultiVector) objects "
1019 "are not available. Pass useFEAssembly=true to the constructor to opt in.");
1020
1021 // Domain-space counterpart of getFEMultiVector(): owned col map -> ghosted col map.
1022 // Both accessors collapse to the row-map versions when there is no separate column
1023 // GlobalIndexer, since getColMap()/getGhostedColMap() fall back to the row maps.
1024 return Teuchos::rcp(new FEMultiVectorType(getColMap(),getGhostedColImport(),numVectors));
1025}
1026
1027template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
1028const Teuchos::RCP<const Teuchos::Comm<int> >
1034
1035template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
1037beginFill(LinearObjContainer & ghostContainer,const LinearObjContainer & container) const
1038{
1039 // Under FE assembly the ghosted container carries no matrix of its own: hand it the owned
1040 // container's, so local assembly writes into the owned+shared view of the very matrix
1041 // endAssembly() will migrate. Doing this here rather than when the container is built is
1042 // what lets the Jacobian be whichever matrix the caller supplies -- panzer::ModelEvaluator
1043 // sets the owned container's operator from W_out on every evaluation, so it is not known
1044 // any earlier, and a factory-cached matrix would alias every W_out to the first one.
1045 if(useFEAssembly_) {
1046 const ContainerType & ownedLoc = Teuchos::dyn_cast<const ContainerType>(container);
1047 if(ownedLoc.get_A()!=Teuchos::null)
1048 Teuchos::dyn_cast<ContainerType>(ghostContainer).set_A(ownedLoc.get_A());
1049 }
1050
1051 beginFill(ghostContainer);
1052}
1053
1054template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
1056beginFill(LinearObjContainer & loc) const
1057{
1058 ContainerType & tloc = Teuchos::dyn_cast<ContainerType>(loc);
1059 Teuchos::RCP<CrsMatrixType> A = tloc.get_A();
1060 if(A!=Teuchos::null) {
1061 // If A is actually an FECrsMatrix, calling the plain CrsMatrix::resumeFill()
1062 // (inherited, unoverridden) would silently bypass FECrsMatrix's own owned/owned+shared
1063 // state machine -- ghost-row contributions accumulated during local assembly would
1064 // never get migrated to the owned rows. Must go through beginAssembly() instead.
1065 //
1066 // The guard matters because in FE mode the owned and ghosted containers hold the SAME
1067 // FECrsMatrix, and AssemblyEngine::evaluate() calls beginFill() on both (ghosted first,
1068 // then the global container). FECrsMatrix::beginAssembly() asserts its fill state is
1069 // "closed", so the second call would throw; tracking which matrix already has an
1070 // assembly open collapses the pair into the single begin the FE state machine expects.
1071 // See feAssemblyOpenOn_ for why the matrix cannot be asked this directly.
1072 Teuchos::RCP<FECrsMatrixType> feA = Teuchos::rcp_dynamic_cast<FECrsMatrixType>(A);
1073 if(feA!=Teuchos::null) {
1074 if(feAssemblyOpenOn_!=feA.get()) {
1075 feA->beginAssembly();
1076
1077 // Zero the matrix to start the assembly. The owned+shared view is active here, so
1078 // this is the one point where a single call reaches every row: between assemblies
1079 // the matrix rests in its OWNED view, whose values alias only the leading chunk of
1080 // the owned+shared array (see Tpetra_FECrsMatrix_def.hpp, "we'll grab the first
1081 // chunk of the Owned+Shared matrix's values array"), so a caller's setAllToScalar
1082 // never touches the ghost rows. endAssembly() does not clear them either, being a
1083 // combining self-export that leaves its source untouched, so without this the next
1084 // assembly sums onto the previous one's ghost contributions and inflates every
1085 // shared-interface dof.
1086 feA->setAllToScalar(0.0);
1087
1088 feAssemblyOpenOn_ = feA.get();
1089 }
1090 }
1091 else
1092 A->resumeFill();
1093 }
1094}
1095
1096template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
1098endFill(LinearObjContainer & ghostContainer,const LinearObjContainer & container) const
1099{
1100 endFill(ghostContainer);
1101
1102 // Give back what beginFill(ghostContainer,container) lent. Guarded on identity rather than
1103 // just on useFEAssembly_, so a container holding a matrix of its own is never cleared --
1104 // only the borrow is undone. Leaving it in place would keep the ghosted container pinning
1105 // the caller's Jacobian alive between evaluations, which is the same thing
1106 // panzer::ModelEvaluator avoids by nulling the owned container's operator after assembly.
1107 if(useFEAssembly_) {
1108 ContainerType & ghostedLoc = Teuchos::dyn_cast<ContainerType>(ghostContainer);
1109 const ContainerType & ownedLoc = Teuchos::dyn_cast<const ContainerType>(container);
1110 if(ghostedLoc.get_A()!=Teuchos::null && ghostedLoc.get_A().get()==ownedLoc.get_A().get())
1111 ghostedLoc.set_A(Teuchos::null);
1112 }
1113}
1114
1115template <typename Traits,typename ScalarT,typename LocalOrdinalT,typename GlobalOrdinalT,typename NodeT>
1117endFill(LinearObjContainer & loc) const
1118{
1119 ContainerType & tloc = Teuchos::dyn_cast<ContainerType>(loc);
1120 Teuchos::RCP<CrsMatrixType> A = tloc.get_A();
1121 if(A!=Teuchos::null) {
1122 // See beginFill(): must go through endAssembly() for an FECrsMatrix, not the plain
1123 // CrsMatrix::fillComplete(), so the owned+shared -> owned cross-rank merge happens.
1124 // This single endAssembly() IS the ghost->global migration for the Jacobian in FE mode,
1125 // which is why ghostToGlobalContainer() skips the matrix export there.
1126 //
1127 // Mirror of the beginFill() guard: endFill() is likewise called on both containers
1128 // (global then ghosted) holding the same matrix, and endAssembly() asserts its fill
1129 // state is "open", so only the first call may run it.
1130 Teuchos::RCP<FECrsMatrixType> feA = Teuchos::rcp_dynamic_cast<FECrsMatrixType>(A);
1131 if(feA!=Teuchos::null) {
1132 if(feAssemblyOpenOn_==feA.get()) {
1133 feA->endAssembly();
1134 feAssemblyOpenOn_ = nullptr;
1135 }
1136 }
1137 else
1138 A->fillComplete(A->getDomainMap(),A->getRangeMap());
1139 }
1140}
1141
1142}
1143
1144#endif // __Panzer_TpetraLinearObjFactory_impl_hpp__
This class provides a boundary exchange communication mechanism for vectors.
Abstract, linear-algebra-library-agnostic container for the vectors and matrix used in a nonlinear/tr...
void buildGatherScatterEvaluators(const BuilderT &builder)
Tpetra-backed implementation of LinearObjContainer.
void set_dxdt(const Teuchos::RCP< MultiVectorType > &in)
void set_A(const Teuchos::RCP< CrsMatrixType > &in)
void set_f(const Teuchos::RCP< MultiVectorType > &in)
void set_x(const Teuchos::RCP< MultiVectorType > &in)
void ghostToGlobalTpetraMatrix(const Tpetra::CrsMatrix< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > &in, Tpetra::CrsMatrix< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > &out) const
virtual const Teuchos::RCP< Tpetra::Export< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedExport() const
get exporter for converting an overalapped object to a "normal" object
void initializeContainer(int, LinearObjContainer &loc) const
virtual void applyDirichletBCs(const LinearObjContainer &counter, LinearObjContainer &result) const
virtual Teuchos::RCP< LinearObjContainer > buildGhostedLinearObjContainer() const
Tpetra::FEMultiVector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > FEMultiVectorType
virtual const Teuchos::RCP< const Teuchos::Comm< int > > getTeuchosComm() const
get exporter for converting an overalapped object to a "normal" object
Teuchos::RCP< Tpetra::Vector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedTpetraColVector() const
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > getColMap() const
Teuchos::RCP< FEMultiVectorType > getFEColMultiVector(std::size_t numVectors=1) const
Build a domain-space (solution-side) FE multivector.
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > buildGhostedColMap() const
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedColMap() const
Teuchos::RCP< FEMultiVectorType > getFEMultiVector(std::size_t numVectors=1) const
Build a new Tpetra::FEMultiVector compatible with the FE graph.
virtual const Teuchos::RCP< Tpetra::CrsGraph< LocalOrdinalT, GlobalOrdinalT, NodeT > > buildGraph() const
virtual const Teuchos::RCP< Tpetra::CrsGraph< LocalOrdinalT, GlobalOrdinalT, NodeT > > buildGhostedGraph() const
Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > MapType
Teuchos::RCP< Tpetra::Vector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > > getTpetraVector() const
void globalToGhostTpetraVector(const Tpetra::MultiVector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > &in, Tpetra::MultiVector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > &out, bool col) const
virtual Teuchos::RCP< const Thyra::VectorSpaceBase< ScalarT > > getGhostedThyraDomainSpace() const
Get the domain space.
virtual const Teuchos::RCP< Tpetra::Export< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedColExport() const
virtual void beginFill(LinearObjContainer &loc) const
Open a container for filling. Takes either a ghosted or an owned container.
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedMap() const
get the ghosted map from the matrix
virtual void adjustForDirichletConditions(const LinearObjContainer &localBCRows, const LinearObjContainer &globalBCRows, LinearObjContainer &ghostedObjs, bool zeroVectorRows=false, bool adjustX=false) const
Tpetra::FECrsGraph< LocalOrdinalT, GlobalOrdinalT, NodeT > FECrsGraphType
TpetraLinearObjContainer< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > ContainerType
Tpetra::Export< LocalOrdinalT, GlobalOrdinalT, NodeT > ExportType
Teuchos::RCP< FECrsGraphType > getFEGraph() const
Get the (cached) FE graph, built via the Tpetra::FECrsGraph "V2" constructor.
virtual Teuchos::RCP< ReadOnlyVector_GlobalEvaluationData > buildReadOnlyDomainContainer() const
virtual Teuchos::RCP< Thyra::LinearOpBase< ScalarT > > getThyraMatrix() const
Get a matrix operator.
Tpetra::CrsGraph< LocalOrdinalT, GlobalOrdinalT, NodeT > CrsGraphType
Teuchos::RCP< Tpetra::CrsMatrix< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedTpetraMatrix() const
void initializeGhostedContainer(int, LinearObjContainer &loc) const
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > buildGhostedMap() const
Teuchos::RCP< Tpetra::Vector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedTpetraVector() const
virtual const Teuchos::RCP< Tpetra::CrsGraph< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGraph() const
get the graph of the crs matrix
Tpetra::FECrsMatrix< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > FECrsMatrixType
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > buildMap() const
virtual void ghostToGlobalContainer(const LinearObjContainer &ghostContainer, LinearObjContainer &container, int) const
virtual void endFill(LinearObjContainer &loc) const
Close a container after filling. Takes either a ghosted or an owned container.
Tpetra::MultiVector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > MultiVectorType
virtual Teuchos::RCP< const Thyra::VectorSpaceBase< ScalarT > > getThyraDomainSpace() const
Get the domain space.
virtual Teuchos::RCP< LinearObjContainer > buildLinearObjContainer() const
Teuchos::RCP< const GlobalIndexer > colGidProvider_
Teuchos::RCP< Tpetra::Vector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > > getTpetraColVector() const
virtual const Teuchos::RCP< Tpetra::CrsGraph< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedGraph() const
get the ghosted graph of the crs matrix
Tpetra::CrsMatrix< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > CrsMatrixType
Teuchos::RCP< FECrsMatrixType > getFEMatrix() const
Build a new Tpetra::FECrsMatrix over the (cached) FE graph. Fresh object per call.
void ghostToGlobalTpetraVector(const Tpetra::MultiVector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > &in, Tpetra::MultiVector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > &out, bool col) const
virtual const Teuchos::RCP< Tpetra::Import< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedColImport() const
virtual Teuchos::RCP< const Thyra::VectorSpaceBase< ScalarT > > getThyraRangeSpace() const
Get the range space.
virtual Teuchos::MpiComm< int > getComm() const
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > getMap() const
get the map from the matrix
virtual const Teuchos::RCP< Tpetra::Map< LocalOrdinalT, GlobalOrdinalT, NodeT > > buildColMap() const
TpetraLinearObjFactory(const Teuchos::RCP< const Teuchos::Comm< int > > &comm, const Teuchos::RCP< const GlobalIndexer > &gidProvider, bool useFEAssembly=false)
virtual void globalToGhostContainer(const LinearObjContainer &container, LinearObjContainer &ghostContainer, int) const
virtual const Teuchos::RCP< Tpetra::Import< LocalOrdinalT, GlobalOrdinalT, NodeT > > getGhostedImport() const
get importer for converting an overalapped object to a "normal" object
Tpetra::Vector< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > VectorType
virtual const Teuchos::RCP< FECrsGraphType > buildFEGraph() const
Tpetra::Import< LocalOrdinalT, GlobalOrdinalT, NodeT > ImportType
Teuchos::RCP< Tpetra::CrsMatrix< ScalarT, LocalOrdinalT, GlobalOrdinalT, NodeT > > getTpetraMatrix() const
Panzer's specialization of the Phalanx traits class.