Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_GMRESDivisionExpansionStrategy.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 
10 #ifndef STOKHOS_GMRES_DIVISION_EXPANSION_STRATEGY_HPP
11 #define STOKHOS_GMRES_DIVISION_EXPANSION_STRATEGY_HPP
12 
21 
22 #include "Teuchos_TimeMonitor.hpp"
23 #include "Teuchos_RCP.hpp"
25 #include "Teuchos_BLAS.hpp"
26 #include "Teuchos_LAPACK.hpp"
27 
28 namespace Stokhos {
29 
31 
34  template <typename ordinal_type, typename value_type, typename node_type>
36  public DivisionExpansionStrategy<ordinal_type,value_type,node_type> {
37  public:
38 
43  const ordinal_type prec_iter_,
44  const value_type tol_,
45  const ordinal_type PrecNum_,
46  const ordinal_type max_it_,
47  const ordinal_type linear_,
48  const ordinal_type diag_,
49  const ordinal_type equil_);
50 
53 
54  // Division operation: c = \alpha*(a/b) + beta*c
55  virtual void divide(
57  const value_type& alpha,
60  const value_type& beta);
61 
62  private:
63 
64  // Prohibit copying
67 
68  // Prohibit Assignment
71 
76  ordinal_type max_iter,
77  value_type tolerance,
79  ordinal_type order,
80  ordinal_type dim,
84 
85  protected:
86 
89 
92 
95 
98 
100 
102 
104 
106 
108 
110 
112 
114 
115 
116  }; // class GMRESDivisionExpansionStrategy
117 
118 } // namespace Stokhos
119 
120 template <typename ordinal_type, typename value_type, typename node_type>
125  const ordinal_type prec_iter_,
126  const value_type tol_,
127  const ordinal_type PrecNum_,
128  const ordinal_type max_it_,
129  const ordinal_type linear_,
130  const ordinal_type diag_,
131  const ordinal_type equil_):
132  basis(basis_),
133  Cijk(Cijk_),
134  prec_iter(prec_iter_),
135  tol(tol_),
136  PrecNum(PrecNum_),
137  max_it(max_it_),
138  linear(linear_),
139  diag(diag_),
140  equil(equil_)
141 {
142  ordinal_type sz = basis->size();
144  sz, sz));
146  sz, 1));
148  sz, 1));
150  sz, sz));
151 
152 }
153 
154 
155 template <typename ordinal_type, typename value_type, typename node_type>
156 void
159  const value_type& alpha,
162  const value_type& beta)
163 {
164 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
165  TEUCHOS_FUNC_TIME_MONITOR("Stokhos::GMRESDivisionStrategy::divide()");
166 #endif
167 
168  ordinal_type sz = basis->size();
169  ordinal_type pa = a.size();
170  ordinal_type pb = b.size();
171  ordinal_type pc;
172  if (pb > 1)
173  pc = sz;
174  else
175  pc = pa;
176  if (c.size() != pc)
177  c.resize(pc);
178 
179  const value_type* ca = a.coeff();
180  const value_type* cb = b.coeff();
181  value_type* cc = c.coeff();
182 
183  if (pb > 1) {
184  // Compute A
185  A->putScalar(0.0);
186  typename Cijk_type::k_iterator k_begin = Cijk->k_begin();
187  typename Cijk_type::k_iterator k_end = Cijk->k_end();
188  if (pb < Cijk->num_k())
189  k_end = Cijk->find_k(pb);
191  ordinal_type i,j,k;
192  for (typename Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
193  k = index(k_it);
194  for (typename Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it);
195  j_it != Cijk->j_end(k_it); ++j_it) {
196  j = index(j_it);
197  for (typename Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it);
198  i_it != Cijk->i_end(j_it); ++i_it) {
199  i = index(i_it);
200  cijk = value(i_it);
201  (*A)(i,j) += cijk*cb[k];
202  }
203  }
204  }
205 
206  // Compute B
207  B->putScalar(0.0);
208  for (ordinal_type i=0; i<pa; i++)
209  (*B)(i,0) = ca[i]*basis->norm_squared(i);
210 
212  //Equilibrate the linear system
213  if (equil == 1){
214  //Create diag mtx of max row entries
215  for (ordinal_type i=0; i<sz; i++){
217  D(i,0)=sqrt(r.normOne());
218  }
219  //Compute inv(D)*A*inv(D)
220  for (ordinal_type i=0; i<sz; i++){
221  for (ordinal_type j=0; j<sz; j++){
222  (*A)(i,j)=(*A)(i,j)/(D(i,0)*D(j,0));
223  }
224  }
225 
226  //Scale b by inv(D)
227  for (ordinal_type i=0; i<sz; i++){
228  (*B)(i,0)=(*B)(i,0)/D(i,0);
229  }
230 
231  }
232 
233  if (linear == 1){
234  //Compute M, the linear matrix to be used in the preconditioner
235  pb = basis->dimension()+1;
236  M->putScalar(0.0);
237  if (pb < Cijk->num_k())
238  k_end = Cijk->find_k(pb);
239  for (typename Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
240  k = index(k_it);
241  for ( typename Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it);
242  j_it != Cijk->j_end(k_it); ++j_it) {
243  j = index(j_it);
244  for ( typename Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it);
245  i_it != Cijk->i_end(j_it); ++i_it) {
246  i = index(i_it);
247  cijk = value(i_it);
248  (*M)(i,j) += cijk*cb[k];
249  }
250  }
251  }
252 
253  //Scale M
254  if (equil == 1){
255  //Compute inv(D)*M*inv(D)
256  for (ordinal_type i=0; i<sz; i++){
257  for (ordinal_type j=0; j<sz; j++){
258  (*M)(i,j)=(*M)(i,j)/(D(i,0)*D(j,0));
259  }
260  }
261  }
262 
263 
264  // Compute X = A^{-1}*B
265  GMRES(*A,*X,*B, max_it, tol, prec_iter, basis->order(), basis->dimension(), PrecNum, *M, diag);
266  }
267 
268  else{
269  GMRES(*A,*X,*B, max_it, tol, prec_iter, basis->order(), basis->dimension(), PrecNum, *A, diag);
270  }
271 
272  if (equil == 1 ) {
273  //Rescale X
274  for (ordinal_type i=0; i<sz; i++){
275  (*X)(i,0)=(*X)(i,0)/D(i,0);
276  }
277  }
278 
279  // Compute c
280  for (ordinal_type i=0; i<pc; i++)
281  cc[i] = alpha*(*X)(i,0) + beta*cc[i];
282  }
283  else {
284  for (ordinal_type i=0; i<pc; i++)
285  cc[i] = alpha*ca[i]/cb[0] + beta*cc[i];
286  }
287 }
288 
289 
290 template <typename ordinal_type, typename value_type, typename node_type>
296  ordinal_type max_iter,
297  value_type tolerance,
298  ordinal_type prec_iter,
299  ordinal_type order,
300  ordinal_type dim,
301  ordinal_type PrecNum,
304 {
305  ordinal_type n = A.numRows();
306  ordinal_type k = 1;
307  value_type resid;
310  Ax.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, X, 0.0);
312  r0-=Ax;
313  resid=r0.normFrobenius();
314  //define vector v=r/norm(r) where r=b-Ax
316  r0.scale(1/resid);
318  //Matrix of orthog basis vectors V
320  //Set v=r0/norm(r0) to be 1st col of V
321  for (ordinal_type i=0; i<n; i++){
322  V(i,0)=r0(i,0);
323  }
324  //right hand side
326  bb(0,0)=resid;
330  while (resid > tolerance && k < max_iter){
331  h.reshape(k+1,k);
332  //Arnoldi iteration(Gram-Schmidt )
333  V.reshape(n,k+1);
334  //set vk to be kth col of V
336  //Preconditioning step: solve Mz=vk
338  if (PrecNum == 1){
340  precond.ApplyInverse(vk,z,prec_iter);
341  }
342  else if (PrecNum == 2){
344  precond.ApplyInverse(vk,z,2);
345  }
346  else if (PrecNum == 3){
348  precond.ApplyInverse(vk,z,1);
349  }
350  else if (PrecNum == 4){
351  Stokhos::SchurPreconditioner<ordinal_type, value_type> precond(M, order, dim, diag);
352  precond.ApplyInverse(vk,z,prec_iter);
353  }
354 
355  w.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1, A, z, 0.0);
358  for (ordinal_type i=0; i<k; i++){
359  //set vi to be ith col of V
361  //Calculate inner product
362  ip.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, vi, w, 0.0);
363  h(i,k-1)= ip(0,0);
364  //scale vi by h(i,k-1)
365  vi.scale(ip(0,0));
366  w-=vi;
367  }
368  h(k,k-1)=w.normFrobenius();
369  w.scale(1.0/h(k,k-1));
370  //add column vk+1=w to V
371  for (ordinal_type i=0; i<n; i++){
372  V(i,k)=w(i,0);
373  }
374  //Solve upper hessenberg least squares problem via Givens rotations
375  //Compute previous Givens rotations
376  for (ordinal_type i=0; i<k-1; i++){
377  value_type q=c(i,0)*h(i,k-1)+s(i,0)*h(i+1,k-1);
378  h(i+1,k-1)=-1*s(i,0)*h(i,k-1)+c(i,0)*h(i+1,k-1);
379  h(i,k-1)=q;
380 
381  }
382  //Compute next Givens rotations
383  c.reshape(k,1);
384  s.reshape(k,1);
385  bb.reshape(k+1,1);
386  value_type l = sqrt(h(k-1,k-1)*h(k-1,k-1)+h(k,k-1)*h(k,k-1));
387  c(k-1,0)=h(k-1,k-1)/l;
388  s(k-1,0)=h(k,k-1)/l;
389 
390  // Givens rotation on h and bb
391  h(k-1,k-1)=l;
392  h(k,k-1)=0;
393 
394  bb(k,0)=-s(k-1,0)*bb(k-1,0);
395  bb(k-1,0)=c(k-1,0)*bb(k-1,0);
396 
397  //Determine residual
398  resid = fabs(bb(k,0));
399  k++;
400  }
401  //Extract upper triangular square matrix
402  bb.reshape(h.numRows()-1 ,1);
403  //Solve linear system
404  ordinal_type info;
406  lapack.TRTRS('U', 'N', 'N', h.numRows()-1, 1, h.values(), h.stride(), bb.values(), bb.stride(),&info);
408  V.reshape(n,k-1);
409  ans.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, V, bb, 0.0);
410  if (PrecNum == 1){
412  precond.ApplyInverse(ans,ans,prec_iter);
413  }
414  else if (PrecNum == 2){
416  precond.ApplyInverse(ans,ans,2);
417  }
418  else if (PrecNum == 3){
420  precond.ApplyInverse(ans,ans,1);
421  }
422  else if (PrecNum == 4){
423  Stokhos::SchurPreconditioner<ordinal_type, value_type> precond(M, order, dim, diag);
424  precond.ApplyInverse(ans,ans,prec_iter);}
425  X+=ans;
426 
427  //std::cout << "iteration count= " << k-1 << std::endl;
428 
429  return 0;
430 }
431 
432 #endif // STOKHOS_DIVISION_EXPANSION_STRATEGY_HPP
ScalarTraits< ScalarType >::magnitudeType normOne() const
ScalarType * values() const
KOKKOS_INLINE_FUNCTION PCE< Storage > sqrt(const PCE< Storage > &a)
KOKKOS_INLINE_FUNCTION PCE< Storage > fabs(const PCE< Storage > &a)
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
void resize(ordinal_type sz)
Resize coefficient array (coefficients are preserved)
Teuchos::RCP< const Cijk_type > Cijk
Triple product.
virtual ordinal_type ApplyInverse(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Result, ordinal_type m) const
Returns the result of a Operator inverse applied to a Teuchos::SerialDenseMatrix Input in Result...
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
void TRTRS(const char &UPLO, const char &TRANS, const char &DIAG, const OrdinalType &n, const OrdinalType &nrhs, const ScalarType *A, const OrdinalType &lda, ScalarType *B, const OrdinalType &ldb, OrdinalType *info) const
Stokhos::Sparse3Tensor< ordinal_type, value_type > Cijk_type
Short-hand for Cijk.
int scale(const ScalarType alpha)
ordinal_type GMRES(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &A, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &X, const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &B, ordinal_type max_iter, value_type tolerance, ordinal_type prec_iter, ordinal_type order, ordinal_type dim, ordinal_type PrecNum, const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &M, ordinal_type diag)
pointer coeff()
Return coefficient array.
Teuchos::RCP< const Stokhos::OrthogPolyBasis< ordinal_type, value_type > > basis
Basis.
ScalarTraits< ScalarType >::magnitudeType normFrobenius() const
virtual ordinal_type ApplyInverse(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Result, ordinal_type m) const
Returns the result of a Operator inverse applied to a Teuchos::SerialDenseMatrix Input in Result...
Bi-directional iterator for traversing a sparse array.
Abstract base class for multivariate orthogonal polynomials.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > B
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...
int putScalar(const ScalarType value=Teuchos::ScalarTraits< ScalarType >::zero())
Strategy interface for computing PCE of a/b.
virtual void divide(Stokhos::OrthogPolyApprox< ordinal_type, value_type, node_type > &c, const value_type &alpha, const Stokhos::OrthogPolyApprox< ordinal_type, value_type, node_type > &a, const Stokhos::OrthogPolyApprox< ordinal_type, value_type, node_type > &b, const value_type &beta)
virtual ordinal_type ApplyInverse(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &Result, ordinal_type m) const
Returns the result of a Operator inverse applied to a Teuchos::SerialDenseMatrix Input in Result...
Teuchos::RCP< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > M
Teuchos::RCP< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > X
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< is_view_uq_pce< view_type >::value, typename CijkType< view_type >::type >::type cijk(const view_type &view)
Strategy interface for computing PCE of a/b using only b[0].
Class to store coefficients of a projection onto an orthogonal polynomial basis.
int reshape(OrdinalType numRows, OrdinalType numCols)
ordinal_type size() const
Return size.
GMRESDivisionExpansionStrategy & operator=(const GMRESDivisionExpansionStrategy &b)
int n
GMRESDivisionExpansionStrategy(const Teuchos::RCP< const Stokhos::OrthogPolyBasis< ordinal_type, value_type > > &basis_, const Teuchos::RCP< const Stokhos::Sparse3Tensor< ordinal_type, value_type > > &Cijk_, const ordinal_type prec_iter_, const value_type tol_, const ordinal_type PrecNum_, const ordinal_type max_it_, const ordinal_type linear_, const ordinal_type diag_, const ordinal_type equil_)
Constructor.
OrdinalType stride() const
OrdinalType numRows() const
Teuchos::RCP< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > A
Dense matrices for linear system.