Teuchos::RCP< Stokhos::Sparse3Tensor<ordinal_type, value_type> > Stokhos::CompletePolynomialBasis<ordinal_type, value_type>:: computeTripleProductTensorOld(ordinal_type order) const { // Compute Cijk = < \Psi_i \Psi_j \Psi_k > Teuchos::RCP< Stokhos::Sparse3Tensor<ordinal_type, value_type> > Cijk = Teuchos::rcp(new Sparse3Tensor<ordinal_type, value_type>); // Create 1-D triple products Teuchos::Array< Teuchos::RCP<Dense3Tensor<ordinal_type,value_type> > > Cijk_1d(d); for (ordinal_type i=0; i<d; i++) Cijk_1d[i] = bases[i]->computeTripleProductTensor(); for (ordinal_type j=0; j<sz; j++) { for (ordinal_type i=0; i<sz; i++) { for (ordinal_type k=0; k<order; k++) { value_type c = value_type(1.0); for (ordinal_type l=0; l<d; l++) c *= (*Cijk_1d[l])(terms[i][l],terms[j][l],terms[k][l]); if (std::abs(c/norms[i]) > sparse_tol) Cijk->add_term(i,j,k,c); } } } Cijk->fillComplete(); return Cijk; }
Teuchos::RCP< Stokhos::Sparse3Tensor<ordinal_type, value_type> > Stokhos::CompletePolynomialBasis<ordinal_type, value_type>:: computeTripleProductTensorNew(ordinal_type order) const { // The algorithm for computing Cijk = < \Psi_i \Psi_j \Psi_k > here works // by factoring // < \Psi_i \Psi_j \Psi_k > = // < \psi^1_{i_1}\psi^1_{j_1}\psi^1_{k_1} >_1 x ... x // < \psi^d_{i_d}\psi^d_{j_d}\psi^d_{k_d} >_d // We compute the sparse triple product < \psi^l_i\psi^l_j\psi^l_k >_l // for each dimension l, and then compute all non-zero products of these // terms. The complexity arises from iterating through all possible // combinations, throwing out terms that aren't in the basis and are beyond // the k-order limit provided Teuchos::RCP< Stokhos::Sparse3Tensor<ordinal_type, value_type> > Cijk = Teuchos::rcp(new Sparse3Tensor<ordinal_type, value_type>); // Map the specified order limit to a limit on each dimension // Subtract 1 to get the term for the last order we want to include, // add up the orders for each term to get the total order, then add 1 MultiIndex<ordinal_type> term = this->term(order-1); ordinal_type k_lim = 0; for (ordinal_type i=0; i<d; i++) k_lim = k_lim + term[i]; k_lim++; // Create 1-D triple products Teuchos::Array< Teuchos::RCP<Sparse3Tensor<ordinal_type,value_type> > > Cijk_1d(d); for (ordinal_type i=0; i<d; i++) { if (k_lim <= basis_orders[i]+1) Cijk_1d[i] = bases[i]->computeSparseTripleProductTensor(k_lim); else Cijk_1d[i] = bases[i]->computeSparseTripleProductTensor(basis_orders[i]+1); } // Create i, j, k iterators for each dimension // Note: we have to supply an initializer in the arrays of iterators to // avoid checked-stl errors about singular iterators typedef Sparse3Tensor<ordinal_type,value_type> Cijk_type; typedef typename Cijk_type::k_iterator k_iterator; typedef typename Cijk_type::kj_iterator kj_iterator; typedef typename Cijk_type::kji_iterator kji_iterator; Teuchos::Array<k_iterator> k_iterators(d, Cijk_1d[0]->k_begin()); Teuchos::Array<kj_iterator > j_iterators(d, Cijk_1d[0]->j_begin(k_iterators[0])); Teuchos::Array<kji_iterator > i_iterators(d, Cijk_1d[0]->i_begin(j_iterators[0])); MultiIndex<ordinal_type> terms_i(d), terms_j(d), terms_k(d); ordinal_type sum_i = 0; ordinal_type sum_j = 0; ordinal_type sum_k = 0; for (ordinal_type dim=0; dim<d; dim++) { k_iterators[dim] = Cijk_1d[dim]->k_begin(); j_iterators[dim] = Cijk_1d[dim]->j_begin(k_iterators[dim]); i_iterators[dim] = Cijk_1d[dim]->i_begin(j_iterators[dim]); terms_i[dim] = Stokhos::index(i_iterators[dim]); terms_j[dim] = Stokhos::index(j_iterators[dim]); terms_k[dim] = Stokhos::index(k_iterators[dim]); sum_i += terms_i[dim]; sum_j += terms_j[dim]; sum_k += terms_k[dim]; } ordinal_type I = 0; ordinal_type J = 0; ordinal_type K = 0; bool inc_i = true; bool inc_j = true; bool inc_k = true; bool stop = false; ordinal_type cnt = 0; while (!stop) { // Add term if it is in the basis if (sum_i <= p && sum_j <= p && sum_k <= p) { if (inc_k) K = CPBUtils::compute_index(terms_k, terms, num_terms, p); if (K < order) { if (inc_i) I = CPBUtils::compute_index(terms_i, terms, num_terms, p); if (inc_j) J = CPBUtils::compute_index(terms_j, terms, num_terms, p); value_type c = value_type(1.0); for (ordinal_type dim=0; dim<d; dim++) c *= value(i_iterators[dim]); if (std::abs(c/norms[I]) > sparse_tol) Cijk->add_term(I,J,K,c); } } // Increment iterators to the next valid term ordinal_type cdim = 0; bool inc = true; inc_i = false; inc_j = false; inc_k = false; while (inc && cdim < d) { ordinal_type cur_dim = cdim; ++i_iterators[cdim]; inc_i = true; if (i_iterators[cdim] != Cijk_1d[cdim]->i_end(j_iterators[cdim])) { terms_i[cdim] = Stokhos::index(i_iterators[cdim]); sum_i = 0; for (int dim=0; dim<d; dim++) sum_i += terms_i[dim]; } if (i_iterators[cdim] == Cijk_1d[cdim]->i_end(j_iterators[cdim]) || sum_i > p) { ++j_iterators[cdim]; inc_j = true; if (j_iterators[cdim] != Cijk_1d[cdim]->j_end(k_iterators[cdim])) { terms_j[cdim] = Stokhos::index(j_iterators[cdim]); sum_j = 0; for (int dim=0; dim<d; dim++) sum_j += terms_j[dim]; } if (j_iterators[cdim] == Cijk_1d[cdim]->j_end(k_iterators[cdim]) || sum_j > p) { ++k_iterators[cdim]; inc_k = true; if (k_iterators[cdim] != Cijk_1d[cdim]->k_end()) { terms_k[cdim] = Stokhos::index(k_iterators[cdim]); sum_k = 0; for (int dim=0; dim<d; dim++) sum_k += terms_k[dim]; } if (k_iterators[cdim] == Cijk_1d[cdim]->k_end() || sum_k > p) { k_iterators[cdim] = Cijk_1d[cdim]->k_begin(); ++cdim; terms_k[cur_dim] = Stokhos::index(k_iterators[cur_dim]); sum_k = 0; for (int dim=0; dim<d; dim++) sum_k += terms_k[dim]; } else inc = false; j_iterators[cur_dim] = Cijk_1d[cur_dim]->j_begin(k_iterators[cur_dim]); terms_j[cur_dim] = Stokhos::index(j_iterators[cur_dim]); sum_j = 0; for (int dim=0; dim<d; dim++) sum_j += terms_j[dim]; } else inc = false; i_iterators[cur_dim] = Cijk_1d[cur_dim]->i_begin(j_iterators[cur_dim]); terms_i[cur_dim] = Stokhos::index(i_iterators[cur_dim]); sum_i = 0; for (int dim=0; dim<d; dim++) sum_i += terms_i[dim]; } else inc = false; if (sum_i > p || sum_j > p || sum_k > p) inc = true; } if (cdim == d) stop = true; cnt++; } Cijk->fillComplete(); return Cijk; }
TEUCHOS_UNIT_TEST( Stokhos_Sparse3Tensor, Sparsity ) { Teuchos::RCP< Stokhos::Sparse3Tensor<int, double> > Cijk_quad = Teuchos::rcp(new Stokhos::Sparse3Tensor<int,double>); // Create 1-D triple products Teuchos::Array< Teuchos::RCP<Stokhos::Dense3Tensor<int,double> > > Cijk_1d(setup.d); for (int i=0; i<setup.d; i++) Cijk_1d[i] = setup.bases[i]->computeTripleProductTensor(); for (int j=0; j<setup.sz; j++) { Stokhos::MultiIndex<int> terms_j = setup.basis->term(j); for (int i=0; i<setup.sz; i++) { Stokhos::MultiIndex<int> terms_i = setup.basis->term(i); for (int k=0; k<setup.sz; k++) { Stokhos::MultiIndex<int> terms_k = setup.basis->term(k); double c = 1.0; for (int l=0; l<setup.d; l++) c *= (*Cijk_1d[l])(terms_i[l],terms_j[l],terms_k[l]); if (std::abs(c/setup.basis->norm_squared(i)) > setup.sparse_tol) Cijk_quad->add_term(i,j,k,c); } } } Cijk_quad->fillComplete(); // Check number of nonzeros int nnz = setup.Cijk->num_entries(); int nnz_quad = Cijk_quad->num_entries(); success = (nnz == nnz_quad); if (!success) out << std::endl << "Check: nnz(C) = " << nnz << " == nnz(C_quad) = " << nnz_quad << ": Failed"; for (Cijk_type::k_iterator k_it=Cijk_quad->k_begin(); k_it!=Cijk_quad->k_end(); ++k_it) { int k = Stokhos::index(k_it); for (Cijk_type::kj_iterator j_it = Cijk_quad->j_begin(k_it); j_it != Cijk_quad->j_end(k_it); ++j_it) { int j = Stokhos::index(j_it); for (Cijk_type::kji_iterator i_it = Cijk_quad->i_begin(j_it); i_it != Cijk_quad->i_end(j_it); ++i_it) { int i = Stokhos::index(i_it); double c = setup.Cijk->getValue(i,j,k); double c2 = Stokhos::value(i_it); double tol = setup.atol + c2*setup.rtol; double err = std::abs(c-c2); bool s = err < tol; if (!s) { out << std::endl << "Check: rel_err( C(" << i << "," << j << "," << k << ") )" << " = " << "rel_err( " << c << ", " << c2 << " ) = " << err << " <= " << tol << " : "; if (s) out << "Passed."; else out << "Failed!"; out << std::endl; } success = success && s; } } } }