Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_ProductBasisUtils.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_PRODUCT_BASIS_UTILS_HPP
11 #define STOKHOS_PRODUCT_BASIS_UTILS_HPP
12 
13 #include "Teuchos_Array.hpp"
14 #include "Teuchos_RCP.hpp"
16 #include "Teuchos_TimeMonitor.hpp"
17 
18 #include "Stokhos_SDMUtils.hpp"
20 #include "Stokhos_GrowthRules.hpp"
21 
22 namespace Stokhos {
23 
27  template <typename ordinal_type>
29  // Use formula
30  // n!/(k!(n-k)!) = n(n-1)...(k+1) / ( (n-k)(n-k-1)...1 ) ( n-k terms )
31  // = n(n-1)...(n-k+1) / ( k(k-1)...1 ) ( k terms )
32  // which ever has fewer terms
33  if (k > n)
34  return 0;
35  ordinal_type num = 1;
36  ordinal_type den = 1;
37  ordinal_type l = std::min(n-k,k);
38  for (ordinal_type i=0; i<l; i++) {
39  num *= n-i;
40  den *= i+1;
41  }
42  return num / den;
43  }
44 
46  template <typename ordinal_t>
47  class MultiIndex {
48  public:
49 
50  typedef ordinal_t ordinal_type;
51  typedef ordinal_t element_type;
52 
55 
58  index(dim,v) {}
59 
62 
64  ordinal_type dimension() const { return index.size(); }
65 
67  ordinal_type size() const { return index.size(); }
68 
70  const ordinal_type& operator[] (ordinal_type i) const { return index[i]; }
71 
74 
76  const Teuchos::Array<element_type>& getTerm() const { return index; }
77 
80 
82  void init(ordinal_type v) {
83  for (ordinal_type i=0; i<dimension(); i++)
84  index[i] = v;
85  }
86 
89  index.resize(d,v);
90  }
91 
93  ordinal_type order() const {
94  ordinal_type my_order = 0;
95  for (ordinal_type i=0; i<dimension(); ++i) my_order += index[i];
96  return my_order;
97  }
98 
100  bool operator==(const MultiIndex& idx) const {
101  if (dimension() != idx.dimension())
102  return false;
103  for (ordinal_type i=0; i<dimension(); i++) {
104  if (index[i] != idx.index[i])
105  return false;
106  }
107  return true;
108  }
109 
111  bool operator!=(const MultiIndex& idx) const { return !(*this == idx); }
112 
114  bool termWiseLEQ(const MultiIndex& idx) const {
115  for (ordinal_type i=0; i<dimension(); i++) {
116  if (index[i] > idx.index[i])
117  return false;
118  }
119  return true;
120  }
121 
123  std::ostream& print(std::ostream& os) const {
124  os << "[ ";
125  for (ordinal_type i=0; i<dimension(); i++)
126  os << index[i] << " ";
127  os << "]";
128  return os;
129  }
130 
133  for (ordinal_type i=0; i<dimension(); i++)
134  index[i] = index[i] <= idx[i] ? index[i] : idx[i];
135  return *this;
136  }
137 
140  for (ordinal_type i=0; i<dimension(); i++)
141  index[i] = index[i] <= idx ? index[i] : idx;
142  return *this;
143  }
144 
147  for (ordinal_type i=0; i<dimension(); i++)
148  index[i] = index[i] >= idx[i] ? index[i] : idx[i];
149  return *this;
150  }
151 
154  for (ordinal_type i=0; i<dimension(); i++)
155  index[i] = index[i] >= idx ? index[i] : idx;
156  return *this;
157  }
158 
159  protected:
160 
163 
164  };
165 
166  template <typename ordinal_type>
167  std::ostream& operator << (std::ostream& os,
168  const MultiIndex<ordinal_type>& m) {
169  return m.print(os);
170  }
171 
173 
182  template <typename ordinal_t>
184  public:
185 
186  // Forward declaration of our iterator
187  class Iterator;
188 
189  typedef ordinal_t ordinal_type;
193 
195 
200  ordinal_type lower_,
201  ordinal_type upper_) :
202  dim(dim_), lower(lower_), upper(upper_) {}
203 
205 
210  ordinal_type upper_) :
211  dim(dim_), lower(0), upper(upper_) {}
212 
214  ordinal_type dimension() const { return dim; }
215 
218  return multiindex_type(dim, upper);
219  }
220 
223  multiindex_type index(dim);
224  index[0] = lower;
225  return Iterator(upper, index);
226  }
227 
229  const_iterator end() const {
230  multiindex_type index(dim);
231  index[dim-1] = upper+1;
232  return Iterator(upper, index);
233  }
234 
235  protected:
236 
239 
242 
245 
246  public:
247 
249  class Iterator : public std::iterator<std::input_iterator_tag,
250  multiindex_type> {
251  public:
252 
253  typedef std::iterator<std::input_iterator_tag,multiindex_type> base_type;
254  typedef typename base_type::iterator_category iterator_category;
256  typedef typename base_type::difference_type difference_type;
257  typedef typename base_type::reference reference;
258  typedef typename base_type::pointer pointer;
259 
262 
264 
268  Iterator(ordinal_type max_order_, const multiindex_type& index_) :
269  max_order(max_order_), index(index_), dim(index.dimension()),
270  orders(dim) {
271  orders[dim-1] = max_order;
272  for (ordinal_type i=dim-2; i>=0; --i)
273  orders[i] = orders[i+1] - index[i+1];
274  }
275 
277  bool operator==(const Iterator& it) const { return index == it.index; }
278 
280  bool operator!=(const Iterator& it) const { return index != it.index; }
281 
283  const_reference operator*() const { return index; }
284 
286  const_pointer operator->() const { return &index; }
287 
289 
299  ++index[0];
300  ordinal_type i=0;
301  while (i<dim-1 && index[i] > orders[i]) {
302  index[i] = 0;
303  ++i;
304  ++index[i];
305  }
306  for (ordinal_type ii=dim-2; ii>=0; --ii)
307  orders[ii] = orders[ii+1] - index[ii+1];
308 
309  return *this;
310  }
311 
314  Iterator tmp(*this);
315  ++(*this);
316  return tmp;
317  }
318 
319  protected:
320 
323 
326 
329 
332  };
333  };
334 
336 
345  template <typename ordinal_t>
347  public:
348 
349  // Forward declaration of our iterator
350  class Iterator;
351 
352  typedef ordinal_t ordinal_type;
356 
358 
363  const multiindex_type& lower_,
364  const multiindex_type& upper_) :
365  dim(lower_.dimension()),
366  upper_order(upper_order_),
367  lower(lower_),
368  upper(upper_) {}
369 
371 
376  const multiindex_type& upper_) :
377  dim(upper_.dimension()),
378  upper_order(upper_order_),
379  lower(dim,0),
380  upper(upper_) {}
381 
383  ordinal_type dimension() const { return dim; }
384 
386  multiindex_type max_orders() const { return upper; }
387 
390  return Iterator(upper_order, upper, lower);
391  }
392 
394  const_iterator end() const {
395  multiindex_type index(dim);
396  index[dim-1] = std::min(upper_order, upper[dim-1]) + 1;
397  return Iterator(upper_order, upper, index);
398  }
399 
400  protected:
401 
404 
407 
410 
413 
416 
417  public:
418 
420  class Iterator : public std::iterator<std::input_iterator_tag,
421  multiindex_type> {
422  public:
423 
424  typedef std::iterator<std::input_iterator_tag,multiindex_type> base_type;
425  typedef typename base_type::iterator_category iterator_category;
427  typedef typename base_type::difference_type difference_type;
428  typedef typename base_type::reference reference;
429  typedef typename base_type::pointer pointer;
430 
433 
435 
439  Iterator(ordinal_type max_order_,
440  const multiindex_type& component_max_order_,
441  const multiindex_type& index_) :
442  max_order(max_order_),
443  component_max_order(component_max_order_),
444  index(index_),
445  dim(index.dimension()),
446  orders(dim)
447  {
448  orders[dim-1] = max_order;
449  for (ordinal_type i=dim-2; i>=0; --i)
450  orders[i] = orders[i+1] - index[i+1];
451  }
452 
454  bool operator==(const Iterator& it) const { return index == it.index; }
455 
457  bool operator!=(const Iterator& it) const { return index != it.index; }
458 
460  const_reference operator*() const { return index; }
461 
463  const_pointer operator->() const { return &index; }
464 
466 
476  ++index[0];
477  ordinal_type i=0;
478  while (i<dim-1 && (index[i] > orders[i] || index[i] > component_max_order[i])) {
479  index[i] = 0;
480  ++i;
481  ++index[i];
482  }
483  for (ordinal_type ii=dim-2; ii>=0; --ii)
484  orders[ii] = orders[ii+1] - index[ii+1];
485 
486  return *this;
487  }
488 
491  Iterator tmp(*this);
492  ++(*this);
493  return tmp;
494  }
495 
496  protected:
497 
500 
503 
506 
509 
512  };
513  };
514 
516 
525  template <typename ordinal_t>
527  public:
528 
529  // Forward declaration of our iterator
530  class Iterator;
531 
532  typedef ordinal_t ordinal_type;
536 
538 
543  ordinal_type lower_,
544  ordinal_type upper_) :
545  dim(dim_), lower(dim_,lower_), upper(dim_,upper_) {}
546 
548 
553  ordinal_type upper_) :
554  dim(dim_), lower(dim_,ordinal_type(0)), upper(dim_,upper_) {}
555 
557 
562  const multiindex_type& upper_) :
563  dim(lower_.dimension()), lower(lower_), upper(upper_) {}
564 
566 
571  dim(upper_.dimension()), lower(dim,ordinal_type(0)), upper(upper_) {}
572 
574  ordinal_type dimension() const { return dim; }
575 
578  return upper;
579  }
580 
583  return Iterator(upper, lower);
584  }
585 
587  const_iterator end() const {
588  multiindex_type index(dim);
589  index[dim-1] = upper[dim-1]+1;
590  return Iterator(upper, index);
591  }
592 
593  protected:
594 
597 
600 
603 
604  public:
605 
607  class Iterator : public std::iterator<std::input_iterator_tag,
608  multiindex_type> {
609  public:
610 
611  typedef std::iterator<std::input_iterator_tag,multiindex_type> base_type;
612  typedef typename base_type::iterator_category iterator_category;
614  typedef typename base_type::difference_type difference_type;
615  typedef typename base_type::reference reference;
616  typedef typename base_type::pointer pointer;
617 
620 
622 
626  Iterator(const multiindex_type& upper_, const multiindex_type& index_) :
627  upper(upper_), index(index_), dim(index.dimension()) {}
628 
630  bool operator==(const Iterator& it) const { return index == it.index; }
631 
633  bool operator!=(const Iterator& it) const { return index != it.index; }
634 
636  const_reference operator*() const { return index; }
637 
639  const_pointer operator->() const { return &index; }
640 
642 
652  ++index[0];
653  ordinal_type i=0;
654  while (i<dim-1 && index[i] > upper[i]) {
655  index[i] = 0;
656  ++i;
657  ++index[i];
658  }
659  return *this;
660  }
661 
664  Iterator tmp(*this);
665  ++(*this);
666  return tmp;
667  }
668 
669  protected:
670 
673 
676 
679 
680  };
681  };
682 
684  template <typename ordinal_t, typename element_t>
686  public:
687 
688  typedef ordinal_t ordinal_type;
689  typedef element_t element_type;
690 
693 
696  const element_type& val = element_type(0)) :
697  term(dim,val) {}
698 
701 
703  ordinal_type dimension() const { return term.size(); }
704 
706  ordinal_type size() const { return term.size(); }
707 
709  const element_type& operator[] (ordinal_type i) const { return term[i]; }
710 
713 
715  const Teuchos::Array<element_type>& getTerm() const { return term; }
716 
719 
721  operator Teuchos::ArrayView<element_type>() { return term; }
722 
724  operator Teuchos::ArrayView<const element_type>() const { return term; }
725 
727  element_type order() const {
728  element_type my_order = 0;
729  for (ordinal_type i=0; i<dimension(); ++i) my_order += term[i];
730  return my_order;
731  }
732 
734  std::ostream& print(std::ostream& os) const {
735  os << "[ ";
736  for (ordinal_type i=0; i<dimension(); i++)
737  os << term[i] << " ";
738  os << "]";
739  return os;
740  }
741 
742  protected:
743 
746 
747  };
748 
749  template <typename ordinal_type, typename element_type>
750  std::ostream& operator << (
751  std::ostream& os,
753  return m.print(os);
754  }
755 
760  /*
761  * Objects of type \c term_type must implement \c dimension() and
762  * \c operator[] methods, as well as contain ordinal_type and element_type
763  * nested types.
764  */
765  template <typename term_type,
766  typename compare_type = std::less<typename term_type::element_type> >
768  public:
769 
770  typedef term_type product_element_type;
772  typedef typename term_type::element_type element_type;
773 
775  LexographicLess(const compare_type& cmp_ = compare_type()) : cmp(cmp_) {}
776 
778  bool operator()(const term_type& a, const term_type& b) const {
779  ordinal_type i=0;
780  while(i < a.dimension() && i < b.dimension() && equal(a[i],b[i])) i++;
781 
782  // if a is shorter than b and the first a.dimension() elements agree
783  // then a is always less than b
784  if (i == a.dimension()) return i != b.dimension();
785 
786  // if a is longer than b and the first b.dimension() elements agree
787  // then b is always less than a
788  if (i == b.dimension()) return false;
789 
790  // a and b different at element i, a is less than b if a[i] < b[i]
791  return cmp(a[i],b[i]);
792  }
793 
794  protected:
795 
797  compare_type cmp;
798 
800  bool equal(const element_type& a, const element_type& b) const {
801  return !(cmp(a,b) || cmp(b,a));
802  }
803 
804  };
805 
810  /*
811  * Objects of type \c term_type must implement \c dimension(), \c order, and
812  * \c operator[] methods, as well as contain ordinal_type and element_type
813  * nested types.
814  */
815  template <typename term_type,
816  typename compare_type = std::less<typename term_type::element_type> >
818  public:
819 
820  typedef term_type product_element_type;
822  typedef typename term_type::element_type element_type;
823 
825  TotalOrderLess(const compare_type& cmp_ = compare_type()) : cmp(cmp_) {}
826 
827  bool operator()(const term_type& a, const term_type& b) const {
828  element_type a_order = a.order();
829  element_type b_order = b.order();
830  ordinal_type i=0;
831  while (i < a.dimension() && i < b.dimension() && equal(a_order,b_order)) {
832  a_order -= a[i];
833  b_order -= b[i];
834  ++i;
835  }
836  return cmp(a_order,b_order);
837  }
838 
839  protected:
840 
842  compare_type cmp;
843 
845  bool equal(const element_type& a, const element_type& b) const {
846  return !(cmp(a,b) || cmp(b,a));
847  }
848 
849  };
850 
855  /*
856  * A Morton Z-ordering is based on thinking of terms of dimension d as
857  * coordinates in a d-dimensional space, and forming a linear ordering of
858  * the points in that space by interleaving the bits from each coordinate.
859  * As implemented, this ordering only works with integral types and
860  * directly uses <. The code was taken from here:
861  *
862  * http://en.wikipedia.org/wiki/Z-order_curve
863  *
864  * With the idea behind it published here:
865  *
866  * Chan, T. (2002), "Closest-point problems simplified on the RAM",
867  * ACM-SIAM Symposium on Discrete Algorithms.
868  */
869  template <typename term_type>
870  class MortonZLess {
871  public:
872 
873  typedef term_type product_element_type;
875  typedef typename term_type::element_type element_type;
876 
879 
880  bool operator()(const term_type& a, const term_type& b) const {
881  ordinal_type d = a.dimension();
883  //ordinal_type k = ordinal_type(0); // causes shadowing warning
884  element_type x = element_type(0);
885  for (ordinal_type k=0; k<d; ++k) {
886  element_type y = a[k] ^ b[k];
887  if ( (x < y) && (x < (x^y)) ) {
888  j = k;
889  x = y;
890  }
891  }
892  return a[j] < b[j];
893  }
894 
895  };
896 
898 
902  template <typename value_type>
904  public:
905 
907  FloatingPointLess(const value_type& tol_ = 1.0e-12) : tol(tol_) {}
908 
911 
913  bool operator() (const value_type& a, const value_type& b) const {
914  return a < b - tol;
915  }
916 
917  protected:
918 
921 
922  };
923 
925  template <typename ordinal_type>
929 
930  TensorProductPredicate(const coeff_type& orders_) : orders(orders_) {}
931 
932  bool operator() (const coeff_type& term) const {
933  return term.termWiseLEQ(orders);
934  }
935 
936  };
937 
939  template <typename ordinal_type>
944 
945  TotalOrderPredicate(ordinal_type max_order_, const coeff_type& orders_)
946  : max_order(max_order_), orders(orders_) {}
947 
948  bool operator() (const coeff_type& term) const {
949  return term.termWiseLEQ(orders) && term.order() <= max_order;
950  }
951 
952  };
953 
954  // Compute global index from a total-order-sorted multi-index
955  /*
956  * The strategy is based on the fact we can compute the number of terms
957  * of a total order expansion for any given order and dimension. Thus
958  * starting from the last dimension of the multi-index:
959  * -- compute the order p of the multi-index from the current dimension
960  * dim-d to the last
961  * -- compute the number of terms in an order p-1 expansion of dimension
962  * d
963  * -- add this number of terms to the global index
964  * The logic here is independent of the values of the multi-index and
965  * requires exactly 8*d + (3/2)*d*(d+1) integer operations and comparisons
966  */
967  template <typename ordinal_type>
970  ordinal_type dim = index.dimension();
971  ordinal_type idx = ordinal_type(0);
972  ordinal_type p = ordinal_type(0);
973  ordinal_type den = ordinal_type(1);
974  for (ordinal_type d=1; d<=dim; ++d) {
975  p += index[dim-d];
976 
977  // offset = n_choose_k(p-1+d,d) = (p-1+d)! / ( (p-1)!*d! ) =
978  // ( p*(p+1)*...*(p+d-1) )/( 1*2*...*d )
979  den *= d;
980  ordinal_type num = 1;
981  for (ordinal_type i=p; i<p+d; ++i)
982  num *= i;
983 
984  idx += num / den;
985  }
986  return idx;
987  }
988 
989  // Compute global index from a lexicographic-sorted multi-index
990  /*
991  * For a given dimension d, let p be the sum of the orders for dimensions
992  * <= d. Then the number of terms that agree with the first d entries
993  * is (max_order-p+dim-d)!/(max_order-p)!*(dim-d)! where max_order is
994  * the maximum order of the multi-index and dim is the dimension. Thus
995  * we loop over each dimension d and compute the number of terms that come
996  * before that term that agree with the first d dimensions.
997  */
998  template <typename ordinal_type>
1001  ordinal_type max_order) {
1002  ordinal_type dim = index.dimension();
1003  ordinal_type idx = ordinal_type(0);
1004  for (ordinal_type d=1; d<=dim; ++d) {
1005  ordinal_type p = index[d-1];
1006 
1007  ordinal_type offset = ordinal_type(0);
1008  for (ordinal_type pp=0; pp<p; ++pp)
1009  offset += Stokhos::n_choose_k(max_order-pp+dim-d,dim-d);
1010 
1011  idx += offset;
1012  max_order -= p;
1013  }
1014  return idx;
1015  }
1016 
1026  public:
1027 
1031  template <typename index_set_type,
1032  typename growth_rule_type,
1033  typename basis_set_type,
1034  typename basis_map_type>
1035  static void
1036  buildProductBasis(const index_set_type& index_set,
1037  const growth_rule_type& growth_rule,
1038  basis_set_type& basis_set,
1039  basis_map_type& basis_map) {
1040 
1041  typedef typename index_set_type::ordinal_type ordinal_type;
1042  typedef typename index_set_type::iterator index_iterator_type;
1043  typedef typename basis_set_type::iterator basis_iterator_type;
1044  typedef typename basis_set_type::key_type coeff_type;
1045 
1046  ordinal_type dim = index_set.dimension();
1047 
1048  // Iterator over elements of index set
1049  index_iterator_type index_iterator = index_set.begin();
1050  index_iterator_type index_iterator_end = index_set.end();
1051  for (; index_iterator != index_iterator_end; ++index_iterator) {
1052 
1053  // Generate product coefficient
1054  coeff_type coeff(dim);
1055  for (ordinal_type i=0; i<dim; i++)
1056  coeff[i] = growth_rule[i]((*index_iterator)[i]);
1057 
1058  // Insert coefficient into set
1059  basis_set[coeff] = ordinal_type(0);
1060  }
1061 
1062  // Generate linear ordering of basis_set elements
1063  basis_map.resize(basis_set.size());
1064  ordinal_type idx = 0;
1065  basis_iterator_type basis_iterator = basis_set.begin();
1066  basis_iterator_type basis_iterator_end = basis_set.end();
1067  for (; basis_iterator != basis_iterator_end; ++basis_iterator) {
1068  basis_iterator->second = idx;
1069  basis_map[idx] = basis_iterator->first;
1070  ++idx;
1071  }
1072  }
1073 
1078  template <typename index_set_type,
1079  typename basis_set_type,
1080  typename basis_map_type>
1081  static void
1082  buildProductBasis(const index_set_type& index_set,
1083  basis_set_type& basis_set,
1084  basis_map_type& basis_map) {
1085  typedef typename index_set_type::ordinal_type ordinal_type;
1086  ordinal_type dim = index_set.dimension();
1088  buildProductBasis(index_set, growth_rule, basis_set, basis_map);
1089  }
1090 
1091  template <typename ordinal_type,
1092  typename value_type,
1093  typename basis_set_type,
1094  typename basis_map_type,
1095  typename coeff_predicate_type,
1096  typename k_coeff_predicate_type>
1100  const basis_set_type& basis_set,
1101  const basis_map_type& basis_map,
1102  const coeff_predicate_type& coeff_pred,
1103  const k_coeff_predicate_type& k_coeff_pred,
1104  const value_type sparse_tol = 1.0e-12)
1105  {
1106 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
1107  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Triple-Product Tensor Time");
1108 #endif
1109  typedef typename basis_map_type::value_type coeff_type;
1110  ordinal_type d = bases.size();
1111 
1112  // The algorithm for computing Cijk = < \Psi_i \Psi_j \Psi_k > here
1113  // works by factoring
1114  // < \Psi_i \Psi_j \Psi_k > =
1115  // < \psi^1_{i_1}\psi^1_{j_1}\psi^1_{k_1} >_1 x ... x
1116  // < \psi^d_{i_d}\psi^d_{j_d}\psi^d_{k_d} >_d
1117  // We compute the sparse triple product < \psi^l_i\psi^l_j\psi^l_k >_l
1118  // for each dimension l, and then compute all non-zero products of these
1119  // terms. The complexity arises from iterating through all possible
1120  // combinations, throwing out terms that aren't in the basis and are
1121  // beyond the k-order limit provided
1124 
1125  // Create 1-D triple products
1127  for (ordinal_type i=0; i<d; i++) {
1128  Cijk_1d[i] =
1129  bases[i]->computeSparseTripleProductTensor(bases[i]->order()+1);
1130  }
1131 
1132  // Create i, j, k iterators for each dimension
1133  // Note: we have to supply an initializer in the arrays of iterators
1134  // to avoid checked-stl errors about singular iterators
1136  typedef typename Cijk_type::k_iterator k_iterator;
1137  typedef typename Cijk_type::kj_iterator kj_iterator;
1138  typedef typename Cijk_type::kji_iterator kji_iterator;
1139  Teuchos::Array<k_iterator> k_iterators(d, Cijk_1d[0]->k_begin());
1140  Teuchos::Array<kj_iterator > j_iterators(d, Cijk_1d[0]->j_begin(k_iterators[0]));
1141  Teuchos::Array<kji_iterator > i_iterators(d, Cijk_1d[0]->i_begin(j_iterators[0]));
1142  coeff_type terms_i(d), terms_j(d), terms_k(d);
1143  for (ordinal_type dim=0; dim<d; dim++) {
1144  k_iterators[dim] = Cijk_1d[dim]->k_begin();
1145  j_iterators[dim] = Cijk_1d[dim]->j_begin(k_iterators[dim]);
1146  i_iterators[dim] = Cijk_1d[dim]->i_begin(j_iterators[dim]);
1147  terms_i[dim] = index(i_iterators[dim]);
1148  terms_j[dim] = index(j_iterators[dim]);
1149  terms_k[dim] = index(k_iterators[dim]);
1150  }
1151 
1152  ordinal_type I = 0;
1153  ordinal_type J = 0;
1154  ordinal_type K = 0;
1155  bool valid_i = coeff_pred(terms_i);
1156  bool valid_j = coeff_pred(terms_j);
1157  bool valid_k = k_coeff_pred(terms_k);
1158  bool inc_i = true;
1159  bool inc_j = true;
1160  bool inc_k = true;
1161  bool stop = false;
1162  ordinal_type cnt = 0;
1163  while (!stop) {
1164 
1165  // Add term if it is in the basis
1166  if (valid_i && valid_j && valid_k) {
1167  if (inc_k) {
1168  typename basis_set_type::const_iterator k =
1169  basis_set.find(terms_k);
1170  K = k->second;
1171  }
1172  if (inc_i) {
1173  typename basis_set_type::const_iterator i =
1174  basis_set.find(terms_i);
1175  I = i->second;
1176  }
1177  if (inc_j) {
1178  typename basis_set_type::const_iterator j =
1179  basis_set.find(terms_j);
1180  J = j->second;
1181  }
1182  value_type c = value_type(1.0);
1183  value_type nrm = value_type(1.0);
1184  for (ordinal_type dim=0; dim<d; dim++) {
1185  c *= value(i_iterators[dim]);
1186  nrm *= bases[dim]->norm_squared(terms_i[dim]);
1187  }
1188  if (std::abs(c/nrm) > sparse_tol)
1189  Cijk->add_term(I,J,K,c);
1190  }
1191 
1192  // Increment iterators to the next valid term
1193  ordinal_type cdim = 0;
1194  bool inc = true;
1195  inc_i = false;
1196  inc_j = false;
1197  inc_k = false;
1198  while (inc && cdim < d) {
1199  ordinal_type cur_dim = cdim;
1200  ++i_iterators[cdim];
1201  inc_i = true;
1202  if (i_iterators[cdim] != Cijk_1d[cdim]->i_end(j_iterators[cdim])) {
1203  terms_i[cdim] = index(i_iterators[cdim]);
1204  valid_i = coeff_pred(terms_i);
1205  }
1206  if (i_iterators[cdim] == Cijk_1d[cdim]->i_end(j_iterators[cdim]) ||
1207  !valid_i) {
1208  ++j_iterators[cdim];
1209  inc_j = true;
1210  if (j_iterators[cdim] != Cijk_1d[cdim]->j_end(k_iterators[cdim])) {
1211  terms_j[cdim] = index(j_iterators[cdim]);
1212  valid_j = coeff_pred(terms_j);
1213  }
1214  if (j_iterators[cdim] == Cijk_1d[cdim]->j_end(k_iterators[cdim]) ||
1215  !valid_j) {
1216  ++k_iterators[cdim];
1217  inc_k = true;
1218  if (k_iterators[cdim] != Cijk_1d[cdim]->k_end()) {
1219  terms_k[cdim] = index(k_iterators[cdim]);
1220  valid_k = k_coeff_pred(terms_k);
1221  }
1222  if (k_iterators[cdim] == Cijk_1d[cdim]->k_end() || !valid_k) {
1223  k_iterators[cdim] = Cijk_1d[cdim]->k_begin();
1224  ++cdim;
1225  terms_k[cur_dim] = index(k_iterators[cur_dim]);
1226  valid_k = k_coeff_pred(terms_k);
1227  }
1228  else
1229  inc = false;
1230  j_iterators[cur_dim] =
1231  Cijk_1d[cur_dim]->j_begin(k_iterators[cur_dim]);
1232  terms_j[cur_dim] = index(j_iterators[cur_dim]);
1233  valid_j = coeff_pred(terms_j);
1234  }
1235  else
1236  inc = false;
1237  i_iterators[cur_dim] =
1238  Cijk_1d[cur_dim]->i_begin(j_iterators[cur_dim]);
1239  terms_i[cur_dim] = index(i_iterators[cur_dim]);
1240  valid_i = coeff_pred(terms_i);
1241  }
1242  else
1243  inc = false;
1244 
1245  if (!valid_i || !valid_j || !valid_k)
1246  inc = true;
1247  }
1248 
1249  if (cdim == d)
1250  stop = true;
1251 
1252  cnt++;
1253  }
1254 
1255  Cijk->fillComplete();
1256 
1257  return Cijk;
1258  }
1259 
1260  template <typename ordinal_type>
1265 
1266  Cijk_1D_Iterator(ordinal_type p = 0, bool sym = false) :
1267  i_order(p), j_order(p), k_order(p),
1268  symmetric(sym),
1269  i(0), j(0), k(0) {}
1270 
1272  bool sym) :
1273  i_order(p_i), j_order(p_j), k_order(p_k),
1274  symmetric(sym),
1275  i(0), j(0), k(0) {}
1276 
1277  // Reset i,j,k to first non-zero
1278  void reset() { i = 0; j = 0; k = 0; }
1279 
1280  // Increment i,j,k to next non-zero with constraint i >= j >= k
1281  // Return false if no more non-zeros
1282  bool increment() {
1283  bool zero = true;
1284 
1285  // Increment terms to next non-zero
1286  while (zero) {
1287  bool more = increment_once();
1288  if (!more) return false;
1289  zero = is_zero();
1290  }
1291 
1292  return true;
1293  }
1294 
1295  // Increment i,j,k to next non-zero with constraint i >= j >= k
1296  // Return false if no more non-zeros
1297  bool increment(ordinal_type& delta_i,
1298  ordinal_type& delta_j,
1299  ordinal_type& delta_k) {
1300  bool zero = true;
1301  bool more = true;
1302  ordinal_type i0 = i;
1303  ordinal_type j0 = j;
1304  ordinal_type k0 = k;
1305 
1306  // Increment terms to next non-zero
1307  while (more && zero) {
1308  more = increment_once();
1309  if (more)
1310  zero = is_zero();
1311  }
1312 
1313  delta_i = i-i0;
1314  delta_j = j-j0;
1315  delta_k = k-k0;
1316 
1317  if (!more)
1318  return false;
1319 
1320  return true;
1321  }
1322 
1323  private:
1324 
1325  // Increment i,j,k to next term with constraint i >= j >= k
1326  // If no more terms, reset to first term and return false
1328  ++i;
1329  if (i > i_order) {
1330  ++j;
1331  if (j > j_order) {
1332  ++k;
1333  if (k > k_order) {
1334  i = 0;
1335  j = 0;
1336  k = 0;
1337  return false;
1338  }
1339  j = 0;
1340  }
1341  i = 0;
1342  }
1343  return true;
1344  }
1345 
1346  // Determine if term is zero
1347  bool is_zero() const {
1348  if (k+j < i || i+j < k || i+k < j) return true;
1349  if (symmetric && ((k+j) % 2) != (i % 2) ) return true;
1350  return false;
1351  }
1352  };
1353 
1354  template <typename ordinal_type,
1355  typename value_type,
1356  typename basis_set_type,
1357  typename basis_map_type,
1358  typename coeff_predicate_type,
1359  typename k_coeff_predicate_type>
1363  const basis_set_type& basis_set,
1364  const basis_map_type& basis_map,
1365  const coeff_predicate_type& coeff_pred,
1366  const k_coeff_predicate_type& k_coeff_pred,
1367  bool symmetric = false,
1368  const value_type sparse_tol = 1.0e-12) {
1369 #ifdef STOKHOS_TEUCHOS_TIME_MONITOR
1370  TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Triple-Product Tensor Time");
1371 #endif
1372  typedef typename basis_map_type::value_type coeff_type;
1373  ordinal_type d = bases.size();
1374 
1375  // The algorithm for computing Cijk = < \Psi_i \Psi_j \Psi_k > here
1376  // works by factoring
1377  // < \Psi_i \Psi_j \Psi_k > =
1378  // < \psi^1_{i_1}\psi^1_{j_1}\psi^1_{k_1} >_1 x ... x
1379  // < \psi^d_{i_d}\psi^d_{j_d}\psi^d_{k_d} >_d
1380  // We compute the sparse triple product < \psi^l_i\psi^l_j\psi^l_k >_l
1381  // for each dimension l, and then compute all non-zero products of these
1382  // terms. The complexity arises from iterating through all possible
1383  // combinations, throwing out terms that aren't in the basis and are
1384  // beyond the k-order limit provided
1387 
1388  // Create 1-D triple products
1390  for (ordinal_type i=0; i<d; i++) {
1391  Cijk_1d[i] =
1392  bases[i]->computeSparseTripleProductTensor(bases[i]->order()+1);
1393  }
1394 
1395  // Create i, j, k iterators for each dimension
1396  typedef Cijk_1D_Iterator<ordinal_type> Cijk_Iterator;
1397  Teuchos::Array< Cijk_1D_Iterator<ordinal_type> > Cijk_1d_iterators(d);
1398  coeff_type terms_i(d), terms_j(d), terms_k(d);
1399  for (ordinal_type dim=0; dim<d; dim++) {
1400  Cijk_1d_iterators[dim] = Cijk_Iterator(bases[dim]->order(), symmetric);
1401  terms_i[dim] = 0;
1402  terms_j[dim] = 0;
1403  terms_k[dim] = 0;
1404  }
1405 
1406  ordinal_type I = 0;
1407  ordinal_type J = 0;
1408  ordinal_type K = 0;
1409  bool valid_i = coeff_pred(terms_i);
1410  bool valid_j = coeff_pred(terms_j);
1411  bool valid_k = k_coeff_pred(terms_k);
1412  bool stop = !valid_i || !valid_j || !valid_k;
1413  ordinal_type cnt = 0;
1414  while (!stop) {
1415 
1416  typename basis_set_type::const_iterator k = basis_set.find(terms_k);
1417  typename basis_set_type::const_iterator i = basis_set.find(terms_i);
1418  typename basis_set_type::const_iterator j = basis_set.find(terms_j);
1419  K = k->second;
1420  I = i->second;
1421  J = j->second;
1422 
1423  value_type c = value_type(1.0);
1424  for (ordinal_type dim=0; dim<d; dim++) {
1425  c *= Cijk_1d[dim]->getValue(terms_i[dim], terms_j[dim], terms_k[dim]);
1426  }
1427  if (std::abs(c) > sparse_tol) {
1428  Cijk->add_term(I,J,K,c);
1429  // Cijk->add_term(I,K,J,c);
1430  // Cijk->add_term(J,I,K,c);
1431  // Cijk->add_term(J,K,I,c);
1432  // Cijk->add_term(K,I,J,c);
1433  // Cijk->add_term(K,J,I,c);
1434  }
1435 
1436  // Increment iterators to the next valid term
1437  // We keep i >= j >= k for each dimension
1438  ordinal_type cdim = 0;
1439  bool inc = true;
1440  while (inc && cdim < d) {
1441  bool more = Cijk_1d_iterators[cdim].increment();
1442  terms_i[cdim] = Cijk_1d_iterators[cdim].i;
1443  terms_j[cdim] = Cijk_1d_iterators[cdim].j;
1444  terms_k[cdim] = Cijk_1d_iterators[cdim].k;
1445  if (!more) {
1446  ++cdim;
1447  }
1448  else {
1449  valid_i = coeff_pred(terms_i);
1450  valid_j = coeff_pred(terms_j);
1451  valid_k = k_coeff_pred(terms_k);
1452 
1453  if (valid_i && valid_j && valid_k)
1454  inc = false;
1455  }
1456  }
1457 
1458  if (cdim == d)
1459  stop = true;
1460 
1461  cnt++;
1462  }
1463 
1464  Cijk->fillComplete();
1465 
1466  return Cijk;
1467  }
1468  };
1469 
1473  template <typename ordinal_type, typename value_type>
1475  public:
1476 
1481  /*
1482  * Returns expansion total order.
1483  * This version is for an isotropic expansion of total order \c p in
1484  * \c d dimensions.
1485  */
1486  static ordinal_type
1488  ordinal_type& sz,
1490  Teuchos::Array<ordinal_type>& num_terms);
1491 
1496  /*
1497  * Returns expansion total order.
1498  * This version allows for anisotropy in the maximum order in each
1499  * dimension.
1500  */
1501  static ordinal_type
1502  compute_terms(const Teuchos::Array<ordinal_type>& basis_orders,
1503  ordinal_type& sz,
1505  Teuchos::Array<ordinal_type>& num_terms);
1506 
1511  static ordinal_type
1513  const Teuchos::Array< MultiIndex<ordinal_type> >& terms,
1514  const Teuchos::Array<ordinal_type>& num_terms,
1515  ordinal_type max_p);
1516 
1517  };
1518 
1519 }
1520 
1521 template <typename ordinal_type, typename value_type>
1525  ordinal_type& sz,
1527  Teuchos::Array<ordinal_type>& num_terms)
1528 {
1529  Teuchos::Array<ordinal_type> basis_orders(d, p);
1530  return compute_terms(basis_orders, sz, terms, num_terms);
1531 }
1532 
1533 template <typename ordinal_type, typename value_type>
1537  ordinal_type& sz,
1539  Teuchos::Array<ordinal_type>& num_terms)
1540 {
1541  // The approach here for ordering the terms is inductive on the total
1542  // order p. We get the terms of total order p from the terms of total
1543  // order p-1 by incrementing the orders of the first dimension by 1.
1544  // We then increment the orders of the second dimension by 1 for all of the
1545  // terms whose first dimension order is 0. We then repeat for the third
1546  // dimension whose first and second dimension orders are 0, and so on.
1547  // How this is done is most easily illustrated by an example of dimension 3:
1548  //
1549  // Order terms cnt Order terms cnt
1550  // 0 0 0 0 4 4 0 0 15 5 1
1551  // 3 1 0
1552  // 1 1 0 0 3 2 1 3 0 1
1553  // 0 1 0 2 2 0
1554  // 0 0 1 2 1 1
1555  // 2 0 2
1556  // 2 2 0 0 6 3 1 1 3 0
1557  // 1 1 0 1 2 1
1558  // 1 0 1 1 1 2
1559  // 0 2 0 1 0 3
1560  // 0 1 1 0 4 0
1561  // 0 0 2 0 3 1
1562  // 0 2 2
1563  // 3 3 0 0 10 4 1 0 1 3
1564  // 2 1 0 0 0 4
1565  // 2 0 1
1566  // 1 2 0
1567  // 1 1 1
1568  // 1 0 2
1569  // 0 3 0
1570  // 0 2 1
1571  // 0 1 2
1572  // 0 0 3
1573 
1574  // Compute total order
1575  ordinal_type d = basis_orders.size();
1576  ordinal_type p = 0;
1577  for (ordinal_type i=0; i<d; i++) {
1578  if (basis_orders[i] > p)
1579  p = basis_orders[i];
1580  }
1581 
1582  // Temporary array of terms grouped in terms of same order
1584 
1585  // Store number of terms up to each order
1586  num_terms.resize(p+2, ordinal_type(0));
1587 
1588  // Set order 0
1589  terms_order[0].resize(1);
1590  terms_order[0][0].resize(d, ordinal_type(0));
1591  num_terms[0] = 1;
1592 
1593  // The array "cnt" stores the number of terms we need to increment for each
1594  // dimension.
1595  Teuchos::Array<ordinal_type> cnt(d), cnt_next(d);
1596  MultiIndex<ordinal_type> term(d);
1597  for (ordinal_type j=0; j<d; j++) {
1598  if (basis_orders[j] >= 1)
1599  cnt[j] = 1;
1600  else
1601  cnt[j] = 0;
1602  cnt_next[j] = 0;
1603  }
1604 
1605  sz = 1;
1606  // Loop over orders
1607  for (ordinal_type k=1; k<=p; k++) {
1608 
1609  num_terms[k] = num_terms[k-1];
1610 
1611  // Stores the index of the term we copying
1612  ordinal_type prev = 0;
1613 
1614  // Loop over dimensions
1615  for (ordinal_type j=0; j<d; j++) {
1616 
1617  // Increment orders of cnt[j] terms for dimension j
1618  for (ordinal_type i=0; i<cnt[j]; i++) {
1619  if (terms_order[k-1][prev+i][j] < basis_orders[j]) {
1620  term = terms_order[k-1][prev+i];
1621  ++term[j];
1622  terms_order[k].push_back(term);
1623  ++sz;
1624  num_terms[k]++;
1625  for (ordinal_type l=0; l<=j; l++)
1626  ++cnt_next[l];
1627  }
1628  }
1629 
1630  // Move forward to where all orders for dimension j are 0
1631  if (j < d-1)
1632  prev += cnt[j] - cnt[j+1];
1633 
1634  }
1635 
1636  // Update the number of terms we must increment for the new order
1637  for (ordinal_type j=0; j<d; j++) {
1638  cnt[j] = cnt_next[j];
1639  cnt_next[j] = 0;
1640  }
1641 
1642  }
1643 
1644  num_terms[p+1] = sz;
1645 
1646  // Copy into final terms array
1647  terms.resize(sz);
1648  ordinal_type i = 0;
1649  for (ordinal_type k=0; k<=p; k++) {
1650  ordinal_type num_k = terms_order[k].size();
1651  for (ordinal_type j=0; j<num_k; j++)
1652  terms[i++] = terms_order[k][j];
1653  }
1654 
1655  return p;
1656 }
1657 
1658 template <typename ordinal_type, typename value_type>
1663  const Teuchos::Array<ordinal_type>& num_terms,
1664  ordinal_type max_p)
1665 {
1666  // The approach here for computing the index is to find the order block
1667  // corresponding to this term by adding up the component orders. We then
1668  // do a linear search through the terms_order array for this order
1669 
1670  // First compute order of term
1671  ordinal_type d = term.dimension();
1672  ordinal_type ord = 0;
1673  for (ordinal_type i=0; i<d; i++)
1674  ord += term[i];
1675  TEUCHOS_TEST_FOR_EXCEPTION(ord < 0 || ord > max_p, std::logic_error,
1676  "Stokhos::CompletePolynomialBasis::compute_index(): " <<
1677  "Term has invalid order " << ord);
1678 
1679  // Now search through terms of that order to find a match
1680  ordinal_type k;
1681  if (ord == 0)
1682  k = 0;
1683  else
1684  k = num_terms[ord-1];
1685  ordinal_type k_max=num_terms[ord];
1686  bool found = false;
1687  while (k < k_max && !found) {
1688  bool found_term = true;
1689  for (ordinal_type j=0; j<d; j++) {
1690  found_term = found_term && (term[j] == terms[k][j]);
1691  if (!found_term)
1692  break;
1693  }
1694  found = found_term;
1695  ++k;
1696  }
1697  TEUCHOS_TEST_FOR_EXCEPTION(k >= k_max && !found, std::logic_error,
1698  "Stokhos::CompletePolynomialBasis::compute_index(): " <<
1699  "Could not find specified term.");
1700 
1701  return k-1;
1702 }
1703 
1704 #endif
static ordinal_type compute_index(const MultiIndex< ordinal_type > &term, const Teuchos::Array< MultiIndex< ordinal_type > > &terms, const Teuchos::Array< ordinal_type > &num_terms, ordinal_type max_p)
Compute basis index given the orders for each basis dimension.
std::iterator< std::input_iterator_tag, multiindex_type > base_type
multiindex_type upper
Component-wise upper bounds.
A functor for comparing floating-point numbers to some tolerance.
Iterator(ordinal_type max_order_, const multiindex_type &component_max_order_, const multiindex_type &index_)
Constructor.
multiindex_type lower
Component-wise lower bounds.
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
bool termWiseLEQ(const MultiIndex &idx) const
Compare term-wise less-than or equal-to.
const_pointer operator->() const
Dereference.
ordinal_type upper_order
Upper order of index set.
bool operator==(const Iterator &it) const
Compare equality of iterators.
Iterator(const multiindex_type &upper_, const multiindex_type &index_)
Constructor.
multiindex_type max_orders() const
Return maximum order for each dimension.
ordinal_type n_choose_k(const ordinal_type &n, const ordinal_type &k)
Compute bionomial coefficient (n ; k) = n!/( k! (n-k)! )
const_reference operator*() const
Dereference.
MultiIndex< ordinal_type > multiindex_type
Container storing a term in a generalized tensor product.
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
Teuchos::Array< ordinal_type > orders
Maximum orders for each term to determine how to increment.
TensorProductIndexSet(ordinal_type dim_, ordinal_type lower_, ordinal_type upper_)
Constructor.
Utilities for indexing a multi-variate complete polynomial basis.
term_type::ordinal_type ordinal_type
bool increment(ordinal_type &delta_i, ordinal_type &delta_j, ordinal_type &delta_k)
std::ostream & print(std::ostream &os) const
Print multiindex.
ordinal_type dimension() const
Return dimension.
std::iterator< std::input_iterator_tag, multiindex_type > base_type
const_iterator end() const
Return iterator for end of the index set.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
ordinal_type size() const
Size.
AnisotropicTotalOrderIndexSet(ordinal_type upper_order_, const multiindex_type &lower_, const multiindex_type &upper_)
Constructor.
ordinal_type dimension() const
Dimension.
MultiIndex & termWiseMin(const MultiIndex &idx)
Replace multiindex with min of this and other multiindex.
static Teuchos::RCP< Stokhos::Sparse3Tensor< ordinal_type, value_type > > computeTripleProductTensor(const Teuchos::Array< Teuchos::RCP< const OneDOrthogPolyBasis< ordinal_type, value_type > > > &bases, const basis_set_type &basis_set, const basis_map_type &basis_map, const coeff_predicate_type &coeff_pred, const k_coeff_predicate_type &k_coeff_pred, const value_type sparse_tol=1.0e-12)
term_type::element_type element_type
Iterator & operator++()
Prefix increment, i.e., ++iterator.
term_type::ordinal_type ordinal_type
Teuchos::Array< element_type > term
Array storing term elements.
bool operator!=(const Iterator &it) const
Compare inequality of iterators.
Teuchos::Array< ordinal_type > index
index terms
term_type::ordinal_type ordinal_type
TensorProductPredicate(const coeff_type &orders_)
static void buildProductBasis(const index_set_type &index_set, const growth_rule_type &growth_rule, basis_set_type &basis_set, basis_map_type &basis_map)
Generate a product basis from an index set.
Teuchos::Array< element_type > & getTerm()
Term access.
TotalOrderPredicate(ordinal_type max_order_, const coeff_type &orders_)
multiindex_type index
Current value of iterator.
const Teuchos::Array< element_type > & getTerm() const
Term access.
TotalOrderIndexSet(ordinal_type dim_, ordinal_type lower_, ordinal_type upper_)
Constructor.
Iterator & operator++()
Prefix increment, i.e., ++iterator.
ordinal_type dimension() const
Return dimension.
bool operator!=(const Iterator &it) const
Compare inequality of iterators.
A comparison functor implementing a strict weak ordering based total-order ordering, recursive on the dimension.
Iterator class for iterating over elements of the index set.
ordinal_type size() const
Return dimension.
Utilities for indexing a multi-variate complete polynomial basis.
KOKKOS_INLINE_FUNCTION PCE< Storage > min(const typename PCE< Storage >::value_type &a, const PCE< Storage > &b)
TensorProductElement(ordinal_type dim, const element_type &val=element_type(0))
Constructor.
Iterator & operator++()
Prefix increment, i.e., ++iterator.
ordinal_type upper
Upper order of index set.
multiindex_type max_orders() const
Return maximum order for each dimension.
A multidimensional index.
Iterator & operator++(int)
Postfix increment, i.e., iterator++.
Cijk_1D_Iterator(ordinal_type p_i, ordinal_type p_j, ordinal_type p_k, bool sym)
Teuchos::Array< ordinal_type > orders
Maximum orders for each term to determine how to increment.
const ordinal_type & operator[](ordinal_type i) const
Term access.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
const_reference operator*() const
Dereference.
Iterator(ordinal_type max_order_, const multiindex_type &index_)
Constructor.
std::ostream & operator<<(std::ostream &os, const ProductContainer< coeff_type > &vec)
multiindex_type index
Current value of iterator.
MultiIndex & termWiseMax(const ordinal_type idx)
Replace multiindex with max of this and given value.
TotalOrderLess(const compare_type &cmp_=compare_type())
Constructor.
bool operator()(const term_type &a, const term_type &b) const
bool operator()(const coeff_type &term) const
ordinal_type max_order
Maximum order of iterator.
Teuchos::Array< element_type > & getTerm()
Term access.
MultiIndex(ordinal_type dim, ordinal_type v=ordinal_type(0))
Constructor.
MultiIndex< ordinal_type > coeff_type
std::iterator< std::input_iterator_tag, multiindex_type > base_type
bool operator!=(const MultiIndex &idx) const
Compare equality.
compare_type cmp
Element comparison functor.
multiindex_type upper
Upper bound of iterator.
KOKKOS_INLINE_FUNCTION PCE< Storage > abs(const PCE< Storage > &a)
Iterator & operator++(int)
Postfix increment, i.e., iterator++.
void resize(ordinal_type d, ordinal_type v=ordinal_type(0))
Resize.
TensorProductIndexSet(ordinal_type dim_, ordinal_type upper_)
Constructor.
term_type::element_type element_type
const element_type & operator[](ordinal_type i) const
Term access.
void resize(size_type new_size, const value_type &x=value_type())
const_iterator begin() const
Return iterator for first element in the set.
MultiIndex & termWiseMax(const MultiIndex &idx)
Replace multiindex with max of this and other multiindex.
An anisotropic total order index set.
bool equal(const element_type &a, const element_type &b) const
Determine if two elements a and b are equal.
Predicate functor for building sparse triple products based on total order.
const_iterator end() const
Return iterator for end of the index set.
TensorProductIndexSet(const multiindex_type &upper_)
Constructor.
element_type order() const
Compute total order of tensor product element.
bool operator==(const Iterator &it) const
Compare equality of iterators.
Iterator class for iterating over elements of the index set.
multiindex_type upper
Upper bound of index set.
Stokhos::Sparse3Tensor< int, double > Cijk_type
bool operator==(const MultiIndex &idx) const
Compare equality.
multiindex_type index
Current value of iterator.
LexographicLess(const compare_type &cmp_=compare_type())
Constructor.
expr val()
void push_back(const value_type &x)
An isotropic total order index set.
Abstract base class for 1-D orthogonal polynomials.
std::ostream & print(std::ostream &os) const
Print multiindex.
void init(ordinal_type v)
Initialize.
FloatingPointLess(const value_type &tol_=1.0e-12)
Constructor.
A comparison functor implementing a strict weak ordering based Morton Z-ordering. ...
size_type size() const
const Teuchos::Array< element_type > & getTerm() const
Term access.
multiindex_type lower
Lower bound of index set.
A comparison functor implementing a strict weak ordering based lexographic ordering.
Iterator class for iterating over elements of the index set.
MultiIndex & termWiseMin(const ordinal_type idx)
Replace multiindex with min of this and given value.
static void buildProductBasis(const index_set_type &index_set, basis_set_type &basis_set, basis_map_type &basis_map)
Generate a product basis from an index set.
ordinal_type order() const
Compute total order of index.
Iterator & operator++(int)
Postfix increment, i.e., iterator++.
TensorProductIndexSet(const multiindex_type &lower_, const multiindex_type &upper_)
Constructor.
AnisotropicTotalOrderIndexSet(ordinal_type upper_order_, const multiindex_type &upper_)
Constructor.
multiindex_type max_orders() const
Return maximum order for each dimension.
ordinal_type dimension() const
Return dimension.
const_pointer operator->() const
Dereference.
const_iterator begin() const
Return iterator for first element in the set.
static Teuchos::RCP< Stokhos::Sparse3Tensor< ordinal_type, value_type > > computeTripleProductTensorNew(const Teuchos::Array< Teuchos::RCP< const OneDOrthogPolyBasis< ordinal_type, value_type > > > &bases, const basis_set_type &basis_set, const basis_map_type &basis_map, const coeff_predicate_type &coeff_pred, const k_coeff_predicate_type &k_coeff_pred, bool symmetric=false, const value_type sparse_tol=1.0e-12)
ordinal_type lower_order
Lower order of index set.
ordinal_type lower
Lower order of index set.
bool operator()(const term_type &a, const term_type &b) const
Determine if a is less than b.
ordinal_type dimension() const
Return dimension.
ordinal_type lexicographicMapping(const Stokhos::MultiIndex< ordinal_type > &index, ordinal_type max_order)
bool equal(const element_type &a, const element_type &b) const
Determine if two elements a and b are equal.
const_iterator end() const
Return iterator for end of the index set.
bool operator()(const coeff_type &term) const
bool operator()(const value_type &a, const value_type &b) const
Compare if a &lt; b.
Predicate functor for building sparse triple products.
bool operator!=(const Iterator &it) const
Compare inequality of iterators.
bool operator==(const Iterator &it) const
Compare equality of iterators.
bool operator()(const term_type &a, const term_type &b) const
const_iterator begin() const
Return iterator for first element in the set.
term_type::element_type element_type
TotalOrderIndexSet(ordinal_type dim_, ordinal_type upper_)
Constructor.
multiindex_type component_max_order
Maximum order for each component.
static ordinal_type compute_terms(ordinal_type p, ordinal_type d, ordinal_type &sz, Teuchos::Array< MultiIndex< ordinal_type > > &terms, Teuchos::Array< ordinal_type > &num_terms)
Compute the 2-D array of basis terms which maps a basis index into the orders for each basis dimensio...
MultiIndex< ordinal_type > multiindex_type
ordinal_type totalOrderMapping(const Stokhos::MultiIndex< ordinal_type > &index)
compare_type cmp
Element comparison functor.