LifeV
ComposedOperator.hpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*- */
2 //@HEADER
3 /*
4 *******************************************************************************
5 
6  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
7  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
8 
9  This file is part of LifeV.
10 
11  LifeV is free software; you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  LifeV is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
23 
24 *******************************************************************************
25 */
26 //@HEADER
27 
28 /**
29  * \file ComposedOperator.hpp
30  * \author Simone Deparis, Paolo Crosetto
31  * \mantainer Paolo Crosetto
32  * \date 2009-03-25
33  * Class handling a preconditioner defined as a composition of operators. The class is templated
34  * so that the operators that define the preconditioner can be general
35  * (matrices, other preconditioners, other composed preconditioners, etc.).
36  * It is similar to the thyra package in Trilinos although it doesn't depend on it.
37  *
38  */
39 
40 #ifndef COMPOSEDPRECONDITIONER_HPP
41 #define COMPOSEDPRECONDITIONER_HPP
42 
43 
44 #include <Epetra_Operator.h>
45 #include <Epetra_MultiVector.h>
46 
47 #include <lifev/core/LifeV.hpp>
48 #include <lifev/core/filter/GetPot.hpp>
49 #include <lifev/core/util/LifeChrono.hpp>
50 #include <lifev/core/util/Displayer.hpp>
51 
52 namespace LifeV
53 {
54 //! ComposedOperator -
55 /*!
56  @author Simone Deparis, Paolo Crosetto
57  @mantainer Paolo Crosetto
58  * Class handling a preconditioner defined as a composition of operators. The class is templated
59  * so that the operators that define the preconditioner can be general
60  * (matrices, other preconditioners, other composed preconditioners, etc.).
61  */
62 
63 template<typename OperatorType>
64 class ComposedOperator
65  : public Epetra_Operator
66 {
67 
68 public:
69 
70  //! @name Typedefs
71  //@{
72  //typedef Ifpack_Preconditioner prec_Type;
73  typedef OperatorType operator_Type;
74  typedef typename std::shared_ptr<operator_Type> operatorPtr_Type;
75  //@}
76 
77  //! @name Constructors, destructor
78  //@{
79  /**
80  The constructor builds an empty chain of composed operators.
81  The resulting operator shall be equal to the identity.
82  */
83  ComposedOperator ( const std::shared_ptr<Epetra_Comm>& comm );
84 
85  /**
86  Copy constructor: it doesn't make a real copy of the operators, it just copies the vector of shared pointer
87  (note that the implementation is mandatory in order to avoid a bit-copy of the shared_ptr vector)
88  */
89  ComposedOperator ( const ComposedOperator<operator_Type>& P);
90 
91  virtual ~ComposedOperator();
92  //@}
93 
94  //!@name Public Methods
95  //@{
96  /**
97  Method to add an operator at the end of the operators list.
98  we expect an external Operator shared pointer, we will not destroy the matrix!
99  remember: P = M_operator(0) * ... * M_operator(Qp-1)
100  \param P: the operator
101  \param useTranspose: flag specifying if we want to applly the transposed operator
102  \param summed: flag specifying if we want the operator to be summed. Note that the operator would be "out
103  of the vector", summed in a second step after all the multiplications.
104  */
105  UInt push_back (operatorPtr_Type P,
106  const bool useInverse = false,
107  const bool useTranspose = false,
108  const bool summed = false);
109 
110  /**
111  Method to add an operator at the end of the operators list.
112  Deprecated. The input parameter P is a standard pointer.
113  \param P: the operator
114  \param useTranspose: flag specifying if we want to applly the transposed operator
115  \param summed: flag specifying if we want the operator to be summed. Note that the operator would be "out
116  of the vector", summed in a second step after all the multiplications.
117  */
118 
119  UInt push_back (operator_Type* P,
120  const bool useInverse = false,
121  const bool useTranspose = false,
122  const bool summed = false);
123 
124  //! we expecte an external matrix shared pointer, we will not destroy the matrix!
125  //! remember: P = M_operator(0) * ... * M_operator(Qp-1)
126  /**
127  Method to replace an operator in a specified position of the operators vector.
128  \param P: input operator
129  \param index: position (starting from 0)
130  \param useInverse: flag specifying if the operator is already inverted (if AllpyInverse() is implemented)
131  */
132  UInt replace (operatorPtr_Type P,
133  const UInt index,
134  const bool useInverse = false,
135  const bool useTranspose = false);
136 
137  //! Resets all the factors in the operator
138  /**
139  Calls reset() on all the factors
140  */
141  void reset();
142 
143  //! swaps two factors
144  /**
145  Swaps the factors and all the related flags (useTranspose, etc...)
146  \param first: first factor
147  \param second: second factor
148  */
149  void swap (UInt first, UInt second);
150 
151  //! resets the sandard vector holding all the factors
152  /**
153  calls clear on the std::vector
154  \todo change name in e.g. resetOperator
155  */
156  void resetOperator()
157  {
158  M_operator.clear();
159  }
160  //@}
161 
162  /** @name Implementation of Epetra_Operator Methods
163  */
164  //@{
165  /**
166  Method to set the flag M_useTranspose, which specifies if the composed operator is to be transposed.
167  */
168  int SetUseTranspose (bool UseTranspose);
169 
170  /**
171  Method returning the result of applying the operator to a vector
172  \param X: input vector
173  \param Y: output vector
174  */
175  int Apply (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
176 
177  // Simone:here use the ApplyInverse from the local operators.
178  int ApplyInverse (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
179 
180  /** Returns the quantity \f$ \| A \|_\infty\f$ such that
181  \f[\| A \|_\infty = \max_{1\le i\le m} \sum_{j=1}^n |a_{ij}| \f].
182 
183  \warning This method must not be called unless HasNormInf() returns true.
184  */
185  double NormInf() const;
186 
187  //! Returns an estimation of the condition number
188  /**
189  the estimation is devised from an estimation on each factor with the rule \f$ K_{12}\leq K_1K_2 \f$
190  */
191  double Condest() const;
192 
193  /**
194  Method returning a string identifying the type of operator
195  */
196  const char* Label() const;
197 
198  /**
199  Returns true if all the operators composed have to be considered transpose (i.e. if M_allTranspose==true)
200  */
201  bool UseTranspose() const;
202 
203  /**
204  Never called: it is implemented for compatibility with Epetra_Operator
205  */
206  bool HasNormInf() const;
207 
208  /**
209  Returns the communicator
210  */
211  const Epetra_Comm& Comm() const;
212 
213  /**
214  Returns a shared pointer to the communicator
215  */
216  const std::shared_ptr<Epetra_Comm> commPtr() const;
217 
218  /**
219  returns the OperatorDomainMap of the operators contained
220  */
221  const Epetra_Map& OperatorDomainMap() const;
222 
223  /**
224  returns the OperatorRangeMap of the operators contained
225  */
226  const Epetra_Map& OperatorRangeMap() const;
227  //@}
228 
229  //! Public Get Methods
230  //@{
231 
232  //!returns a const reference tor the std::vector of factors
233  /**
234  */
235  const std::vector<operatorPtr_Type>& Operator() const
236  {
237  return M_operator;
238  }
239 
240  //!returns the std::vector of factors by (non const) reference
241  /**
242  */
243  std::vector<operatorPtr_Type>& OperatorView() const
244  {
245  return M_operator;
246  }
247 
248  //! Returns true if the operator is transposed
249  /**
250  The operator transposed means that all its factors have to be considered transposed
251  */
252  bool allTranspose() const
253  {
254  return M_allTranspose;
255  }
256 
257  //! Returns a vector saying for each factor if it is considered transposed or not
258  const std::vector<bool>& transpose() const
259  {
260  return M_transpose;
261  }
262 
263  //! Returns a vector of UInt specifying the form of the operator
264  /**
265  The size of the vector corresponds to the number of '+' operation in the operator.
266  Each element of the output vector says how many factors are there between two '+' operation. For instance for
267  the operator AB+CDE the vector M_summed returned would be [2,3]
268  */
269  const std::vector<ID>& summed() const
270  {
271  return M_summed;
272  }
273 
274  //! Returns a vector saying which factors have to be considered as inverse
275  const std::vector<bool>& inverse() const
276  {
277  return M_inverse;
278  }
279  //! returns the number of factors present in the operator
280  UInt number() const
281  {
282  return M_set;
283  }
284 
285  const double& meanIter() const
286  {
287  return M_meanIter;
288  }
289 
290  int numCalled() const
291  {
292  return M_numCalled;
293  }
294 
295  const Displayer& displayer()
296  {
297  return M_displayer;
298  }
299  //@}
300 
301  //!@name Setter Methods
302  //!{
303  //! Sets the MPI communicator
304  void setComm (const std::shared_ptr<Epetra_Comm> comm);
305  //!}
306 
307 protected:
308 
309  //!@name Protected Methods
310  //!{
311 
312  int Apply_DirectOperator (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
313 
314  int Apply_InverseOperator (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const;
315  //@}
316 
317  //!@name Protected Members
318  //!{
319  // P = M_operator(0) * ... * M_operator(n-1)
320  mutable std::vector<operatorPtr_Type> M_operator;
321  std::vector<bool> M_inverse;
322  std::vector<bool> M_transpose;
323  std::vector<ID> M_summed;
324  bool M_allTranspose;
325 
326  UInt M_set;
327 
328  mutable double M_meanIter;
329  mutable int M_numCalled;
330 
331  Displayer M_displayer;
332  //@}
333 };
334 
335 // ===================================================
336 //! Constructors and Destructor
337 // ===================================================
338 
339 template <typename operator_Type>
340 ComposedOperator<operator_Type>::ComposedOperator ( const std::shared_ptr<Epetra_Comm>& comm)
341  :
342  M_operator(),
343  M_inverse(),
344  M_transpose(),
345  M_summed(),
346  M_allTranspose (false),
347  M_set (0),
348  M_meanIter (0),
349  M_numCalled (0),
350  M_displayer (comm)
351 {
352 }
353 
354 template <typename operator_Type>
355 ComposedOperator<operator_Type>::ComposedOperator ( const ComposedOperator<operator_Type>& P)
356  :
357  M_operator(),
358  M_inverse (P.inverse() ),
359  M_transpose (P.transpose() ),
360  M_summed (P.summed() ),
361  M_allTranspose (P.allTranspose() ),
362  M_set (P.number() ),
363  M_meanIter (P.meanIter() ),
364  M_numCalled (P.numCalled() ),
365  M_displayer (P.commPtr() )
366 {
367  for (UInt i = 0; i < M_set; ++i)
368  {
369  M_operator.push_back (P.Operator() [i]);
370  }
371 }
372 
373 template <typename operator_Type>
374 ComposedOperator<operator_Type>::~ComposedOperator()
375 {
376  M_operator.clear();
377 }
378 
379 // ===================================================
380 //! Public Methods
381 // ===================================================
382 
383 template <typename operator_Type>
384 UInt ComposedOperator<operator_Type>::
385 push_back ( operator_Type* P,
386  const bool useInverse,
387  const bool useTranspose,
388  const bool summed)
389 {
390  operatorPtr_Type prec (P);
391  return push_back (P, useInverse, useTranspose, summed);
392 }
393 
394 
395 // we expect an external matrix pointer, we will not destroy the matrix!
396 template <typename operator_Type>
397 UInt ComposedOperator<operator_Type>::
398 push_back ( operatorPtr_Type P,
399  const bool useInverse,
400  const bool useTranspose,
401  const bool summed)
402 {
403  if (P.get() == 0)
404  {
405  M_displayer.leaderPrint (" CP- Precondtioner not set: ", M_set, "\n");
406  return (M_set);
407  }
408 
409  // M_displayer.leaderPrint(" CP- Previous number of call: ", M_numCalled, "\n");
410  // M_displayer.leaderPrint(" CP- Mean iters: ", M_meanIter, "\n" );
411 
412  M_meanIter = 0;
413  M_numCalled = 0;
414 
415  // push back the nth operator
416 
417  M_operator. push_back (P);
418  M_inverse. push_back (useInverse);
419  M_transpose.push_back (useTranspose);
420  if (summed)
421  {
422  M_summed.push_back (M_set);
423  }
424 
425  // if (useInverse && useTranspose) assert(false); // I am not sure I have coded this in the right way
426 
427  M_set++;
428 
429  return (M_set);
430 }
431 
432 // we expect an external matrix pointer, we will not destroy the matrix!
433 template <typename operator_Type>
434 UInt ComposedOperator<operator_Type>::
435 replace ( operatorPtr_Type P,
436  const UInt index,
437  const bool useInverse,
438  const bool useTranspose)
439 {
440  if (P.get() == 0)
441  {
442  return (M_set);
443  }
444 
445  ASSERT (index <= M_set, "ComposedOperator::replace: index too large");
446 
447  M_displayer.leaderPrint (" CP- Previous number of call: ", M_numCalled, "\n");
448  M_displayer.leaderPrint (" CP- Mean iters: ", M_meanIter, "\n" );
449 
450  M_meanIter = 0;
451  M_numCalled = 0;
452 
453  // replace the nth operator
454  M_operator [index] = P;
455  M_inverse [index] = useInverse;
456  M_transpose[index] = useTranspose;
457 
458  if (useInverse && useTranspose)
459  {
460  assert (false); // I am not sure I have coded this in the right way
461  }
462 
463  return (M_set);
464 
465 }
466 
467 
468 template <typename operator_Type>
469 void ComposedOperator<operator_Type>::reset()
470 {
471  for (UInt q (0); q < M_set ; q++)
472  {
473  M_operator[q].reset();
474  }
475 }
476 
477 
478 template <typename operator_Type>
479 void ComposedOperator<operator_Type>::swap (UInt first, UInt second)
480 {
481  operatorPtr_Type tmpPrec;
482  tmpPrec = M_operator[first];
483  M_operator[first] = M_operator[second];
484  M_operator[second] = tmpPrec;
485 }
486 
487 // ===================================================
488 //! Implementation of Epetra_Operator methods
489 // ===================================================
490 
491 template <typename operator_Type>
492 int ComposedOperator<operator_Type>::SetUseTranspose (bool useTranspose)
493 {
494  if (useTranspose != UseTranspose() )
495  {
496  M_allTranspose = useTranspose;
497  int size = M_operator.size() - 1;
498  if (size)
499  for (int i = 0; i < size / 2; ++i)
500  {
501  operatorPtr_Type swp;
502  swp = M_operator[i];
503  M_operator[i] = M_operator[size - i];
504  M_operator[size - i] = swp;
505  M_operator[i]->SetUseTranspose (!M_operator[i]->UseTranspose() );
506  assert (M_operator[size - i]->SetUseTranspose (!M_operator[size - i]->UseTranspose() ) != -1);
507  }
508  else
509  {
510  assert (M_operator[0]->SetUseTranspose (!M_operator[0]->UseTranspose() ) != -1);
511  }
512  M_operator[ (int) (size / 2)]->SetUseTranspose (!M_operator[ (int) (size / 2)]->UseTranspose() );
513  }
514  return 0;
515 }
516 
517 template <typename operator_Type>
518 int ComposedOperator<operator_Type>::
519 Apply (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
520 {
521  return Apply_DirectOperator (X, Y);
522 
523 }
524 
525 template <typename operator_Type>
526 int ComposedOperator<operator_Type>::
527 ApplyInverse (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
528 {
529  return Apply_InverseOperator (X, Y);
530 }
531 
532 template <typename operator_Type>
533 double ComposedOperator<operator_Type>::NormInf() const
534 {
535  assert (false);
536  return (EXIT_FAILURE);
537 }
538 
539 template <typename operator_Type>
540 double ComposedOperator<operator_Type>::Condest() const
541 {
542  double cond (1);
543 
544  for (UInt q (0); q < M_set ; q++)
545  {
546  if (M_inverse[q])
547  {
548  cond = cond / M_operator[q]->condest();
549  }
550  else
551  {
552  cond *= M_operator[q]->condest();
553  }
554  }
555  return (cond);
556 }
557 
558 template <typename operator_Type>
559 const char* ComposedOperator<operator_Type>::
560 Label() const
561 {
562  return ("Composed operator_Type P1*P2* ... *Pn");
563 }
564 
565 // ===================================================
566 //! Get Methods
567 // ===================================================
568 
569 template <typename operator_Type>
570 bool ComposedOperator<operator_Type>::UseTranspose() const
571 {
572  return (M_allTranspose);
573 }
574 
575 template <typename operator_Type>
576 bool ComposedOperator<operator_Type>::
577 HasNormInf() const
578 {
579  return (false);
580 }
581 
582 
583 template <typename operator_Type>
584 const Epetra_Comm& ComposedOperator<operator_Type>::
585 Comm() const
586 {
587  assert (M_set > 0);
588  //cout << "Prec: M_setted = " << M_set << endl;
589  return ( *M_displayer.comm() );
590 }
591 
592 template <typename operator_Type>
593 const std::shared_ptr<Epetra_Comm> ComposedOperator<operator_Type>::
594 commPtr() const
595 {
596  return ( M_displayer.comm() );
597 }
598 
599 
600 template <typename operator_Type>
601 const Epetra_Map& ComposedOperator<operator_Type>::
602 OperatorDomainMap() const
603 {
604  // P = M_operator(0) * ... * M_operator(Qp-1)
605  assert (M_set > 0 );
606  return ( M_operator[M_set - 1]->OperatorDomainMap() );
607 }
608 
609 template <typename operator_Type>
610 const Epetra_Map& ComposedOperator<operator_Type>::
611 OperatorRangeMap() const
612 {
613  // P = M_operator(0) * ... * M_operator(Qp-1)
614  assert (M_set > 0);
615  return ( M_operator[0]->OperatorRangeMap() );
616 
617 }
618 
619 // ===================================================
620 //! Set Methods
621 // ===================================================
622 
623 template <typename operator_Type> void
624 ComposedOperator<operator_Type>::setComm (const std::shared_ptr<Epetra_Comm> comm)
625 {
626  //this->M_comm=comm;//copy of the communicator
627  M_displayer.setCommunicator (comm);
628 }
629 
630 // ===================================================
631 //! Protected Methods
632 // ===================================================
633 
634 template <typename operator_Type>
635 int ComposedOperator<operator_Type>::
636 Apply_DirectOperator (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
637 {
638  assert (M_set > 0 );
639 
640  bool useTranspose;
641  Epetra_MultiVector Z (X);
642 
643  // P = M_operator(0) * ... * M_operator(Qp-1)
644 
645  ID k = 0;
646  for (Int q (M_set - 1); q >= 0 ; q--)
647  {
648  if (M_summed.size() && q == (Int) M_summed[k])
649  {
650  ++k;
651  }
652  else
653  {
654  if (M_inverse[q])
655  {
656  useTranspose = M_operator[q]->UseTranspose (); // storing original status
657  assert (M_operator[q]->SetUseTranspose (M_transpose[q]) != -1);
658  M_operator[q]->ApplyInverse (Z, Y);
659  M_operator[q]->SetUseTranspose (useTranspose); // put back to original status
660  }
661  else
662  {
663  useTranspose = M_operator[q]->UseTranspose (); // storing original status
664  assert (M_operator[q]->SetUseTranspose (M_transpose[q]) != -1);
665  M_operator[q]->Apply (Z, Y);
666  M_operator[q]->SetUseTranspose (useTranspose); // put back to original status
667  }
668  Z = Y;
669  }
670  }
671 
672  for (UInt k = 0; k < M_summed.size(); ++k)
673  {
674  if (M_inverse[M_summed[k]])
675  {
676  M_operator[M_summed[k]]->ApplyInverse (X, Y);
677  }
678  else
679  {
680  M_operator[M_summed[k]]->Apply (X, Y);
681  }
682  Z.Update (1., Y, 1.);
683  }
684 
685  Y = Z;
686  return (EXIT_SUCCESS);
687 
688 }
689 
690 template <typename operator_Type>
691 int ComposedOperator<operator_Type>::
692 Apply_InverseOperator (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
693 {
694  assert (M_set > 0);
695 
696  // P = M_operator(0) * ... * M_operator(Qp-1)
697 
698  bool useTranspose;
699  Epetra_MultiVector Z (X);
700  ID k = 0;
701 
702  for (UInt q (0); q < M_set ; q++, Z = Y)
703  {
704  if (M_summed.size() && q == M_summed[k])
705  {
706  ++k;
707  }
708  else
709  {
710  if (M_inverse[q])
711  {
712  useTranspose = M_operator[q]->UseTranspose (); // storing original status
713  ASSERT (M_operator[q]->SetUseTranspose (M_transpose[q]) != -1, "SetUseTranspose failed in the preconditioner of your choice");
714  M_operator[q]->Apply (Z, Y); //y+=Pi*z
715  M_operator[q]->SetUseTranspose (useTranspose); // put back to original status
716  }
717  else
718  {
719  useTranspose = M_operator[q]->UseTranspose (); // storing original status
720  //ifdef DEBUG
721  ASSERT (!M_transpose[q] || M_operator[q]->SetUseTranspose (M_transpose[q]) == -1, "Something went wrong in SetUseTranspose for your preconditioner.\n");
722  //#endif
723  M_operator[q]->ApplyInverse (Z, Y); //y+=Pi^(-1)*z
724  M_operator[q]->SetUseTranspose (useTranspose); // put back to original status
725  }
726  Z = Y;
727  }
728  }
729  Y.Scale (0.);
730  for (UInt k = 0; k < M_summed.size(); ++k)
731  {
732  if (M_inverse[M_summed[k]])
733  {
734  useTranspose = M_operator[M_summed[k]]->UseTranspose (); // storing original status
735  assert (M_operator[M_summed[k]]->SetUseTranspose (M_transpose[M_summed[k]]) != -1);
736  M_operator[M_summed[k]]->Apply (X, Y);
737  M_operator[M_summed[k]]->SetUseTranspose (useTranspose); // put back to original status
738  }
739  else
740  {
741  useTranspose = M_operator[M_summed[k]]->UseTranspose (); // storing original status
742  assert (M_operator[M_summed[k]]->SetUseTranspose (M_transpose[M_summed[k]]) != -1);
743  M_operator[M_summed[k]]->ApplyInverse (X, Y);
744  M_operator[M_summed[k]]->SetUseTranspose (useTranspose); // put back to original status
745  }
746  Z.Update (1., Y, 1.);
747  }
748 
749  Y = Z;
750  return (EXIT_SUCCESS);
751 }
752 
753 } // namespace LifeV
754 #endif
void assignFunction(bcBase_Type &base)
Assign the function to the base of the BCHandler.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
uint32_type ID
IDs.
Definition: LifeV.hpp:194
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191