Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_ProductLanczosPCEBasisImp.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 #include "Stokhos_SDMUtils.hpp"
15 
16 template <typename ordinal_type, typename value_type>
19  ordinal_type p,
23  const Teuchos::ParameterList& params_) :
24  name("Product Lanczos PCE Basis"),
25  params(params_)
26 {
28  ordinal_type pce_sz = pce_basis->size();
29 
30  // Check if basis is a product basis
33  if (prod_basis != Teuchos::null)
34  coord_bases = prod_basis->getCoordinateBases();
35 
36  // Build Lanczos basis for each pce
37  bool project = params.get("Project", true);
38  bool normalize = params.get("Normalize", true);
39  bool limit_integration_order = params.get("Limit Integration Order", false);
40  bool use_stieltjes = params.get("Use Old Stieltjes Method", false);
42  Teuchos::Array<int> is_invariant(pce.size(),-2);
43  for (ordinal_type i=0; i<pce.size(); i++) {
44 
45  // Check for pce's lying in invariant subspaces, which are pce's that
46  // depend on only a single dimension. In this case use the corresponding
47  // original coordinate basis. Convention is: -2 -- not invariant, -1 --
48  // constant, i >= 0 pce depends only on dimension i
49  if (prod_basis != Teuchos::null)
50  is_invariant[i] = isInvariant(pce[i]);
51  if (is_invariant[i] >= 0) {
52  coordinate_bases.push_back(coord_bases[is_invariant[i]]);
53  }
54 
55  // Exclude constant pce's from the basis since they don't represent
56  // stochastic dimensions
57  else if (is_invariant[i] != -1) {
58  if (use_stieltjes) {
59  coordinate_bases.push_back(
62  p, Teuchos::rcp(&(pce[i]),false), quad, false,
63  normalize, project, Cijk)));
64  }
65  else {
66  if (project)
67  coordinate_bases.push_back(
70  p, Teuchos::rcp(&(pce[i]),false), Cijk,
71  normalize, limit_integration_order)));
72  else
73  coordinate_bases.push_back(
76  p, Teuchos::rcp(&(pce[i]),false), quad,
77  normalize, limit_integration_order)));
78  }
79  }
80  }
81  ordinal_type d = coordinate_bases.size();
82 
83  // Build tensor product basis
87  coordinate_bases,
88  params.get("Cijk Drop Tolerance", 1.0e-15),
89  params.get("Use Old Cijk Algorithm", false)));
90 
91  // Build reduced quadrature
92  Teuchos::ParameterList sg_params;
93  sg_params.sublist("Basis").set< Teuchos::RCP< const Stokhos::OrthogPolyBasis<ordinal_type,value_type> > >("Stochastic Galerkin Basis", tensor_lanczos_basis);
94  sg_params.sublist("Quadrature") = params.sublist("Reduced Quadrature");
95  reduced_quad =
97 
98  // Build Psi matrix -- Psi_ij = Psi_i(x^j)*w_j/<Psi_i^2>
99  const Teuchos::Array<value_type>& weights = quad->getQuadWeights();
101  quad->getQuadPoints();
102  const Teuchos::Array< Teuchos::Array<value_type> >& basis_vals =
103  quad->getBasisAtQuadPoints();
104  ordinal_type nqp = weights.size();
105  SDM Psi(pce_sz, nqp);
106  for (ordinal_type i=0; i<pce_sz; i++)
107  for (ordinal_type k=0; k<nqp; k++)
108  Psi(i,k) = basis_vals[k][i]*weights[k]/pce_basis->norm_squared(i);
109 
110  // Build Phi matrix -- Phi_ij = Phi_i(y(x^j))
111  ordinal_type sz = tensor_lanczos_basis->size();
112  Teuchos::Array<value_type> red_basis_vals(sz);
113  Teuchos::Array<value_type> pce_vals(d);
114  Phi.shape(sz, nqp);
115  for (int k=0; k<nqp; k++) {
116  ordinal_type jdx = 0;
117  for (int j=0; j<pce.size(); j++) {
118 
119  // Exclude constant pce's
120  if (is_invariant[j] != -1) {
121 
122  // Use the identity mapping for invariant subspaces
123  if (is_invariant[j] >= 0)
124  pce_vals[jdx] = points[k][is_invariant[j]];
125  else
126  pce_vals[jdx] = pce[j].evaluate(points[k], basis_vals[k]);
127  jdx++;
128 
129  }
130 
131  }
132  tensor_lanczos_basis->evaluateBases(pce_vals, red_basis_vals);
133  for (int i=0; i<sz; i++)
134  Phi(i,k) = red_basis_vals[i];
135  }
136 
137  bool verbose = params.get("Verbose", false);
138 
139  // Compute matrix A mapping reduced space to original
140  A.shape(pce_sz, sz);
141  ordinal_type ret =
142  A.multiply(Teuchos::NO_TRANS, Teuchos::TRANS, 1.0, Psi, Phi, 0.0);
143  TEUCHOS_ASSERT(ret == 0);
144  //print_matlab(std::cout << "A = " << std::endl, A);
145 
146  // Compute pseudo-inverse of A mapping original space to reduced
147  // A = U*S*V^T -> A^+ = V*S^+*U^T = (S^+*V^T)^T*U^T where
148  // S^+ is a diagonal matrix comprised of the inverse of the diagonal of S
149  // for each nonzero, and zero otherwise
151  SDM U, Vt;
152  value_type rank_threshold = params.get("Rank Threshold", 1.0e-12);
153  ordinal_type rank = svd_threshold(rank_threshold, A, sigma, U, Vt);
154  Ainv.shape(sz, pce_sz);
155  TEUCHOS_ASSERT(rank == Vt.numRows());
156  for (ordinal_type i=0; i<Vt.numRows(); i++)
157  for (ordinal_type j=0; j<Vt.numCols(); j++)
158  Vt(i,j) = Vt(i,j) / sigma[i];
159  ret = Ainv.multiply(Teuchos::TRANS, Teuchos::TRANS, 1.0, Vt, U, 0.0);
160  TEUCHOS_ASSERT(ret == 0);
161  //print_matlab(std::cout << "Ainv = " << std::endl, Ainv);
162 
163  if (verbose) {
164  std::cout << "rank = " << rank << std::endl;
165 
166  std::cout << "diag(S) = [";
167  for (ordinal_type i=0; i<rank; i++)
168  std::cout << sigma[i] << " ";
169  std::cout << "]" << std::endl;
170 
171  // Check A = U*S*V^T
172  SDM SVt(rank, Vt.numCols());
173  for (ordinal_type i=0; i<Vt.numRows(); i++)
174  for (ordinal_type j=0; j<Vt.numCols(); j++)
175  SVt(i,j) = Vt(i,j) * sigma[i] * sigma[i]; // since we divide by sigma
176  // above
177  SDM err_A(pce_sz,sz);
178  err_A.assign(A);
179  ret = err_A.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, U, SVt,
180  1.0);
181  TEUCHOS_ASSERT(ret == 0);
182  std::cout << "||A - U*S*V^T||_infty = " << err_A.normInf() << std::endl;
183  //print_matlab(std::cout << "A - U*S*V^T = " << std::endl, err_A);
184 
185  // Check Ainv*A == I
186  SDM err(sz,sz);
187  err.putScalar(0.0);
188  for (ordinal_type i=0; i<sz; i++)
189  err(i,i) = 1.0;
191  -1.0);
192  TEUCHOS_ASSERT(ret == 0);
193  std::cout << "||Ainv*A - I||_infty = " << err.normInf() << std::endl;
194  //print_matlab(std::cout << "Ainv*A-I = " << std::endl, err);
195 
196  // Check A*Ainv == I
197  SDM err2(pce_sz,pce_sz);
198  err2.putScalar(0.0);
199  for (ordinal_type i=0; i<pce_sz; i++)
200  err2(i,i) = 1.0;
201  ret = err2.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, A, Ainv, -1.0);
202  TEUCHOS_ASSERT(ret == 0);
203  std::cout << "||A*Ainv - I||_infty = " << err2.normInf() << std::endl;
204  //print_matlab(std::cout << "A*Ainv-I = " << std::endl, err2);
205  }
206 }
207 
208 template <typename ordinal_type, typename value_type>
211 {
212 }
213 
214 template <typename ordinal_type, typename value_type>
217 order() const
218 {
219  return tensor_lanczos_basis->order();
220 }
221 
222 template <typename ordinal_type, typename value_type>
225 dimension() const
226 {
227  return tensor_lanczos_basis->dimension();
228 }
229 
230 template <typename ordinal_type, typename value_type>
233 size() const
234 {
235  return tensor_lanczos_basis->size();
236 }
237 
238 template <typename ordinal_type, typename value_type>
242 {
243  return tensor_lanczos_basis->norm_squared();
244 }
245 
246 template <typename ordinal_type, typename value_type>
247 const value_type&
250 {
251  return tensor_lanczos_basis->norm_squared(i);
252 }
253 
254 template <typename ordinal_type, typename value_type>
258 
259 {
261  tensor_lanczos_basis->computeTripleProductTensor();
262  //std::cout << *Cijk << std::endl;
263  return Cijk;
264 }
265 
266 template <typename ordinal_type, typename value_type>
270 
271 {
273  tensor_lanczos_basis->computeLinearTripleProductTensor();
274  //std::cout << *Cijk << std::endl;
275  return Cijk;
276 }
277 
278 template <typename ordinal_type, typename value_type>
282 {
283  return tensor_lanczos_basis->evaluateZero(i);
284 }
285 
286 template <typename ordinal_type, typename value_type>
287 void
290  Teuchos::Array<value_type>& basis_vals) const
291 {
292  return tensor_lanczos_basis->evaluateBases(point, basis_vals);
293 }
294 
295 template <typename ordinal_type, typename value_type>
296 void
298 print(std::ostream& os) const
299 {
300  tensor_lanczos_basis->print(os);
301 }
302 
303 template <typename ordinal_type, typename value_type>
304 const std::string&
306 getName() const
307 {
308  return name;
309 }
310 
311 template <typename ordinal_type, typename value_type>
315 {
316  return tensor_lanczos_basis->term(i);
317 }
318 
319 template <typename ordinal_type, typename value_type>
323 {
324  return tensor_lanczos_basis->index(term);
325 }
326 
327 template <typename ordinal_type, typename value_type>
331 {
332  return tensor_lanczos_basis->getCoordinateBases();
333 }
334 
335 template <typename ordinal_type, typename value_type>
339 {
340  return tensor_lanczos_basis->getMaxOrders();
341 }
342 
343 template <typename ordinal_type, typename value_type>
344 void
347  ordinal_type ncol, bool transpose) const
348 {
349  ordinal_type pce_sz = A.numRows();
350  ordinal_type sz = A.numCols();
351  if (transpose) {
352  SDM zbar(Teuchos::View, const_cast<value_type*>(in), ncol, ncol, sz);
353  SDM z(Teuchos::View, out, ncol, ncol, pce_sz);
354  ordinal_type ret =
355  z.multiply(Teuchos::NO_TRANS, Teuchos::TRANS, 1.0, zbar, A, 0.0);
356  TEUCHOS_ASSERT(ret == 0);
357  }
358  else {
359  SDM zbar(Teuchos::View, const_cast<value_type*>(in), sz, sz, ncol);
360  SDM z(Teuchos::View, out, pce_sz, pce_sz, ncol);
361  ordinal_type ret =
362  z.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, A, zbar, 0.0);
363  TEUCHOS_ASSERT(ret == 0);
364  }
365 }
366 
367 template <typename ordinal_type, typename value_type>
368 void
371  ordinal_type ncol, bool transpose) const
372 {
373  ordinal_type pce_sz = A.numRows();
374  ordinal_type sz = A.numCols();
375  if (transpose) {
376  SDM z(Teuchos::View, const_cast<value_type*>(in), ncol, ncol, pce_sz);
377  SDM zbar(Teuchos::View, out, ncol, ncol, sz);
378  ordinal_type ret =
379  zbar.multiply(Teuchos::NO_TRANS, Teuchos::TRANS, 1.0, z, Ainv, 0.0);
380  TEUCHOS_ASSERT(ret == 0);
381  }
382  else {
383  SDM z(Teuchos::View, const_cast<value_type*>(in), pce_sz, pce_sz, ncol);
384  SDM zbar(Teuchos::View, out, sz, sz, ncol);
385  ordinal_type ret =
386  zbar.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, Ainv, z, 0.0);
387  TEUCHOS_ASSERT(ret == 0);
388  }
389 }
390 
391 template <typename ordinal_type, typename value_type>
395 {
396  return reduced_quad;
397 }
398 
399 template <typename ordinal_type, typename value_type>
403 {
405  pce.basis();
406  ordinal_type dim = basis->dimension();
407  value_type tol = 1.0e-15;
408 
409  // Check if basis is a product basis
411  if (prod_basis == Teuchos::null)
412  return -2;
413 
414  // Build list of dimensions pce depends on by looping over each dimension,
415  // computing norm of pce with just that dimension -- note we don't include
416  // the constant term
417  Teuchos::Array<ordinal_type> dependent_dims;
418  tmp_pce.reset(basis);
419  for (ordinal_type i=0; i<dim; i++) {
420  ordinal_type p = prod_basis->getCoordinateBases()[i]->order();
421  tmp_pce.init(0.0);
422  for (ordinal_type j=1; j<=p; j++)
423  tmp_pce.term(i,j) = pce.term(i,j);
424  value_type nrm = tmp_pce.two_norm();
425  if (nrm > tol) dependent_dims.push_back(i);
426  }
427 
428  // If dependent_dims has length 1, pce a function of a single variable,
429  // which is an invariant subspace
430  if (dependent_dims.size() == 1)
431  return dependent_dims[0];
432 
433  // If dependent_dims has length 0, pce is constant
434  else if (dependent_dims.size() == 0)
435  return -1;
436 
437  // Otherwise pce depends on more than one variable
438  return -2;
439 }
Generates three-term recurrence using the Lanczos procedure applied to a polynomial chaos expansion i...
virtual void print(std::ostream &os) const
Print basis to stream os.
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
virtual Teuchos::RCP< Stokhos::Sparse3Tensor< ordinal_type, value_type > > computeTripleProductTensor() const
Compute triple product tensor.
T & get(ParameterList &l, const std::string &name)
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
SDM Phi
Values of transformed basis at quadrature points.
SDM Ainv
Projection matrix from original matrix to reduced.
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
virtual Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > getReducedQuadrature() const
Get reduced quadrature object.
ordinal_type svd_threshold(const scalar_type &rank_threshold, const Teuchos::SerialDenseMatrix< ordinal_type, scalar_type > &A, Teuchos::Array< scalar_type > &s, Teuchos::SerialDenseMatrix< ordinal_type, scalar_type > &U, Teuchos::SerialDenseMatrix< ordinal_type, scalar_type > &Vt)
ProductLanczosPCEBasis(ordinal_type p, const Teuchos::Array< Stokhos::OrthogPolyApprox< ordinal_type, value_type > > &pce, const Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > &quad, const Teuchos::RCP< const Stokhos::Sparse3Tensor< ordinal_type, value_type > > &Cijk, const Teuchos::ParameterList &params=Teuchos::ParameterList())
Constructor.
Generates three-term recurrence using the Discretized Stieltjes procedure applied to a polynomial cha...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual const std::string & getName() const
Return string name of basis.
virtual ordinal_type index(const MultiIndex< ordinal_type > &term) const
Get index of the multivariate polynomial given orders of each coordinate.
Abstract base class for quadrature methods.
virtual void transformToOriginalBasis(const value_type *in, value_type *out, ordinal_type ncol=1, bool transpose=false) const
Transform coefficients to original basis from this basis.
int putScalar(const ScalarType value=Teuchos::ScalarTraits< ScalarType >::zero())
ordinal_type dimension() const
Return dimension of basis.
virtual void transformFromOriginalBasis(const value_type *in, value_type *out, ordinal_type ncol=1, bool transpose=false) const
Transform coefficients from original basis to this basis.
Teuchos::RCP< const Stokhos::OrthogPolyBasis< ordinal_type, value_type > > basis() const
Return basis.
ordinal_type isInvariant(const Stokhos::OrthogPolyApprox< ordinal_type, value_type > &pce) const
Teuchos::ParameterList params
Algorithm parameters.
Abstract base class for multivariate orthogonal polynomials generated from tensor products of univari...
Multivariate orthogonal polynomial basis generated from a total-order complete-polynomial tensor prod...
Teuchos::RCP< Stokhos::CompletePolynomialBasis< ordinal_type, value_type > > tensor_lanczos_basis
Product Lanczos basis.
virtual MultiIndex< ordinal_type > getMaxOrders() const
Return maximum order allowable for each coordinate basis.
Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > reduced_quad
Reduced quadrature object.
OrdinalType numCols() const
virtual void evaluateBases(const Teuchos::ArrayView< const value_type > &point, Teuchos::Array< value_type > &basis_vals) const
Evaluate basis polynomials at given point point.
ScalarTraits< ScalarType >::magnitudeType normInf() const
void push_back(const value_type &x)
virtual ordinal_type size() const
Return total size of basis.
virtual const MultiIndex< ordinal_type > & term(ordinal_type i) const
Get orders of each coordinate polynomial given an index i.
size_type size() const
virtual const Teuchos::Array< value_type > & norm_squared() const
Return array storing norm-squared of each basis polynomial.
ordinal_type order() const
Return order of basis.
static Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > create(Teuchos::ParameterList &sgParams)
Generate quadrature object.
int shape(OrdinalType numRows, OrdinalType numCols)
#define TEUCHOS_ASSERT(assertion_test)
SerialDenseMatrix< OrdinalType, ScalarType > & assign(const SerialDenseMatrix< OrdinalType, ScalarType > &Source)
Generates three-term recurrence using the Lanczos procedure applied to a polynomial chaos expansion i...
virtual Teuchos::RCP< Stokhos::Sparse3Tensor< ordinal_type, value_type > > computeLinearTripleProductTensor() const
Compute linear triple product tensor where k = 0,1,..,d.
OrdinalType numRows() const
reference term(ordinal_type dimension, ordinal_type order)
Get coefficient term for given dimension and order.
Teuchos::Array< Teuchos::RCP< const OneDOrthogPolyBasis< ordinal_type, value_type > > > getCoordinateBases() const
Return coordinate bases.
virtual value_type evaluateZero(ordinal_type i) const
Evaluate basis polynomial i at zero.