void polyfit( double *x, double *y, int n, int degree, double *coeffs, double *workspace ) { int ncoeffs = degree + 1; double *u = workspace, *w = u + n*ncoeffs, *v = w + ncoeffs; double **iu = mat_index(u, n,ncoeffs), **iv = mat_index(v,ncoeffs,ncoeffs); Vandermonde_Build(x,n,ncoeffs,u); #ifdef DEBUG_POLYFIT printf("\nV:\n"); mat_print( u, n, ncoeffs); #endif svd( iu, n, ncoeffs, w, iv ); free(iu); free(iv); svd_threshold( POLYFIT_SINGULAR_THRESHOLD, w, ncoeffs ); #ifdef DEBUG_POLYFIT printf("\n---Got---\n"); printf("\nU:\n"); mat_print( u, n, ncoeffs); printf("\nS:\n"); mat_print( w, ncoeffs, 1); printf("\nV:\n"); mat_print( v, ncoeffs, ncoeffs); printf("\nU S V':\n"); mat_print( matmul_right_transpose_static( matmul_right_vec_as_diag_static( u, n, ncoeffs, w, ncoeffs), n, ncoeffs, v, ncoeffs, ncoeffs), n, ncoeffs); #endif polyfit_reuse( y, n, degree, coeffs, workspace ); }
Stokhos::ProductLanczosPCEBasis<ordinal_type, value_type>:: 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_) : name("Product Lanczos PCE Basis"), params(params_) { Teuchos::RCP<const Stokhos::OrthogPolyBasis<ordinal_type,value_type> > pce_basis = pce[0].basis(); ordinal_type pce_sz = pce_basis->size(); // Check if basis is a product basis Teuchos::RCP<const Stokhos::ProductBasis<ordinal_type,value_type> > prod_basis = Teuchos::rcp_dynamic_cast<const Stokhos::ProductBasis<ordinal_type,value_type> >(pce_basis); Teuchos::Array< Teuchos::RCP<const OneDOrthogPolyBasis<ordinal_type,value_type> > > coord_bases; if (prod_basis != Teuchos::null) coord_bases = prod_basis->getCoordinateBases(); // Build Lanczos basis for each pce bool project = params.get("Project", true); bool normalize = params.get("Normalize", true); bool limit_integration_order = params.get("Limit Integration Order", false); bool use_stieltjes = params.get("Use Old Stieltjes Method", false); Teuchos::Array< Teuchos::RCP<const Stokhos::OneDOrthogPolyBasis<int,double > > > coordinate_bases; Teuchos::Array<int> is_invariant(pce.size(),-2); for (ordinal_type i=0; i<pce.size(); i++) { // Check for pce's lying in invariant subspaces, which are pce's that // depend on only a single dimension. In this case use the corresponding // original coordinate basis. Convention is: -2 -- not invariant, -1 -- // constant, i >= 0 pce depends only on dimension i if (prod_basis != Teuchos::null) is_invariant[i] = isInvariant(pce[i]); if (is_invariant[i] >= 0) { coordinate_bases.push_back(coord_bases[is_invariant[i]]); } // Exclude constant pce's from the basis since they don't represent // stochastic dimensions else if (is_invariant[i] != -1) { if (use_stieltjes) { coordinate_bases.push_back( Teuchos::rcp( new Stokhos::StieltjesPCEBasis<ordinal_type,value_type>( p, Teuchos::rcp(&(pce[i]),false), quad, false, normalize, project, Cijk))); } else { if (project) coordinate_bases.push_back( Teuchos::rcp( new Stokhos::LanczosProjPCEBasis<ordinal_type,value_type>( p, Teuchos::rcp(&(pce[i]),false), Cijk, normalize, limit_integration_order))); else coordinate_bases.push_back( Teuchos::rcp( new Stokhos::LanczosPCEBasis<ordinal_type,value_type>( p, Teuchos::rcp(&(pce[i]),false), quad, normalize, limit_integration_order))); } } } ordinal_type d = coordinate_bases.size(); // Build tensor product basis tensor_lanczos_basis = Teuchos::rcp( new Stokhos::CompletePolynomialBasis<ordinal_type,value_type>( coordinate_bases, params.get("Cijk Drop Tolerance", 1.0e-15), params.get("Use Old Cijk Algorithm", false))); // Build reduced quadrature Teuchos::ParameterList sg_params; sg_params.sublist("Basis").set< Teuchos::RCP< const Stokhos::OrthogPolyBasis<ordinal_type,value_type> > >("Stochastic Galerkin Basis", tensor_lanczos_basis); sg_params.sublist("Quadrature") = params.sublist("Reduced Quadrature"); reduced_quad = Stokhos::QuadratureFactory<ordinal_type,value_type>::create(sg_params); // Build Psi matrix -- Psi_ij = Psi_i(x^j)*w_j/<Psi_i^2> const Teuchos::Array<value_type>& weights = quad->getQuadWeights(); const Teuchos::Array< Teuchos::Array<value_type> >& points = quad->getQuadPoints(); const Teuchos::Array< Teuchos::Array<value_type> >& basis_vals = quad->getBasisAtQuadPoints(); ordinal_type nqp = weights.size(); SDM Psi(pce_sz, nqp); for (ordinal_type i=0; i<pce_sz; i++) for (ordinal_type k=0; k<nqp; k++) Psi(i,k) = basis_vals[k][i]*weights[k]/pce_basis->norm_squared(i); // Build Phi matrix -- Phi_ij = Phi_i(y(x^j)) ordinal_type sz = tensor_lanczos_basis->size(); Teuchos::Array<value_type> red_basis_vals(sz); Teuchos::Array<value_type> pce_vals(d); Phi.shape(sz, nqp); for (int k=0; k<nqp; k++) { ordinal_type jdx = 0; for (int j=0; j<pce.size(); j++) { // Exclude constant pce's if (is_invariant[j] != -1) { // Use the identity mapping for invariant subspaces if (is_invariant[j] >= 0) pce_vals[jdx] = points[k][is_invariant[j]]; else pce_vals[jdx] = pce[j].evaluate(points[k], basis_vals[k]); jdx++; } } tensor_lanczos_basis->evaluateBases(pce_vals, red_basis_vals); for (int i=0; i<sz; i++) Phi(i,k) = red_basis_vals[i]; } bool verbose = params.get("Verbose", false); // Compute matrix A mapping reduced space to original A.shape(pce_sz, sz); ordinal_type ret = A.multiply(Teuchos::NO_TRANS, Teuchos::TRANS, 1.0, Psi, Phi, 0.0); TEUCHOS_ASSERT(ret == 0); //print_matlab(std::cout << "A = " << std::endl, A); // Compute pseudo-inverse of A mapping original space to reduced // A = U*S*V^T -> A^+ = V*S^+*U^T = (S^+*V^T)^T*U^T where // S^+ is a diagonal matrix comprised of the inverse of the diagonal of S // for each nonzero, and zero otherwise Teuchos::Array<value_type> sigma; SDM U, Vt; value_type rank_threshold = params.get("Rank Threshold", 1.0e-12); ordinal_type rank = svd_threshold(rank_threshold, A, sigma, U, Vt); Ainv.shape(sz, pce_sz); TEUCHOS_ASSERT(rank == Vt.numRows()); for (ordinal_type i=0; i<Vt.numRows(); i++) for (ordinal_type j=0; j<Vt.numCols(); j++) Vt(i,j) = Vt(i,j) / sigma[i]; ret = Ainv.multiply(Teuchos::TRANS, Teuchos::TRANS, 1.0, Vt, U, 0.0); TEUCHOS_ASSERT(ret == 0); //print_matlab(std::cout << "Ainv = " << std::endl, Ainv); if (verbose) { std::cout << "rank = " << rank << std::endl; std::cout << "diag(S) = ["; for (ordinal_type i=0; i<rank; i++) std::cout << sigma[i] << " "; std::cout << "]" << std::endl; // Check A = U*S*V^T SDM SVt(rank, Vt.numCols()); for (ordinal_type i=0; i<Vt.numRows(); i++) for (ordinal_type j=0; j<Vt.numCols(); j++) SVt(i,j) = Vt(i,j) * sigma[i] * sigma[i]; // since we divide by sigma // above SDM err_A(pce_sz,sz); err_A.assign(A); ret = err_A.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, -1.0, U, SVt, 1.0); TEUCHOS_ASSERT(ret == 0); std::cout << "||A - U*S*V^T||_infty = " << err_A.normInf() << std::endl; //print_matlab(std::cout << "A - U*S*V^T = " << std::endl, err_A); // Check Ainv*A == I SDM err(sz,sz); err.putScalar(0.0); for (ordinal_type i=0; i<sz; i++) err(i,i) = 1.0; ret = err.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, Ainv, A, -1.0); TEUCHOS_ASSERT(ret == 0); std::cout << "||Ainv*A - I||_infty = " << err.normInf() << std::endl; //print_matlab(std::cout << "Ainv*A-I = " << std::endl, err); // Check A*Ainv == I SDM err2(pce_sz,pce_sz); err2.putScalar(0.0); for (ordinal_type i=0; i<pce_sz; i++) err2(i,i) = 1.0; ret = err2.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, A, Ainv, -1.0); TEUCHOS_ASSERT(ret == 0); std::cout << "||A*Ainv - I||_infty = " << err2.normInf() << std::endl; //print_matlab(std::cout << "A*Ainv-I = " << std::endl, err2); } }