Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_TensorProductPseudoSpectralOperator.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_TENSOR_PRODUCT_PSEUDO_SPECTRAL_OPERATOR_HPP
11 #define STOKHOS_TENSOR_PRODUCT_PSEUDO_SPECTRAL_OPERATOR_HPP
12 
14 #include "Stokhos_ProductBasis.hpp"
17 #include "Teuchos_BLAS.hpp"
18 
19 namespace Stokhos {
20 
25  template <typename ordinal_t,
26  typename value_t,
27  typename point_compare_type =
28  typename DefaultPointCompare<ordinal_t,value_t>::type>
30  public PseudoSpectralOperator<ordinal_t,value_t,point_compare_type> {
31  public:
32 
33  typedef ordinal_t ordinal_type;
34  typedef value_t value_type;
36  typedef typename base_type::point_type point_type;
39  typedef typename base_type::iterator iterator;
43 
45 
48  const ProductBasis<ordinal_type,value_type>& product_basis,
49  bool use_pst_ = false,
50  multiindex_type multiindex = multiindex_type(),
51  const point_compare_type& point_compare = point_compare_type()) :
52  use_pst(use_pst_),
53  coeff_sz(product_basis.size()),
54  dim(product_basis.dimension()),
55  points(point_compare),
56  reorder(false) {
57 
58  // Check if we need to reorder for PST
59  // This isn't a perfect test since it doesn't catch not tensor-product
60  // bases
62  if (use_pst) {
64  const tb_type *tb = dynamic_cast<const tb_type*>(&product_basis);
65  if (tb == NULL)
66  reorder = true;
67  }
68 
70 
71  // Make sure order of each 1-D basis is large enough for
72  // supplied set of coefficients
74  multiindex_type max_orders = product_basis.getMaxOrders();
75  for (ordinal_type i=0; i<dim; ++i) {
76  if (bases[i]->order() < max_orders[i])
77  bases[i] = bases[i]->cloneWithOrder(max_orders[i]);
78  }
79 
80  // Check for default quadrature order
81  if (multiindex.dimension() == 0)
82  multiindex = max_orders;
83 
84  // Compute quad points, weights, values
88  multiindex_type n(dim);
89  if (use_pst) {
90  qp2pce_k.resize(dim);
91  pce2qp_k.resize(dim);
92  }
93  for (ordinal_type k=0; k<dim; k++) {
94  bases[k]->getQuadPoints(2*multiindex[k], gp[k], gw[k], gv[k]);
95  n[k] = gp[k].size()-1;
96 
97  // Generate quadrature operators for PST
98  if (use_pst) {
99  ordinal_type npc = bases[k]->size();
100  ordinal_type nqp = gp[k].size();
101  qp2pce_k[k].reshape(npc,nqp);
102  pce2qp_k[k].reshape(nqp,npc);
103  qp2pce_k[k].putScalar(1.0);
104  pce2qp_k[k].putScalar(1.0);
105  for (ordinal_type j=0; j<nqp; j++) {
106  for (ordinal_type i=0; i<npc; i++) {
107  qp2pce_k[k](i,j) *= gw[k][j]*gv[k][j][i] /
108  bases[k]->norm_squared(i);
109  pce2qp_k[k](j,i) *= gv[k][j][i];
110  }
111  }
112  }
113  }
114 
115  // Generate points and weights
117  typedef typename TensorProductIndexSet<ordinal_type>::iterator index_iterator;
118  index_iterator point_iterator = pointIndexSet.begin();
119  index_iterator point_end = pointIndexSet.end();
120  point_type point(dim);
121  while (point_iterator != point_end) {
122  value_type w = 1.0;
123  for (ordinal_type k=0; k<dim; k++) {
124  point[k] = gp[k][(*point_iterator)[k]];
125  w *= gw[k][(*point_iterator)[k]];
126  }
127  points[point] = std::make_pair(w,ordinal_type(0));
128  ++point_iterator;
129  }
130 
131  // Generate linear ordering of points
132  ordinal_type nqp = points.size();
133  point_map.resize(nqp);
134  ordinal_type idx=0;
135  typename point_set_type::iterator di = points.begin();
136  typename point_set_type::iterator di_end = points.end();
137  while (di != di_end) {
138  di->second.second = idx;
139  point_map[idx] = di->first;
140  ++idx;
141  ++di;
142  }
143 
144  // Build permutation array for reordering if coefficients aren't
145  // lexographically ordered
146  if (use_pst && reorder) {
147  typedef std::map<multiindex_type,ordinal_type,lexo_type> reorder_type;
148  reorder_type reorder_map;
149  for (ordinal_type i=0; i<coeff_sz; ++i)
150  reorder_map[product_basis.term(i)] = i;
151  perm.resize(coeff_sz);
152  ordinal_type idx = 0;
153  for (typename reorder_type::iterator it = reorder_map.begin();
154  it != reorder_map.end(); ++it)
155  perm[idx++] = it->second;
156  TEUCHOS_ASSERT(idx == coeff_sz);
157  }
158 
159  // Generate quadrature operator for direct apply
160  // Always do this because we may not use PST in some situations
161  ordinal_type npc = product_basis.size();
162  qp2pce.reshape(npc,nqp);
163  pce2qp.reshape(nqp,npc);
164  qp2pce.putScalar(1.0);
165  pce2qp.putScalar(1.0);
166  for (point_iterator = pointIndexSet.begin();
167  point_iterator != point_end;
168  ++point_iterator) {
169  for (ordinal_type k=0; k<dim; k++)
170  point[k] = gp[k][(*point_iterator)[k]];
171  ordinal_type j = points[point].second;
172  for (ordinal_type i=0; i<npc; i++) {
173  for (ordinal_type k=0; k<dim; k++) {
174  ordinal_type l = (*point_iterator)[k];
175  ordinal_type m = product_basis.term(i)[k];
176  qp2pce(i,j) *= gw[k][l]*gv[k][l][m] / bases[k]->norm_squared(m);
177  pce2qp(j,i) *= gv[k][l][m];
178  }
179  }
180  }
181 
182  }
183 
186 
188  ordinal_type point_size() const { return points.size(); }
189 
191  ordinal_type coeff_size() const { return coeff_sz; }
192 
194  iterator begin() { return point_map.begin(); }
195 
197  iterator end() { return point_map.end(); }
198 
200  const_iterator begin() const { return point_map.begin(); }
201 
203  const_iterator end() const { return point_map.end(); }
204 
206  set_iterator set_begin() { return points.begin(); }
207 
209  set_iterator set_end() { return points.end(); }
210 
212  const_set_iterator set_begin() const { return points.begin(); }
213 
215  const_set_iterator set_end() const { return points.end(); }
216 
219  const_set_iterator it = points.find(point);
221  it == points.end(), std::logic_error, "Invalid term " << point);
222  return it->second.second;
223  }
224 
226  const point_type& point(ordinal_type n) const { return point_map[n]; }
227 
229 
236  virtual void transformQP2PCE(
237  const value_type& alpha,
240  const value_type& beta,
241  bool trans = false) const {
242  if (use_pst)
243  apply_pst(qp2pce_k, alpha, input, result, beta, trans, false, reorder);
244  else
245  apply_direct(qp2pce, alpha, input, result, beta, trans);
246  }
247 
249 
256  virtual void transformPCE2QP(
257  const value_type& alpha,
260  const value_type& beta,
261  bool trans = false) const {
262 
263  // Only use PST if it was requested and number of rows/columns match
264  // (since we may allow fewer rows in input than columns of pce2qp)
265  bool can_use_pst = use_pst;
266  if (trans)
267  can_use_pst = can_use_pst && (input.numCols() == pce2qp.numRows());
268  else
269  can_use_pst = can_use_pst && (input.numRows() == pce2qp.numRows());
270 
271  if (can_use_pst)
272  apply_pst(pce2qp_k, alpha, input, result, beta, trans, reorder, false);
273  else
274  apply_direct(pce2qp, alpha, input, result, beta, trans);
275  }
276 
277  protected:
278 
282  const value_type& alpha,
285  const value_type& beta,
286  bool trans) const {
287  if (trans) {
288  TEUCHOS_ASSERT(input.numCols() <= A.numCols());
289  TEUCHOS_ASSERT(result.numCols() == A.numRows());
290  TEUCHOS_ASSERT(result.numRows() == input.numRows());
292  A.numRows(), input.numCols(), alpha, input.values(),
293  input.stride(), A.values(), A.stride(), beta,
294  result.values(), result.stride());
295  }
296  else {
297  TEUCHOS_ASSERT(input.numRows() <= A.numCols());
298  TEUCHOS_ASSERT(result.numRows() == A.numRows());
299  TEUCHOS_ASSERT(result.numCols() == input.numCols());
301  input.numCols(), input.numRows(), alpha, A.values(),
302  A.stride(), input.values(), input.stride(), beta,
303  result.values(), result.stride());
304  }
305  }
306 
308 
334  void apply_pst(
336  const value_type& alpha,
339  const value_type& beta,
340  bool trans,
341  bool reorder_input,
342  bool reorder_result) const {
343 
344  ordinal_type n, m, p;
345  if (trans) {
346  TEUCHOS_ASSERT(input.numRows() == result.numRows());
347  n = input.numCols();
348  p = input.numRows();
349  m = result.numCols();
350  }
351  else {
352  TEUCHOS_ASSERT(input.numCols() == result.numCols());
353  n = input.numRows();
354  p = input.numCols();
355  m = result.numRows();
356  }
357  ordinal_type M = 1;
358  ordinal_type N = 1;
359  for (ordinal_type k=0; k<dim; ++k) {
360  M *= Ak[k].numRows();
361  N *= Ak[k].numCols();
362  }
363  TEUCHOS_ASSERT(n == N);
364  TEUCHOS_ASSERT(m == M);
365  ordinal_type sz = std::max(n,m);
366 
367  // Temporary buffers used in algorithm
368  Teuchos::Array<value_type> tmp1(sz*p), tmp2(sz*p);
369 
370  // Copy input to tmp1 (transpose if necessary)
371  if (trans) {
372  if (reorder_input) {
373  ordinal_type idx;
374  for (ordinal_type j=0; j<p; j++)
375  for (ordinal_type i=0; i<n; i++) {
376  idx = perm[i];
377  tmp1[i+j*n] = input(j,idx);
378  }
379  }
380  else {
381  for (ordinal_type j=0; j<p; j++)
382  for (ordinal_type i=0; i<n; i++)
383  tmp1[i+j*n] = input(j,i);
384  }
385  }
386  else {
387  if (reorder_input) {
388  ordinal_type idx;
389  for (ordinal_type j=0; j<p; j++)
390  for (ordinal_type i=0; i<n; i++) {
391  idx = perm[i];
392  tmp1[i+j*n] = input(idx,j);
393  }
394  }
395  else {
396  for (ordinal_type j=0; j<p; j++)
397  for (ordinal_type i=0; i<n; i++)
398  tmp1[i+j*n] = input(i,j);
399  }
400  }
401 
402  // Loop over each term in Kronecker product
403  for (ordinal_type k=0; k<dim; k++) {
404  ordinal_type mk = Ak[k].numRows();
405  ordinal_type nk = Ak[k].numCols();
406  n = n / nk;
407 
408  // x = reshape(x, n, n_k)
410  Teuchos::View, &tmp1[0], n, n, nk*p);
411 
412  // y = x'
414  Teuchos::View, &tmp2[0], nk, nk, n*p);
415  for (ordinal_type l=0; l<p; l++)
416  for (ordinal_type j=0; j<n; j++)
417  for (ordinal_type i=0; i<nk; i++)
418  y(i,j+l*n) = x(j,i+l*nk);
419 
420  // x = A_k*x
422  Teuchos::View, &tmp1[0], mk, mk, n*p);
423  ordinal_type ret =
424  z.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, Ak[k], y, 0.0);
425  TEUCHOS_ASSERT(ret == 0);
426 
427  n = n * mk;
428  }
429 
430  // Sum answer into result (transposing and/or reordering if necessary)
431  if (trans) {
432  if (reorder_result) {
433  ordinal_type idx;
434  for (ordinal_type j=0; j<p; j++)
435  for (ordinal_type i=0; i<m; i++) {
436  idx = perm[i];
437  result(j,idx) = beta*result(j,idx) + alpha*tmp1[i+j*m];
438  }
439  }
440  else {
441  for (ordinal_type j=0; j<p; j++)
442  for (ordinal_type i=0; i<m; i++)
443  result(j,i) = beta*result(j,i) + alpha*tmp1[i+j*m];
444  }
445  }
446  else {
447  if (reorder_result) {
448  ordinal_type idx;
449  for (ordinal_type j=0; j<p; j++)
450  for (ordinal_type i=0; i<m; i++) {
451  idx = perm[i];
452  result(idx,j) = beta*result(idx,j) + alpha*tmp1[i+j*m];
453  }
454  }
455  else {
456  for (ordinal_type j=0; j<p; j++)
457  for (ordinal_type i=0; i<m; i++)
458  result(i,j) = beta*result(i,j) + alpha*tmp1[i+j*m];
459  }
460  }
461  }
462 
463  protected:
464 
466  bool use_pst;
467 
470 
473 
476 
479 
481  bool reorder;
482 
485 
488 
491 
494 
497 
500 
501  };
502 
503 }
504 
505 #endif
ScalarType * values() const
std::map< point_type, std::pair< value_type, ordinal_type >, point_compare_type > point_set_type
const point_type & point(ordinal_type n) const
Get point for given index.
Teuchos::SerialDenseMatrix< ordinal_type, value_type > qp2pce
Matrix mapping points to coefficients.
Container storing a term in a generalized tensor product.
Teuchos::Array< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > qp2pce_k
Matrix mapping points to coefficients for each dimension for PST.
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)
An operator interface for building pseudo-spectral approximations.
set_iterator set_begin()
Iterator to begining of point set.
void GEMM(ETransp transa, ETransp transb, const OrdinalType &m, const OrdinalType &n, const OrdinalType &k, const alpha_type alpha, const A_type *A, const OrdinalType &lda, const B_type *B, const OrdinalType &ldb, const beta_type beta, ScalarType *C, const OrdinalType &ldc) const
const_iterator end() const
Iterator to end of point set.
Teuchos::BLAS< ordinal_type, value_type > blas
BLAS wrappers.
PseudoSpectralOperator< ordinal_type, value_type, point_compare_type > base_type
virtual const MultiIndex< ordinal_type > & term(ordinal_type i) const =0
Get orders of each coordinate polynomial given an index i.
int putScalar(const ScalarType value=Teuchos::ScalarTraits< ScalarType >::zero())
KOKKOS_INLINE_FUNCTION PCE< Storage > max(const typename PCE< Storage >::value_type &a, const PCE< Storage > &b)
TensorProductPseudoSpectralOperator(const ProductBasis< ordinal_type, value_type > &product_basis, bool use_pst_=false, multiindex_type multiindex=multiindex_type(), const point_compare_type &point_compare=point_compare_type())
Constructor.
Abstract base class for multivariate orthogonal polynomials generated from tensor products of univari...
void apply_direct(const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &A, const value_type &alpha, const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &result, const value_type &beta, bool trans) const
Apply transformation operator using direct method.
void resize(size_type new_size, const value_type &x=value_type())
const_iterator begin() const
Return iterator for first element in the set.
const_set_iterator set_begin() const
Iterator to begining of point set.
const_iterator begin() const
Iterator to begining of point set.
Teuchos::SerialDenseMatrix< ordinal_type, value_type > pce2qp
Matrix mapping coefficients to points.
iterator end()
virtual void transformQP2PCE(const value_type &alpha, const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &result, const value_type &beta, bool trans=false) const
Transform values at quadrature points to PCE coefficients.
virtual Teuchos::Array< Teuchos::RCP< const OneDOrthogPolyBasis< ordinal_type, value_type > > > getCoordinateBases() const =0
Return array of coordinate bases.
Multivariate orthogonal polynomial basis generated from a tensor product of univariate polynomials...
OrdinalType numCols() const
void apply_pst(const Teuchos::Array< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > &Ak, const value_type &alpha, const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &result, const value_type &beta, bool trans, bool reorder_input, bool reorder_result) const
Apply tranformation operator using PST method.
virtual void transformPCE2QP(const value_type &alpha, const Teuchos::SerialDenseMatrix< ordinal_type, value_type > &input, Teuchos::SerialDenseMatrix< ordinal_type, value_type > &result, const value_type &beta, bool trans=false) const
Transform PCE coefficients to quadrature values.
int reshape(OrdinalType numRows, OrdinalType numCols)
size_type size() const
A comparison functor implementing a strict weak ordering based lexographic ordering.
Iterator class for iterating over elements of the index set.
An operator for building pseudo-spectral coefficients using tensor-product quadrature.
#define TEUCHOS_ASSERT(assertion_test)
const_set_iterator set_end() const
Iterator to end of point set.
Teuchos::Array< Teuchos::SerialDenseMatrix< ordinal_type, value_type > > pce2qp_k
Matrix mapping coefficients to points for each dimension for PST.
const_iterator end() const
Return iterator for end of the index set.
iterator begin()
int n
ordinal_type index(const point_type &point) const
Get point index for given point.
Teuchos::Array< ordinal_type > perm
Permutation array when reordering for PST.
virtual ordinal_type size() const =0
Return total size of basis.
OrdinalType stride() const
virtual MultiIndex< ordinal_type > getMaxOrders() const =0
Return maximum order allowable for each coordinate basis.
OrdinalType numRows() const