Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_ApproxGaussSeidelPreconditioner.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
11 #include "Teuchos_TimeMonitor.hpp"
12 
16  const Teuchos::RCP<const Stokhos::OrthogPolyBasis<int,double> >& sg_basis_,
18  const Teuchos::RCP<const Epetra_Map>& base_map_,
19  const Teuchos::RCP<const Epetra_Map>& sg_map_,
21  const Teuchos::RCP<Teuchos::ParameterList>& params_) :
22  label("Stokhos Approximate Gauss-Seidel Preconditioner"),
23  sg_comm(sg_comm_),
24  sg_basis(sg_basis_),
25  epetraCijk(epetraCijk_),
26  base_map(base_map_),
27  sg_map(sg_map_),
28  prec_factory(prec_factory_),
29  mean_prec(),
30  useTranspose(false),
31  sg_op(),
32  sg_poly(),
33  Cijk(epetraCijk->getParallelCijk()),
34  scale_op(true),
35  symmetric(false),
36  only_use_linear(true),
37  mat_vec_tmp(),
38  rhs_block()
39 {
40  scale_op = params_->get("Scale Operator by Inverse Basis Norms", true);
41  symmetric = params_->get("Symmetric Gauss-Seidel", false);
42  only_use_linear = params_->get("Only Use Linear Terms", true);
43 }
44 
47 {
48 }
49 
50 void
53  const Epetra_Vector& x)
54 {
55  sg_op = sg_op_;
56  sg_poly = sg_op->getSGPolynomial();
57  mean_prec = prec_factory->compute(sg_poly->getCoeffPtr(0));
58  label = std::string("Stokhos Approximate Gauss-Seidel Preconditioner:\n") +
59  std::string(" ***** ") +
60  std::string(mean_prec->Label());
61 }
62 
63 int
65 SetUseTranspose(bool UseTheTranspose)
66 {
67  useTranspose = UseTheTranspose;
68  sg_op->SetUseTranspose(UseTheTranspose);
69  mean_prec->SetUseTranspose(UseTheTranspose);
70 
71  return 0;
72 }
73 
74 int
76 Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const
77 {
78  return sg_op->Apply(Input, Result);
79 }
80 
81 int
84 {
85 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
86  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Approximate Gauss-Seidel Time");
87 #endif
88 
89  // We have to be careful if Input and Result are the same vector.
90  // If this is the case, the only possible solution is to make a copy
91  const Epetra_MultiVector *input = &Input;
92  bool made_copy = false;
93  if (Input.Values() == Result.Values()) {
94  input = new Epetra_MultiVector(Input);
95  made_copy = true;
96  }
97 
98  int m = input->NumVectors();
99  if (mat_vec_tmp == Teuchos::null || mat_vec_tmp->NumVectors() != m)
100  mat_vec_tmp = Teuchos::rcp(new Epetra_MultiVector(*base_map, m));
101  if (rhs_block == Teuchos::null || rhs_block->NumVectors() != m)
102  rhs_block =
103  Teuchos::rcp(new EpetraExt::BlockMultiVector(*base_map, *sg_map, m));
104 
105  // Extract blocks
106  EpetraExt::BlockMultiVector input_block(View, *base_map, *input);
107  EpetraExt::BlockMultiVector result_block(View, *base_map, Result);
108 
109  result_block.PutScalar(0.0);
110 
111  int k_limit = sg_poly->size();
112  if (only_use_linear)
113  k_limit = sg_poly->basis()->dimension() + 1;
114  const Teuchos::Array<double>& norms = sg_basis->norm_squared();
115 
116  rhs_block->Update(1.0, input_block, 0.0);
117 
118  for (Cijk_type::i_iterator i_it=Cijk->i_begin();
119  i_it!=Cijk->i_end(); ++i_it) {
120  int i = index(i_it);
121 
122  Teuchos::RCP<Epetra_MultiVector> res_i = result_block.GetBlock(i);
123  {
124  // Apply deterministic preconditioner
125 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
126  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total AGS Deterministic Preconditioner Time");
127 #endif
128  mean_prec->ApplyInverse(*(rhs_block->GetBlock(i)), *res_i);
129  }
130 
131  int i_gid = epetraCijk->GRID(i);
132  for (Cijk_type::ik_iterator k_it = Cijk->k_begin(i_it);
133  k_it != Cijk->k_end(i_it); ++k_it) {
134  int k = index(k_it);
135  if (k!=0 && k<k_limit) {
136  bool do_mat_vec = false;
137  for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it);
138  j_it != Cijk->j_end(k_it); ++j_it) {
139  int j = index(j_it);
140  int j_gid = epetraCijk->GCID(j);
141  if (j_gid > i_gid) {
142  bool on_proc = epetraCijk->myGRID(j_gid);
143  if (on_proc) {
144  do_mat_vec = true;
145  break;
146  }
147  }
148  }
149  if (do_mat_vec) {
150  (*sg_poly)[k].Apply(*res_i, *mat_vec_tmp);
151  for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it);
152  j_it != Cijk->j_end(k_it); ++j_it) {
153  int j = index(j_it);
154  int j_gid = epetraCijk->GCID(j);
155  double c = value(j_it);
156  if (scale_op) {
157  if (useTranspose)
158  c /= norms[i_gid];
159  else
160  c /= norms[j_gid];
161  }
162  if (j_gid > i_gid) {
163  bool on_proc = epetraCijk->myGRID(j_gid);
164  if (on_proc) {
165  rhs_block->GetBlock(j)->Update(-c, *mat_vec_tmp, 1.0);
166  }
167  }
168  }
169  }
170  }
171  }
172  }
173 
174  // For symmetric Gauss-Seidel
175  if (symmetric) {
176 
177  for (Cijk_type::i_reverse_iterator i_it= Cijk->i_rbegin();
178  i_it!=Cijk->i_rend(); ++i_it) {
179  int i = index(i_it);
180 
181  Teuchos::RCP<Epetra_MultiVector> res_i = result_block.GetBlock(i);
182  {
183  // Apply deterministic preconditioner
184 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
185  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total AGS Deterministic Preconditioner Time");
186 #endif
187  mean_prec->ApplyInverse(*(rhs_block->GetBlock(i)), *res_i);
188  }
189 
190  int i_gid = epetraCijk->GRID(i);
191  for (Cijk_type::ik_iterator k_it = Cijk->k_begin(i_it);
192  k_it != Cijk->k_end(i_it); ++k_it) {
193  int k = index(k_it);
194  if (k!=0 && k<k_limit) {
195  bool do_mat_vec = false;
196  for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it);
197  j_it != Cijk->j_end(k_it); ++j_it) {
198  int j = index(j_it);
199  int j_gid = epetraCijk->GCID(j);
200  if (j_gid < i_gid) {
201  bool on_proc = epetraCijk->myGRID(j_gid);
202  if (on_proc) {
203  do_mat_vec = true;
204  break;
205  }
206  }
207  }
208  if (do_mat_vec) {
209  (*sg_poly)[k].Apply(*res_i, *mat_vec_tmp);
210  for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it);
211  j_it != Cijk->j_end(k_it); ++j_it) {
212  int j = index(j_it);
213  int j_gid = epetraCijk->GCID(j);
214  double c = value(j_it);
215  if (scale_op)
216  c /= norms[j_gid];
217  if (j_gid < i_gid) {
218  bool on_proc = epetraCijk->myGRID(j_gid);
219  if (on_proc) {
220  rhs_block->GetBlock(j)->Update(-c, *mat_vec_tmp, 1.0);
221  }
222  }
223  }
224  }
225  }
226  }
227  }
228  }
229 
230  if (made_copy)
231  delete input;
232 
233  return 0;
234 }
235 
236 double
238 NormInf() const
239 {
240  return sg_op->NormInf();
241 }
242 
243 
244 const char*
246 Label() const
247 {
248  return const_cast<char*>(label.c_str());
249 }
250 
251 bool
254 {
255  return useTranspose;
256 }
257 
258 bool
260 HasNormInf() const
261 {
262  return sg_op->HasNormInf();
263 }
264 
265 const Epetra_Comm &
267 Comm() const
268 {
269  return *sg_comm;
270 }
271 const Epetra_Map&
274 {
275  return *sg_map;
276 }
277 
278 const Epetra_Map&
281 {
282  return *sg_map;
283 }
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
T & get(ParameterList &l, const std::string &name)
virtual bool HasNormInf() const
Returns true if the this object can provide an approximate Inf-norm, false otherwise.
ApproxGaussSeidelPreconditioner(const Teuchos::RCP< const EpetraExt::MultiComm > &sg_comm, const Teuchos::RCP< const Stokhos::OrthogPolyBasis< int, double > > &sg_basis, const Teuchos::RCP< const Stokhos::EpetraSparse3Tensor > &epetraCijk, const Teuchos::RCP< const Epetra_Map > &base_map, const Teuchos::RCP< const Epetra_Map > &sg_map, const Teuchos::RCP< Stokhos::AbstractPreconditionerFactory > &prec_factory, const Teuchos::RCP< Teuchos::ParameterList > &params)
Constructor.
virtual const Epetra_Map & OperatorRangeMap() const
Returns the Epetra_Map object associated with the range of this matrix operator.
Bi-directional iterator for traversing a sparse array.
Bi-directional reverse iterator for traversing a sparse array.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Returns the result of the inverse of the operator applied to a Epetra_MultiVector Input in Result as ...
bool scale_op
Flag indicating whether operator be scaled with &lt;^2&gt;
virtual int Apply(const Epetra_MultiVector &Input, Epetra_MultiVector &Result) const
Returns the result of a Epetra_Operator applied to a Epetra_MultiVector Input in Result as described ...
virtual Teuchos::RCP< Stokhos::EpetraOperatorOrthogPoly > getSGPolynomial()=0
Get SG polynomial.
bool only_use_linear
Limit Gauss-Seidel loop to linear terms.
virtual const Epetra_Comm & Comm() const
Returns a reference to the Epetra_Comm communicator associated with this operator.
virtual bool UseTranspose() const
Returns the current UseTranspose setting.
virtual int SetUseTranspose(bool UseTranspose)
Set to true if the transpose of the operator is requested.
virtual void setupPreconditioner(const Teuchos::RCP< Stokhos::SGOperator > &sg_op, const Epetra_Vector &x)
Setup preconditioner.
virtual double NormInf() const
Returns an approximate infinity norm of the operator matrix.
virtual const char * Label() const
Returns a character string describing the operator.
virtual const Epetra_Map & OperatorDomainMap() const
Returns the Epetra_Map object associated with the domain of this matrix operator. ...