Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_ProductLanczosGramSchmidtPCEBasisImp.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 #include "Stokhos_ProductBasis.hpp"
17 
18 template <typename ordinal_type, typename value_type>
21  ordinal_type max_p,
25  const Teuchos::ParameterList& params_) :
26  name("Product Lanczos Gram-Schmidt PCE Basis"),
27  params(params_),
28  p(max_p)
29 {
31  pce_sz = pce_basis->size();
32 
33  // Check if basis is a product basis
36  if (prod_basis != Teuchos::null)
37  coord_bases = prod_basis->getCoordinateBases();
38 
39  // Build Lanczos basis for each pce
40  bool project = params.get("Project", true);
41  bool normalize = params.get("Normalize", true);
42  bool limit_integration_order = params.get("Limit Integration Order", false);
43  bool use_stieltjes = params.get("Use Old Stieltjes Method", false);
45  Teuchos::Array<int> is_invariant(pce.size(),-2);
46  for (ordinal_type i=0; i<pce.size(); i++) {
47 
48  // Check for pce's lying in invariant subspaces, which are pce's that
49  // depend on only a single dimension. In this case use the corresponding
50  // original coordinate basis. Convention is: -2 -- not invariant, -1 --
51  // constant, i >= 0 pce depends only on dimension i
52  if (prod_basis != Teuchos::null)
53  is_invariant[i] = isInvariant(pce[i]);
54  if (is_invariant[i] >= 0) {
55  coordinate_bases.push_back(coord_bases[is_invariant[i]]);
56  }
57 
58  // Exclude constant pce's from the basis since they don't represent
59  // stochastic dimensions
60  else if (is_invariant[i] != -1) {
61  if (use_stieltjes) {
62  coordinate_bases.push_back(
65  p, Teuchos::rcp(&(pce[i]),false), quad, false,
66  normalize, project, Cijk)));
67  }
68  else {
69  if (project)
70  coordinate_bases.push_back(
73  p, Teuchos::rcp(&(pce[i]),false), Cijk,
74  normalize, limit_integration_order)));
75  else
76  coordinate_bases.push_back(
79  p, Teuchos::rcp(&(pce[i]),false), quad,
80  normalize, limit_integration_order)));
81  }
82  }
83  }
84  d = coordinate_bases.size();
85 
86  // Build tensor product basis
90  coordinate_bases,
91  params.get("Cijk Drop Tolerance", 1.0e-15),
92  params.get("Use Old Cijk Algorithm", false)));
93 
94  // Build Psi matrix -- Psi_ij = Psi_i(x^j)*w_j/<Psi_i^2>
95  const Teuchos::Array<value_type>& weights = quad->getQuadWeights();
97  quad->getQuadPoints();
98  const Teuchos::Array< Teuchos::Array<value_type> >& basis_vals =
99  quad->getBasisAtQuadPoints();
100  ordinal_type nqp = weights.size();
101  SDM Psi(pce_sz, nqp);
102  for (ordinal_type i=0; i<pce_sz; i++)
103  for (ordinal_type k=0; k<nqp; k++)
104  Psi(i,k) = basis_vals[k][i]*weights[k]/pce_basis->norm_squared(i);
105 
106  // Build Phi matrix -- Phi_ij = Phi_i(y(x^j))
107  sz = tensor_lanczos_basis->size();
108  Teuchos::Array<value_type> red_basis_vals(sz);
109  Teuchos::Array<value_type> pce_vals(d);
110  SDM Phi(sz, nqp);
111  SDM F(nqp, d);
112  for (int k=0; k<nqp; k++) {
113  ordinal_type jdx = 0;
114  for (int j=0; j<pce.size(); j++) {
115 
116  // Exclude constant pce's
117  if (is_invariant[j] != -1) {
118 
119  // Use the identity mapping for invariant subspaces
120  if (is_invariant[j] >= 0)
121  pce_vals[jdx] = points[k][is_invariant[j]];
122  else
123  pce_vals[jdx] = pce[j].evaluate(points[k], basis_vals[k]);
124  F(k,jdx) = pce_vals[jdx];
125  jdx++;
126 
127  }
128 
129  }
130  tensor_lanczos_basis->evaluateBases(pce_vals, red_basis_vals);
131  for (int i=0; i<sz; i++)
132  Phi(i,k) = red_basis_vals[i];
133  }
134 
135  bool verbose = params.get("Verbose", false);
136 
137  // Compute matrix A mapping reduced space to original
138  SDM A(pce_sz, sz);
139  ordinal_type ret =
140  A.multiply(Teuchos::NO_TRANS, Teuchos::TRANS, 1.0, Psi, Phi, 0.0);
141  TEUCHOS_ASSERT(ret == 0);
142 
143  // Rescale columns of A to have unit norm
144  const Teuchos::Array<value_type>& basis_norms = pce_basis->norm_squared();
145  for (ordinal_type j=0; j<sz; j++) {
146  value_type nrm = 0.0;
147  for (ordinal_type i=0; i<pce_sz; i++)
148  nrm += A(i,j)*A(i,j)*basis_norms[i];
149  nrm = std::sqrt(nrm);
150  for (ordinal_type i=0; i<pce_sz; i++)
151  A(i,j) /= nrm;
152  }
153 
154  // Compute our new basis -- each column of Qp is the coefficients of the
155  // new basis in the original basis. Constraint pivoting so first d+1
156  // columns and included in Qp.
157  value_type rank_threshold = params.get("Rank Threshold", 1.0e-12);
158  std::string orthogonalization_method =
159  params.get("Orthogonalization Method", "Householder");
160  Teuchos::Array<value_type> w(pce_sz, 1.0);
161  SDM R;
163  for (int i=0; i<d+1; i++)
164  piv[i] = 1;
166  sz = SOF::createOrthogonalBasis(
167  orthogonalization_method, rank_threshold, verbose, A, w, Qp, R, piv);
168 
169  // Original basis at quadrature points -- needed to transform expansions
170  // in this basis back to original
171  SDM B(nqp, pce_sz);
172  for (ordinal_type i=0; i<nqp; i++)
173  for (ordinal_type j=0; j<pce_sz; j++)
174  B(i,j) = basis_vals[i][j];
175 
176  // Evaluate new basis at original quadrature points
177  Q.reshape(nqp, sz);
178  ret = Q.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, B, Qp, 0.0);
179  TEUCHOS_ASSERT(ret == 0);
180 
181  // Compute reduced quadrature rule
183  params.sublist("Reduced Quadrature"));
185  reduced_quad = quad_factory.createReducedQuadrature(Q, Q2, F, weights);
186 
187  // Basis is orthonormal by construction
188  norms.resize(sz, 1.0);
189 }
190 
191 template <typename ordinal_type, typename value_type>
194 {
195 }
196 
197 template <typename ordinal_type, typename value_type>
200 order() const
201 {
202  return p;
203 }
204 
205 template <typename ordinal_type, typename value_type>
208 dimension() const
209 {
210  return d;
211 }
212 
213 template <typename ordinal_type, typename value_type>
216 size() const
217 {
218  return sz;
219 }
220 
221 template <typename ordinal_type, typename value_type>
225 {
226  return norms;
227 }
228 
229 template <typename ordinal_type, typename value_type>
230 const value_type&
233 {
234  return norms[i];
235 }
236 
237 template <typename ordinal_type, typename value_type>
241 
242 {
243  return Teuchos::null;
244 }
245 
246 template <typename ordinal_type, typename value_type>
250 
251 {
252  return Teuchos::null;
253 }
254 
255 template <typename ordinal_type, typename value_type>
259 {
260  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented!");
261 }
262 
263 template <typename ordinal_type, typename value_type>
264 void
267  Teuchos::Array<value_type>& basis_vals) const
268 {
269  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented!");
270 }
271 
272 template <typename ordinal_type, typename value_type>
273 void
275 print(std::ostream& os) const
276 {
277  os << "Product Lanczos Gram-Schmidt basis of order " << p << ", dimension "
278  << d
279  << ", and size " << sz << ". Matrix coefficients:\n";
280  os << printMat(Qp) << std::endl;
281  os << "Basis vector norms (squared):\n\t";
282  for (ordinal_type i=0; i<sz; i++)
283  os << norms[i] << " ";
284  os << "\n";
285 }
286 
287 template <typename ordinal_type, typename value_type>
288 const std::string&
290 getName() const
291 {
292  return name;
293 }
294 
295 template <typename ordinal_type, typename value_type>
296 void
299  ordinal_type ncol, bool transpose) const
300 {
301  if (transpose) {
302  SDM zbar(Teuchos::View, const_cast<value_type*>(in), ncol, ncol, sz);
303  SDM z(Teuchos::View, out, ncol, ncol, pce_sz);
304  ordinal_type ret =
305  z.multiply(Teuchos::NO_TRANS, Teuchos::TRANS, 1.0, zbar, Qp, 0.0);
306  TEUCHOS_ASSERT(ret == 0);
307  }
308  else {
309  SDM zbar(Teuchos::View, const_cast<value_type*>(in), sz, sz, ncol);
310  SDM z(Teuchos::View, out, pce_sz, pce_sz, ncol);
311  ordinal_type ret =
312  z.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, Qp, zbar, 0.0);
313  TEUCHOS_ASSERT(ret == 0);
314  }
315 }
316 
317 template <typename ordinal_type, typename value_type>
318 void
321  ordinal_type ncol, bool transpose) const
322 {
323  if (transpose) {
324  SDM z(Teuchos::View, const_cast<value_type*>(in), ncol, ncol, pce_sz);
325  SDM zbar(Teuchos::View, out, ncol, ncol, sz);
326  ordinal_type ret =
327  zbar.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, z, Qp, 0.0);
328  TEUCHOS_ASSERT(ret == 0);
329  }
330  else {
331  SDM z(Teuchos::View, const_cast<value_type*>(in), pce_sz, pce_sz, ncol);
332  SDM zbar(Teuchos::View, out, sz, sz, ncol);
333  ordinal_type ret =
334  zbar.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, Qp, z, 0.0);
335  TEUCHOS_ASSERT(ret == 0);
336  }
337 }
338 
339 template <typename ordinal_type, typename value_type>
343 {
344  return reduced_quad;
345 }
346 
347 template <typename ordinal_type, typename value_type>
351 {
353  pce.basis();
354  ordinal_type dim = basis->dimension();
355  value_type tol = 1.0e-15;
356 
357  // Check if basis is a product basis
359  if (prod_basis == Teuchos::null)
360  return -2;
361 
362  // Build list of dimensions pce depends on by looping over each dimension,
363  // computing norm of pce with just that dimension -- note we don't include
364  // the constant term
365  Teuchos::Array<ordinal_type> dependent_dims;
366  tmp_pce.reset(basis);
367  for (ordinal_type i=0; i<dim; i++) {
368  ordinal_type p = prod_basis->getCoordinateBases()[i]->order();
369  tmp_pce.init(0.0);
370  for (ordinal_type j=1; j<=p; j++)
371  tmp_pce.term(i,j) = pce.term(i,j);
372  value_type nrm = tmp_pce.two_norm();
373  if (nrm > tol) dependent_dims.push_back(i);
374  }
375 
376  // If dependent_dims has length 1, pce a function of a single variable,
377  // which is an invariant subspace
378  if (dependent_dims.size() == 1)
379  return dependent_dims[0];
380 
381  // If dependent_dims has length 0, pce is constant
382  else if (dependent_dims.size() == 0)
383  return -1;
384 
385  // Otherwise pce depends on more than one variable
386  return -2;
387 }
KOKKOS_INLINE_FUNCTION PCE< Storage > sqrt(const PCE< Storage > &a)
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.
virtual value_type evaluateZero(ordinal_type i) const
Evaluate basis polynomial i at zero.
Generates three-term recurrence using the Lanczos procedure applied to a polynomial chaos expansion i...
Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > reduced_quad
Reduced quadrature object.
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
SerialBandDenseMatrixPrinter< OrdinalType, ScalarType > printMat(const SerialBandDenseMatrix< OrdinalType, ScalarType > &obj)
T & get(ParameterList &l, const std::string &name)
SDM Qp
Coefficients of transformed basis in original basis.
virtual void evaluateBases(const Teuchos::ArrayView< const value_type > &point, Teuchos::Array< value_type > &basis_vals) const
Evaluate basis polynomials at given point point.
int multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix< OrdinalType, ScalarType > &A, const SerialDenseMatrix< OrdinalType, ScalarType > &B, ScalarType beta)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual Teuchos::RCP< Stokhos::Sparse3Tensor< ordinal_type, value_type > > computeLinearTripleProductTensor() const
Compute linear triple product tensor where k = 0,1,..,d.
ordinal_type dimension() const
Return dimension of basis.
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
SDM Q
Values of transformed basis at quadrature points.
virtual Teuchos::RCP< Stokhos::Sparse3Tensor< ordinal_type, value_type > > computeTripleProductTensor() const
Compute triple product tensor.
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.
virtual ordinal_type size() const
Return total size of basis.
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)
Abstract base class for quadrature methods.
Teuchos::RCP< const Stokhos::OrthogPolyBasis< ordinal_type, value_type > > basis() const
Return basis.
Abstract base class for multivariate orthogonal polynomials generated from tensor products of univari...
void resize(size_type new_size, const value_type &x=value_type())
Multivariate orthogonal polynomial basis generated from a total-order complete-polynomial tensor prod...
virtual void print(std::ostream &os) const
Print basis to stream os.
Generate a basis from a given set of PCE expansions that is orthogonal with respect to the product me...
virtual Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > getReducedQuadrature() const
Get reduced quadrature object.
void push_back(const value_type &x)
virtual const std::string & getName() const
Return string name of basis.
virtual const Teuchos::Array< value_type > & norm_squared() const
Return array storing norm-squared of each basis polynomial.
int reshape(OrdinalType numRows, OrdinalType numCols)
size_type size() const
Teuchos::RCP< Stokhos::CompletePolynomialBasis< ordinal_type, value_type > > tensor_lanczos_basis
Product Lanczos basis.
ProductLanczosGramSchmidtPCEBasis(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.
#define TEUCHOS_ASSERT(assertion_test)
ordinal_type isInvariant(const Stokhos::OrthogPolyApprox< ordinal_type, value_type > &pce) const
Generates three-term recurrence using the Lanczos procedure applied to a polynomial chaos expansion i...
Encapsulate various orthogonalization (ie QR) methods.
reference term(ordinal_type dimension, ordinal_type order)
Get coefficient term for given dimension and order.