IFPACK  Development
 All Classes Namespaces Files Functions Variables Enumerations Friends Pages
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 
98 template<typename T>
100 
101 public:
102 
104  Ifpack_SparseContainer(const int NumRows, const int NumVectors = 1);
106 
109 
111  virtual ~Ifpack_SparseContainer();
113 
115 
119 
121  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  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 
283 private:
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 //==============================================================================
318 template<typename T>
320 Ifpack_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 //==============================================================================
337 template<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 //==============================================================================
366 template<typename T>
368 {
369  Destroy();
370 }
371 
372 //==============================================================================
373 template<typename T>
375 {
376  if (IsInitialized() == false)
377  return(0);
378  else
379  return(NumRows_);
380 }
381 
382 //==============================================================================
383 template<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 //==============================================================================
426 template<typename T>
427 double& Ifpack_SparseContainer<T>::LHS(const int i, const int Vector)
428 {
429  return(((*LHS_)(Vector))->Values()[i]);
430 }
431 
432 //==============================================================================
433 template<typename T>
434 double& Ifpack_SparseContainer<T>::RHS(const int i, const int Vector)
435 {
436  return(((*RHS_)(Vector))->Values()[i]);
437 }
438 
439 //==============================================================================
440 template<typename T>
442 SetMatrixElement(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 //==============================================================================
485 template<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 //==============================================================================
511 template<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 //==============================================================================
525 template<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 //==============================================================================
538 template<typename T>
540 {
541  IsInitialized_ = false;
542  IsComputed_ = false;
543  return(0);
544 }
545 
546 //==============================================================================
547 template<typename T>
549 {
550  return(GID_[i]);
551 }
552 
553 //==============================================================================
554 template<typename T>
556 SetParameters(Teuchos::ParameterList& List)
557 {
558  List_ = List;
559  return(0);
560 }
561 
562 //==============================================================================
563 // FIXME: optimize performances of this guy...
564 template<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 //==============================================================================
622 template<typename T>
623 std::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 double ComputeFlops() const
Returns the flops in Compute().
virtual double InitializeFlops() const
Returns the flops in Compute().
Teuchos::RCP< const Epetra_MultiVector > LHS() const
Returns a pointer to the internally stored solution multi-vector.
virtual int NumRows() const
Returns the number of rows of the matrix and LHS/RHS.
Ifpack_SparseContainer & operator=(const Ifpack_SparseContainer< T > &rhs)
Operator =.
Teuchos::RCP< const Epetra_MultiVector > RHS() const
Returns a pointer to the internally stored rhs multi-vector.
virtual int SetParameters(Teuchos::ParameterList &List)
Sets all necessary parameters.
virtual bool IsInitialized() const
Returns true is the container has been successfully initialized.
Teuchos::RCP< const Epetra_CrsMatrix > Matrix() const
Returns a pointer to the internally stored matrix.
virtual double & LHS(const int i, const int Vector=0)
Returns the i-th component of the vector Vector of LHS.
virtual int Initialize()
Initializes the container, by completing all the operations based on matrix structure.
virtual int SetMatrixElement(const int row, const int col, const double value)
Set the matrix element (row,col) to value.
virtual const char * Label() const
Returns the label of this container.
virtual double & RHS(const int i, const int Vector=0)
Returns the i-th component of the vector Vector of RHS.
Teuchos::RCP< const Epetra_Map > Map() const
Returns a pointer to the internally stored map.
virtual int MaxNumEntries() const =0
virtual int NumVectors() const
Returns the number of vectors in LHS/RHS.
Ifpack_SparseContainer: a class for storing and solving linear systems using sparse matrices...
virtual int SetNumVectors(const int NumVectors_in)
Sets the number of vectors for LHS/RHS.
virtual int ApplyInverse()
Apply the inverse of the matrix to RHS, result is stored in LHS.
Ifpack_SparseContainer(const int NumRows, const int NumVectors=1)
Constructor.
virtual int NumMyRows() const =0
virtual double ApplyFlops() const
Returns the flops in Apply().
virtual std::ostream & Print(std::ostream &os) const
Prints basic information on iostream. This function is used by operator&lt;&lt;.
virtual ~Ifpack_SparseContainer()
Destructor.
Teuchos::RCP< const T > Inverse() const
Returns a pointer to the internally stored inverse operator.
const Epetra_IntSerialDenseVector & ID() const
Returns a pointer to the internally stored ID&#39;s.
virtual int Destroy()
Destroys all data.
Ifpack_Container: a pure virtual class for creating and solving local linear problems.
virtual int ExtractMyRowCopy(int MyRow, int Length, int &NumEntries, double *Values, int *Indices) const =0
virtual bool IsComputed() const
Returns true is the container has been successfully computed.
virtual int Compute(const Epetra_RowMatrix &Matrix_in)
Finalizes the linear system matrix and prepares for the application of the inverse.
virtual double ApplyInverseFlops() const
Returns the flops in ApplyInverse().
virtual int Apply()
Apply the matrix to RHS, result is stored in LHS.