Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_KroneckerProductPreconditioner.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 #include "Epetra_LocalMap.h"
13 #include "EpetraExt_BlockMultiVector.h"
14 #include "Teuchos_Assert.hpp"
15 
19  const Teuchos::RCP<const Stokhos::OrthogPolyBasis<int,double> >& sg_basis_,
21  const Teuchos::RCP<const Epetra_Map>& base_map_,
22  const Teuchos::RCP<const Epetra_Map>& sg_map_,
25  const Teuchos::RCP<Teuchos::ParameterList>& params_) :
26  label("Stokhos Kronecker Product Preconditioner"),
27  sg_comm(sg_comm_),
28  sg_basis(sg_basis_),
29  epetraCijk(epetraCijk_),
30  base_map(base_map_),
31  sg_map(sg_map_),
32  mean_prec_factory(mean_prec_factory_),
33  G_prec_factory(G_prec_factory_),
34  params(params_),
35  mean_prec(),
36  useTranspose(false),
37  sg_op(),
38  sg_poly(),
39  Cijk(epetraCijk->getParallelCijk()),
40  scale_op(true),
41  only_use_linear(false)
42 {
43  scale_op = params->get("Scale Operator by Inverse Basis Norms", true);
44  only_use_linear = params_->get("Only Use Linear Terms", false);
45  // Build new parallel Cijk if we are only using the linear terms, Cijk
46  // is distributed over proc's, and Cijk includes more than just the linear
47  // terms (so we have the right column map; otherwise we will be importing
48  // much more than necessary)
49  if (only_use_linear && epetraCijk->isStochasticParallel()) {
50  int dim = sg_basis->dimension();
51  if (epetraCijk->getKEnd() > dim+1)
52  epetraCijk =
54 
55  }
56 }
57 
60 {
61 }
62 
63 void
66  const Epetra_Vector& x)
67 {
68  sg_op = sg_op_;
69  sg_poly = sg_op->getSGPolynomial();
70  mean_prec = mean_prec_factory->compute(sg_poly->getCoeffPtr(0));
71  label = std::string("Stokhos Kronecker Product Preconditioner:\n") +
72  std::string(" ***** ") +
73  std::string(mean_prec->Label());
74 
75  // Build graph of G matrix
76  Teuchos::RCP<const Epetra_CrsGraph> graph = epetraCijk->getStochasticGraph();
77 
78  // Construct G matrix: G_{ij} = \sum tr(A'B)/tr(A'A)*<psi_alpha,psi_i,psi_j>.
79  const Teuchos::Array<double>& norms = sg_basis->norm_squared();
80  G = Teuchos::rcp(new Epetra_CrsMatrix(Copy, *graph));
82  Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(sg_poly->getCoeffPtr(0), true);
83  double traceAB0 = MatrixTrace(*A0, *A0);
84  Cijk_type::k_iterator k_begin = Cijk->k_begin();
85  Cijk_type::k_iterator k_end = Cijk->k_end();
86  if (only_use_linear) {
87  int dim = sg_basis->dimension();
88  k_end = Cijk->find_k(dim+1);
89  }
90  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
91  int k = index(k_it);
93  Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(sg_poly->getCoeffPtr(k),
94  true);
95  double traceAB = MatrixTrace(*A_k, *A0);
96  for (Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it);
97  j_it != Cijk->j_end(k_it); ++j_it) {
98  int j = epetraCijk->GCID(index(j_it));
99  for (Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it);
100  i_it != Cijk->i_end(j_it); ++i_it) {
101  int i = epetraCijk->GRID(index(i_it));
102  double c = value(i_it)*traceAB/traceAB0;
103  if (scale_op)
104  c /= norms[i];
105  G->SumIntoGlobalValues(i, 1, &c, &j);
106  }
107  }
108  }
109  G->FillComplete();
110 
111  // Build G preconditioner
112  G_prec = G_prec_factory->compute(G);
113 
114  label = std::string("Stokhos Kronecker Product Preconditioner:\n") +
115  std::string(" ***** ") +
116  std::string(mean_prec->Label()) + std::string("\n") +
117  std::string(" ***** ") +
118  std::string(G_prec->Label());
119 }
120 
121 int
123 SetUseTranspose(bool UseTranspose)
124 {
125  useTranspose = UseTranspose;
126  mean_prec->SetUseTranspose(useTranspose);
128  UseTranspose == true, std::logic_error,
129  "Stokhos::KroneckerProductPreconditioner::SetUseTranspose(): " <<
130  "Preconditioner does not support transpose!" << std::endl);
131 
132  return 0;
133 }
134 
135 int
137 Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const
138 {
139  EpetraExt::BlockMultiVector sg_input(View, *base_map, Input);
140  EpetraExt::BlockMultiVector sg_result(View, *base_map, Result);
141 
142  const Epetra_Map& G_map = G->RowMap();
143  int NumMyElements = G_map.NumMyElements();
144  int vecLen = sg_input.GetBlock(0)->MyLength(); // Global length of vector.
145  int m = sg_input.NumVectors();
146 
147  if (result_MVT == Teuchos::null || result_MVT->NumVectors() != vecLen*m) {
148  result_MVT = Teuchos::rcp(new Epetra_MultiVector(G_map, vecLen*m));
149  }
150 
151  // Preconditioner is P = (G x I)(I x A_0)
152 
153  // Apply I x A_0
154  for (int i=0; i<NumMyElements; i++) {
155  mean_prec->Apply(*(sg_input.GetBlock(i)), *(sg_result.GetBlock(i)));
156  }
157 
159  for (int irow=0 ; irow<NumMyElements; irow++) {
160  x = sg_result.GetBlock(irow);
161  for (int vcol=0; vcol<m; vcol++) {
162  for (int icol=0; icol<vecLen; icol++) {
163  (*result_MVT)[m*vcol+icol][irow] = (*x)[vcol][icol];
164  }
165  }
166  }
167 
168  // Apply G x I
169  G_prec->Apply(*result_MVT, *result_MVT);
170 
171  for (int irow=0; irow<NumMyElements; irow++) {
172  x = sg_result.GetBlock(irow);
173  for (int vcol=0; vcol<m; vcol++) {
174  for (int icol=0; icol<vecLen; icol++) {
175  (*x)[vcol][icol] = (*result_MVT)[m*vcol+icol][irow];
176  }
177  }
178  }
179 
180  return 0;
181 }
182 
183 int
186 {
187 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
188  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Kronecker Product Prec Time");
189 #endif
190 
191  EpetraExt::BlockMultiVector sg_input(View, *base_map, Input);
192  EpetraExt::BlockMultiVector sg_result(View, *base_map, Result);
193 
194  const Epetra_Map& G_map = G->RowMap();
195  int NumMyElements = G_map.NumMyElements();
196  int vecLen = sg_input.GetBlock(0)->MyLength(); // Global length of vector.
197  int m = sg_input.NumVectors();
198 
199  if (result_MVT == Teuchos::null || result_MVT->NumVectors() != vecLen*m) {
200  result_MVT = Teuchos::rcp(new Epetra_MultiVector(G_map, vecLen*m));
201  }
202 
203  // Preconditioner is P^{-1} = (I x A_0^{-1})(G^{-1} x I)
204  // => y = P^{-1}x => Y = A_0^{-1}(G^{-1}X^T)^T where X = multivec(x)
205 
207  for (int irow=0 ; irow<NumMyElements; irow++) {
208  x = sg_input.GetBlock(irow);
209  for (int vcol=0; vcol<m; vcol++) {
210  for (int icol=0; icol<vecLen; icol++) {
211  (*result_MVT)[m*vcol+icol][irow] = (*x)[vcol][icol];
212  }
213  }
214  }
215 
216  // Apply (G^{-1} x I)
217  {
218 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
219  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: G Preconditioner Apply Inverse");
220 #endif
221  G_prec->ApplyInverse(*result_MVT, *result_MVT);
222  }
223 
224  for (int irow=0; irow<NumMyElements; irow++) {
225  x = sg_result.GetBlock(irow);
226  for (int vcol=0; vcol<m; vcol++) {
227  for (int icol=0; icol<vecLen; icol++) {
228  (*x)[vcol][icol] = (*result_MVT)[m*vcol+icol][irow];
229  }
230  }
231  }
232 
233  // Apply (I x A_0^{-1})
234  {
235 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
236  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Mean Preconditioner Apply Inverse");
237 #endif
238  for (int i=0; i<NumMyElements; i++) {
239  mean_prec->ApplyInverse(*(sg_result.GetBlock(i)),
240  *(sg_result.GetBlock(i)));
241  }
242  }
243 
244  return 0;
245 }
246 
247 double
249 NormInf() const
250 {
251  // I think this is only an upper bound
252  return mean_prec->NormInf() * G_prec->NormInf();
253 }
254 
255 
256 const char*
258 Label() const
259 {
260  return const_cast<char*>(label.c_str());
261 }
262 
263 bool
266 {
267  return useTranspose;
268 }
269 
270 bool
272 HasNormInf() const
273 {
274  return mean_prec->NormInf() && G_prec->NormInf();
275 }
276 
277 const Epetra_Comm &
279 Comm() const
280 {
281  return *sg_comm;
282 }
283 const Epetra_Map&
286 {
287  return *sg_map;
288 }
289 
290 const Epetra_Map&
293 {
294  return *sg_map;
295 }
296 
297 double
300  int n = A.NumMyRows(); // # of rows on the processor.
301  double traceAB = 0.0;
302  for (int i=0; i<n; i++) {
303  int m = A.NumMyEntries(i); // # of non zero entries in row i.
304  for (int j=0; j<m; j++) {
305  traceAB += A[i][j]*B[i][j];
306  }
307  }
308 
309  return traceAB;
310 }
311 
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
double MatrixTrace(const Epetra_CrsMatrix &A, const Epetra_CrsMatrix &B) const
Compute trace of matrix A&#39;B.
virtual const Epetra_Comm & Comm() const
Returns a reference to the Epetra_Comm communicator associated with this operator.
Teuchos::RCP< const Stokhos::EpetraSparse3Tensor > epetraCijk
Stores Epetra Cijk tensor.
int NumMyEntries(int Row) const
virtual double NormInf() const
Returns an approximate infinity norm of the operator matrix.
T & get(ParameterList &l, const std::string &name)
bool only_use_linear
Limit construction of G to linear terms.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual const Epetra_Map & OperatorDomainMap() const
Returns the Epetra_Map object associated with the domain of this matrix operator. ...
virtual void setupPreconditioner(const Teuchos::RCP< Stokhos::SGOperator > &sg_op, const Epetra_Vector &x)
Setup preconditioner.
virtual ordinal_type dimension() const =0
Return dimension of basis.
KroneckerProductPreconditioner(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 > &mean_prec_factory, const Teuchos::RCP< Stokhos::AbstractPreconditionerFactory > &G_prec_factory, const Teuchos::RCP< Teuchos::ParameterList > &params)
Constructor.
Bi-directional iterator for traversing a sparse array.
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 ...
virtual const Epetra_Map & OperatorRangeMap() const
Returns the Epetra_Map object associated with the range of this matrix operator.
int NumMyElements() const
virtual bool HasNormInf() const
Returns true if the this object can provide an approximate Inf-norm, false otherwise.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool scale_op
Flag indicating whether operator be scaled with &lt;^2&gt;
Teuchos::RCP< Teuchos::ParameterList > params
Preconditioner parameters.
Teuchos::RCP< const Stokhos::OrthogPolyBasis< int, double > > sg_basis
Stochastic Galerking basis.
virtual Teuchos::RCP< Stokhos::EpetraOperatorOrthogPoly > getSGPolynomial()=0
Get SG polynomial.
int NumMyRows() const
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 const char * Label() const
Returns a character string describing the 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.
int n