IFPACK Development
Loading...
Searching...
No Matches
Ifpack_SparseContainer.h
1/*@HEADER
2// ***********************************************************************
3//
4// Ifpack: Object-Oriented Algebraic Preconditioner Package
5// Copyright (2002) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ***********************************************************************
40//@HEADER
41*/
42
43#ifndef IFPACK_SPARSECONTAINER_H
44#define IFPACK_SPARSECONTAINER_H
45
46#if defined(Ifpack_SHOW_DEPRECATED_WARNINGS)
47#ifdef __GNUC__
48#warning "The Ifpack package is deprecated"
49#endif
50#endif
51
52#include "Ifpack_Container.h"
53#include "Epetra_IntSerialDenseVector.h"
54#include "Epetra_MultiVector.h"
55#include "Epetra_Vector.h"
56#include "Epetra_Map.h"
57#include "Epetra_RowMatrix.h"
58#include "Epetra_CrsMatrix.h"
59#include "Epetra_LinearProblem.h"
60#include "Epetra_IntSerialDenseVector.h"
61#include "Teuchos_ParameterList.hpp"
62#include "Teuchos_RefCountPtr.hpp"
63#ifdef HAVE_MPI
64#include "Epetra_MpiComm.h"
65#else
66#include "Epetra_SerialComm.h"
67#endif
68
98template<typename T>
100
101public:
102
104
105 Ifpack_SparseContainer(const int NumRows, const int NumVectors = 1);
106
109
111 virtual ~Ifpack_SparseContainer();
113
115
119
121
122 virtual int NumRows() const;
123
125 virtual int NumVectors() const
126 {
127 return(NumVectors_);
128 }
129
131 virtual int SetNumVectors(const int NumVectors_in)
132 {
133 if (NumVectors_ != NumVectors_in)
134 {
135 NumVectors_=NumVectors_in;
136 LHS_=Teuchos::rcp(new Epetra_MultiVector(*Map_,NumVectors_));
137 RHS_=Teuchos::rcp(new Epetra_MultiVector(*Map_,NumVectors_));
138 }
139 return(0);
140 }
141
143 virtual double& LHS(const int i, const int Vector = 0);
144
146 virtual double& RHS(const int i, const int Vector = 0);
147
149
158 virtual int& ID(const int i);
159
161 virtual int SetMatrixElement(const int row, const int col,
162 const double value);
163
164
166 virtual bool IsInitialized() const
167 {
168 return(IsInitialized_);
169 }
170
172 virtual bool IsComputed() const
173 {
174 return(IsComputed_);
175 }
176
178 virtual int SetParameters(Teuchos::ParameterList& List);
179
181 virtual const char* Label() const
182 {
183 return(Label_.c_str());
184 }
185
187 Teuchos::RCP<const Epetra_Map> Map() const
188 {
189 return(Map_);
190 }
191
193 Teuchos::RCP<const Epetra_MultiVector> LHS() const
194 {
195 return(LHS_);
196 }
197
199 Teuchos::RCP<const Epetra_MultiVector> RHS() const
200 {
201 return(RHS_);
202 }
203
205 Teuchos::RCP<const Epetra_CrsMatrix> Matrix() const
206 {
207 return(Matrix_);
208 }
209
212 {
213 return(GID_);
214 }
215
217 Teuchos::RCP<const T> Inverse() const
218 {
219 return(Inverse_);
220 }
222
224
231 virtual int Initialize();
233 virtual int Compute(const Epetra_RowMatrix& Matrix_in);
235 virtual int Apply();
236
238 virtual int ApplyInverse();
239
241
243
244 virtual int Destroy();
246
248 virtual double InitializeFlops() const
249 {
250 if (Inverse_ == Teuchos::null)
251 return (0.0);
252 else
253 return(Inverse_->InitializeFlops());
254 }
255
257 virtual double ComputeFlops() const
258 {
259 if (Inverse_ == Teuchos::null)
260 return (0.0);
261 else
262 return(Inverse_->ComputeFlops());
263 }
264
266 virtual double ApplyFlops() const
267 {
268 return(ApplyFlops_);
269 }
270
272 virtual double ApplyInverseFlops() const
273 {
274 if (Inverse_ == Teuchos::null)
275 return (0.0);
276 else
277 return(Inverse_->ApplyInverseFlops());
278 }
279
281 virtual std::ostream& Print(std::ostream& os) const;
282
283private:
284
286 virtual int Extract(const Epetra_RowMatrix& Matrix_in);
287
289 int NumRows_;
291 int NumVectors_;
293 Teuchos::RefCountPtr<Epetra_Map> Map_;
295 Teuchos::RefCountPtr<Epetra_CrsMatrix> Matrix_;
297 Teuchos::RefCountPtr<Epetra_MultiVector> LHS_;
299 Teuchos::RefCountPtr<Epetra_MultiVector> RHS_;
303 bool IsInitialized_;
305 bool IsComputed_;
307 Teuchos::RefCountPtr<Epetra_Comm> SerialComm_;
309 Teuchos::RefCountPtr<T> Inverse_;
311 std::string Label_;
312 Teuchos::ParameterList List_;
313 double ApplyFlops_;
314
315};
316
317//==============================================================================
318template<typename T>
320Ifpack_SparseContainer(const int NumRows_in, const int NumVectors_in) :
321 NumRows_(NumRows_in),
322 NumVectors_(NumVectors_in),
323 IsInitialized_(false),
324 IsComputed_(false),
325 ApplyFlops_(0.0)
326{
327
328#ifdef HAVE_MPI
329 SerialComm_ = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_SELF) );
330#else
331 SerialComm_ = Teuchos::rcp( new Epetra_SerialComm );
332#endif
333
334}
335
336//==============================================================================
337template<typename T>
340 NumRows_(rhs.NumRows()),
341 NumVectors_(rhs.NumVectors()),
342 IsInitialized_(rhs.IsInitialized()),
343 IsComputed_(rhs.IsComputed())
344{
345
346#ifdef HAVE_MPI
347 SerialComm_ = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_SELF) );
348#else
349 SerialComm_ = Teuchos::rcp( new Epetra_SerialComm );
350#endif
351
352 if (!rhs.Map().is_null())
353 Map_ = Teuchos::rcp( new Epetra_Map(*rhs.Map()) );
354
355 if (!rhs.Matrix().is_null())
356 Matrix_ = Teuchos::rcp( new Epetra_CrsMatrix(*rhs.Matrix()) );
357
358 if (!rhs.LHS().is_null())
359 LHS_ = Teuchos::rcp( new Epetra_MultiVector(*rhs.LHS()) );
360
361 if (!rhs.RHS().is_null())
362 RHS_ = Teuchos::rcp( new Epetra_MultiVector(*rhs.RHS()) );
363
364}
365//==============================================================================
366template<typename T>
371
372//==============================================================================
373template<typename T>
375{
376 if (IsInitialized() == false)
377 return(0);
378 else
379 return(NumRows_);
380}
381
382//==============================================================================
383template<typename T>
385{
386
387 if (IsInitialized_ == true)
388 Destroy();
389
390 IsInitialized_ = false;
391
392#if !defined(EPETRA_NO_32BIT_GLOBAL_INDICES) || !defined(EPETRA_NO_64BIT_GLOBAL_INDICES)
393 Map_ = Teuchos::rcp( new Epetra_Map(NumRows_,0,*SerialComm_) );
394#endif
395
396 LHS_ = Teuchos::rcp( new Epetra_MultiVector(*Map_,NumVectors_) );
397 RHS_ = Teuchos::rcp( new Epetra_MultiVector(*Map_,NumVectors_) );
398 GID_.Reshape(NumRows_,1);
399
400#if defined(HAVE_TEUCHOSCORE_CXX11)
401 Matrix_ = Teuchos::rcp( new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*Map_,0) );
402#else
403 Matrix_ = Teuchos::rcp( new Epetra_CrsMatrix(::Copy,*Map_,0) );
404#endif
405
406 // create the inverse
407 Inverse_ = Teuchos::rcp( new T(Matrix_.get()) );
408
409 if (Inverse_ == Teuchos::null)
410 IFPACK_CHK_ERR(-5);
411
412 IFPACK_CHK_ERR(Inverse_->SetParameters(List_));
413
414 // Call Inverse_->Initialize() in Compute(). This saves
415 // some time, because I can extract the diagonal blocks faster,
416 // and only once.
417
418 Label_ = "Ifpack_SparseContainer";
419
420 IsInitialized_ = true;
421 return(0);
422
423}
424
425//==============================================================================
426template<typename T>
427double& Ifpack_SparseContainer<T>::LHS(const int i, const int Vector)
428{
429 return(((*LHS_)(Vector))->Values()[i]);
430}
431
432//==============================================================================
433template<typename T>
434double& Ifpack_SparseContainer<T>::RHS(const int i, const int Vector)
435{
436 return(((*RHS_)(Vector))->Values()[i]);
437}
438
439//==============================================================================
440template<typename T>
442SetMatrixElement(const int row, const int col, const double value)
443{
444 if (!IsInitialized())
445 IFPACK_CHK_ERR(-3); // problem not shaped yet
446
447 if ((row < 0) || (row >= NumRows())) {
448 IFPACK_CHK_ERR(-2); // not in range
449 }
450
451 if ((col < 0) || (col >= NumRows())) {
452 IFPACK_CHK_ERR(-2); // not in range
453 }
454
455#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
456 if(Matrix_->RowMatrixRowMap().GlobalIndicesInt()) {
457 int ierr = Matrix_->InsertGlobalValues((int)row,1,(double*)&value,(int*)&col);
458 if (ierr < 0) {
459 ierr = Matrix_->SumIntoGlobalValues((int)row,1,(double*)&value,(int*)&col);
460 if (ierr < 0)
461 IFPACK_CHK_ERR(-1);
462 }
463 }
464 else
465#endif
466#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
467 if(Matrix_->RowMatrixRowMap().GlobalIndicesLongLong()) {
468 long long col_LL = col;
469 int ierr = Matrix_->InsertGlobalValues(row,1,(double*)&value,&col_LL);
470 if (ierr < 0) {
471 ierr = Matrix_->SumIntoGlobalValues(row,1,(double*)&value,&col_LL);
472 if (ierr < 0)
473 IFPACK_CHK_ERR(-1);
474 }
475 }
476 else
477#endif
478 throw "Ifpack_SparseContainer<T>::SetMatrixElement: GlobalIndices type unknown";
479
480 return(0);
481
482}
483
484//==============================================================================
485template<typename T>
487{
488
489 IsComputed_ = false;
490 if (!IsInitialized()) {
491 IFPACK_CHK_ERR(Initialize());
492 }
493
494 // extract the submatrices
495 IFPACK_CHK_ERR(Extract(Matrix_in));
496
497 // initialize the inverse operator
498 IFPACK_CHK_ERR(Inverse_->Initialize());
499
500 // compute the inverse operator
501 IFPACK_CHK_ERR(Inverse_->Compute());
502
503 Label_ = "Ifpack_SparseContainer";
504
505 IsComputed_ = true;
506
507 return(0);
508}
509
510//==============================================================================
511template<typename T>
513{
514 if (IsComputed() == false) {
515 IFPACK_CHK_ERR(-3); // not yet computed
516 }
517
518 IFPACK_CHK_ERR(Matrix_->Apply(*RHS_, *LHS_));
519
520 ApplyFlops_ += 2 * Matrix_->NumGlobalNonzeros64();
521 return(0);
522}
523
524//==============================================================================
525template<typename T>
527{
528 if (!IsComputed())
529 IFPACK_CHK_ERR(-1);
530
531 IFPACK_CHK_ERR(Inverse_->ApplyInverse(*RHS_, *LHS_));
532
533 return(0);
534}
535
536
537//==============================================================================
538template<typename T>
540{
541 IsInitialized_ = false;
542 IsComputed_ = false;
543 return(0);
544}
545
546//==============================================================================
547template<typename T>
549{
550 return(GID_[i]);
551}
552
553//==============================================================================
554template<typename T>
556SetParameters(Teuchos::ParameterList& List)
557{
558 List_ = List;
559 return(0);
560}
561
562//==============================================================================
563// FIXME: optimize performances of this guy...
564template<typename T>
566{
567
568 for (int j = 0 ; j < NumRows_ ; ++j) {
569 // be sure that the user has set all the ID's
570 if (ID(j) == -1)
571 IFPACK_CHK_ERR(-1);
572 // be sure that all are local indices
573 if (ID(j) > Matrix_in.NumMyRows())
574 IFPACK_CHK_ERR(-1);
575 }
576
577 int Length = Matrix_in.MaxNumEntries();
578 std::vector<double> Values;
579 Values.resize(Length);
580 std::vector<int> Indices;
581 Indices.resize(Length);
582
583 for (int j = 0 ; j < NumRows_ ; ++j) {
584
585 int LRID = ID(j);
586
587 int NumEntries;
588
589 int ierr =
590 Matrix_in.ExtractMyRowCopy(LRID, Length, NumEntries,
591 &Values[0], &Indices[0]);
592 IFPACK_CHK_ERR(ierr);
593
594 for (int k = 0 ; k < NumEntries ; ++k) {
595
596 int LCID = Indices[k];
597
598 // skip off-processor elements
599 if (LCID >= Matrix_in.NumMyRows())
600 continue;
601
602 // for local column IDs, look for each ID in the list
603 // of columns hosted by this object
604 // FIXME: use STL
605 int jj = -1;
606 for (int kk = 0 ; kk < NumRows_ ; ++kk)
607 if (ID(kk) == LCID)
608 jj = kk;
609
610 if (jj != -1)
611 SetMatrixElement(j,jj,Values[k]);
612
613 }
614 }
615
616 IFPACK_CHK_ERR(Matrix_->FillComplete());
617
618 return(0);
619}
620
621//==============================================================================
622template<typename T>
623std::ostream& Ifpack_SparseContainer<T>::Print(std::ostream & os) const
624{
625 using std::endl;
626
627 os << "================================================================================" << endl;
628 os << "Ifpack_SparseContainer" << endl;
629 os << "Number of rows = " << NumRows() << endl;
630 os << "Number of vectors = " << NumVectors() << endl;
631 os << "IsInitialized() = " << IsInitialized() << endl;
632 os << "IsComputed() = " << IsComputed() << endl;
633 os << "Flops in Initialize() = " << InitializeFlops() << endl;
634 os << "Flops in Compute() = " << ComputeFlops() << endl;
635 os << "Flops in ApplyInverse() = " << ApplyInverseFlops() << endl;
636 os << "================================================================================" << endl;
637 os << endl;
638
639 return(os);
640}
641#endif // IFPACK_SPARSECONTAINER_H
virtual int NumMyRows() const=0
virtual int MaxNumEntries() const=0
virtual int ExtractMyRowCopy(int MyRow, int Length, int &NumEntries, double *Values, int *Indices) const=0
Ifpack_Container: a pure virtual class for creating and solving local linear problems.
Ifpack_SparseContainer: a class for storing and solving linear systems using sparse matrices.
virtual double InitializeFlops() const
Returns the flops in Compute().
virtual double ApplyFlops() const
Returns the flops in Apply().
virtual int Apply()
Apply the matrix to RHS, result is stored in LHS.
virtual double ComputeFlops() const
Returns the flops in Compute().
virtual int SetNumVectors(const int NumVectors_in)
Sets the number of vectors for LHS/RHS.
virtual std::ostream & Print(std::ostream &os) const
Prints basic information on iostream. This function is used by operator<<.
virtual int SetMatrixElement(const int row, const int col, const double value)
Set the matrix element (row,col) to value.
virtual bool IsComputed() const
Returns true is the container has been successfully computed.
virtual int NumRows() const
Returns the number of rows of the matrix and LHS/RHS.
const Epetra_IntSerialDenseVector & ID() const
Returns a pointer to the internally stored ID's.
virtual int Initialize()
Initializes the container, by completing all the operations based on matrix structure.
virtual double & LHS(const int i, const int Vector=0)
Returns the i-th component of the vector Vector of LHS.
Teuchos::RCP< const Epetra_MultiVector > LHS() const
Returns a pointer to the internally stored solution multi-vector.
virtual int Destroy()
Destroys all data.
virtual bool IsInitialized() const
Returns true is the container has been successfully initialized.
virtual ~Ifpack_SparseContainer()
Destructor.
virtual double ApplyInverseFlops() const
Returns the flops in ApplyInverse().
virtual int Compute(const Epetra_RowMatrix &Matrix_in)
Finalizes the linear system matrix and prepares for the application of the inverse.
Ifpack_SparseContainer & operator=(const Ifpack_SparseContainer< T > &rhs)
Operator =.
virtual int NumVectors() const
Returns the number of vectors in LHS/RHS.
virtual int SetParameters(Teuchos::ParameterList &List)
Sets all necessary parameters.
Teuchos::RCP< const Epetra_Map > Map() const
Returns a pointer to the internally stored map.
virtual int ApplyInverse()
Apply the inverse of the matrix to RHS, result is stored in LHS.
Teuchos::RCP< const T > Inverse() const
Returns a pointer to the internally stored inverse operator.
Teuchos::RCP< const Epetra_MultiVector > RHS() const
Returns a pointer to the internally stored rhs multi-vector.
Ifpack_SparseContainer(const int NumRows, const int NumVectors=1)
Constructor.
Teuchos::RCP< const Epetra_CrsMatrix > Matrix() const
Returns a pointer to the internally stored matrix.
virtual double & RHS(const int i, const int Vector=0)
Returns the i-th component of the vector Vector of RHS.
virtual const char * Label() const
Returns the label of this container.