Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_SchurPreconditionerImp.hpp
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 
12 #include "Teuchos_RCP.hpp"
13 
14 template <typename ordinal_type, typename value_type>
18  const ordinal_type p_, const ordinal_type m_, const ordinal_type diag_) :
19  K(K_),
20  p(p_),
21  m(m_),
22  diag(diag_)
23 {
24 }
25 
26 template <typename ordinal_type, typename value_type>
29 {
30 }
31 
32 template <typename ordinal_type, typename value_type>
35 fact (ordinal_type n) const
36 {
37  if (n > 1)
38  n = n*fact (n-1);
39  else
40  n = 1;
41  return n;
42 }
43 
44 template <typename ordinal_type, typename value_type>
48 {
49  //n is the polynomial order and m is the number of random variables
50  // return (fact(n+m)/(fact(n)*fact(m)));
52  if (n == 0 )
53  return 1;
54  else {
55  if (n<=m){
56  min = n;
57  }
58  else {
59  min = m;
60  }
61 
62  ordinal_type num = n+m;
63  for (ordinal_type i=1; i<=min-1; i++)
64  num = num*(n+m-i);
65  return num/fact(min);
66  }
67 }
68 
69 template <typename ordinal_type, typename value_type>
74  const ordinal_type n) const
75 {
76  //p: polynomial order; m: number of random variables; n: level to stop and form actual Schur Complement; diag=0: Use only diagonal of block D
78  ordinal_type ret;
79  ordinal_type lmin;
80  if (n<=1)
81  lmin=1;
82  else
83  lmin=n;
84 
86  for (ordinal_type l=p; l>=lmin; l--){
87  ordinal_type c=size(l,m);
88  ordinal_type s = size(l-1,m);
89 
90  //split residual
93 
94  //Compute pre-correction
97 
98  //Computing inv(D)r
99  if (diag == 0){
100  //For D diagonal
101  for (ordinal_type i=0; i<c-s; i++)
102  r(i,0)=r(i,0)/D(i,i);
103 
104  }
105  else{
106  //For full D block
109 
111 
112 
113  // Setup solver
114  solver.setMatrix(DD);
115  solver.setVectors(RR, RR);
116  //Solve D*r=r
117  if (solver.shouldEquilibrate()) {
118  solver.factorWithEquilibration(true);
119  solver.equilibrateMatrix();
120  }
121  solver.solve();
122 
123 
124  for (ordinal_type i=0; i<c-s; i++){
125  r(i,0)=(*RR)(i,0);
126  }
127 
128  }
129 
131  ret = rm.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS, -1.0, B, r, 1.0);
132  TEUCHOS_ASSERT(ret == 0);
133 
134  //set r(l-1)=g(l-1)
135  if (l>lmin){
136  for (ordinal_type i=0; i<s; i++)
137  Resid(i,0)=rm(i,0);
138  }
139  else {
140  //For l=1, solve A0u0=g0
141  if (n<1){
142  U(0,0)=rm(0,0)/K(0,0);
143  }
144  //Compute the Schur completement
145  else {
146  for (ordinal_type i=0; i<s; i++)
147  Resid(i,0)=rm(i,0);
148 
151  for (ordinal_type i=0; i<c-s; i++)
152  for (ordinal_type j=0; j<s; j++)
153  BinvD(j,i)=B(j,i)/D(i,i);
154 
155  S.multiply(Teuchos::NO_TRANS,Teuchos::TRANS, -1.0, BinvD, B, 1.0);
161  //Setup solver
163  solver2.setMatrix(SS);
164  solver2.setVectors(UU, RR);
165  //Solve S*u=rm
166  if (solver2.shouldEquilibrate()) {
167  solver2.factorWithEquilibration(true);
168  solver2.equilibrateMatrix();
169  }
170  solver2.solve();
171 
172  for (ordinal_type i=0; i<s; i++)
173  U(i,0)=(*UU)(i,0);
174  }
175  }
176  }
177 
178  for (ordinal_type l=lmin; l<=p; l++){
179  //compute post-correction
180  ordinal_type c = size(l,m);
181  ordinal_type s = size(l-1,m);
182 
185  //split residual
187  //Get first s values of U
189  ret = r.multiply(Teuchos::TRANS,Teuchos::NO_TRANS, -1.0, B, Ul, 1.0);
190  if (diag == 0) {
191  //For diag D
192  //Concatenate U
193  for (ordinal_type i=s; i<c; i++)
194  U(i,0)=r(-s+i,0)/D(-s+i,-s+i);
195 
196  }
197  else {
198  //For full block D
199 
203  // Setup solver
204  solver.setMatrix(DD);
205  solver.setVectors(RR, RR);
206  //Solve D*r=r
207  if (solver.shouldEquilibrate()) {
208  solver.factorWithEquilibration(true);
209  solver.equilibrateMatrix();
210  }
211  solver.solve();
212  for (ordinal_type i=s; i<c; i++)
213  U(i,0)=(*RR)(-s+i,0);
214  }
215 
216 
217  }
218 
219  return 0;
220 }
221 
222 
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
KOKKOS_INLINE_FUNCTION PCE< Storage > min(const typename PCE< Storage >::value_type &a, const PCE< Storage > &b)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual ordinal_type ApplyInverse(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Result, ordinal_type prec_iters) const
Returns the result of a Operator inverse applied to a Teuchos::SerialDenseMatrix Input in Result...
void factorWithEquilibration(bool flag)
SchurPreconditioner(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &K, const ordinal_type p, const ordinal_type m, const ordinal_type diag)
Constructor.
ordinal_type fact(ordinal_type n) const
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
ordinal_type size(ordinal_type n, ordinal_type m) const
#define TEUCHOS_ASSERT(assertion_test)
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)