bool Albany::KLResponseFunction:: computeKL(const Stokhos::EpetraVectorOrthogPoly& sg_u, const int NumKL, Teuchos::Array<double>& evals, Teuchos::RCP<Epetra_MultiVector>& evecs) { Teuchos::RCP<const EpetraExt::BlockVector> X_ov = sg_u.getBlockVector(); //App_sg->get_sg_model()->import_solution( *(sg_u->getBlockVector()) ); //Teuchos::RCP<const EpetraExt::BlockVector> cX_ov = X_ov; // pceKL is object with member functions that explicitly call anasazi Stokhos::PCEAnasaziKL pceKL(X_ov, *(sg_u.basis()), NumKL); // Set parameters for anasazi Teuchos::ParameterList& anasazi_params = responseParams.sublist("Anasazi"); Teuchos::ParameterList default_params = pceKL.getDefaultParams(); anasazi_params.setParametersNotAlreadySet(default_params); // Self explanatory bool result = pceKL.computeKL(anasazi_params); // Retrieve evals/evectors into return argument slots... evals = pceKL.getEigenvalues(); evecs = pceKL.getEigenvectors(); return result; }
void Stokhos::KLReducedMatrixFreeOperator:: setup() { #ifdef HAVE_STOKHOS_ANASAZI #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::KLReducedMatrixFreeOperator -- Calculation/setup of KL opeator"); #endif mean = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>( block_ops->getCoeffPtr(0)); // Copy matrix coefficients into vectors for (int coeff=0; coeff<num_blocks; coeff++) { Teuchos::RCP<const Epetra_CrsMatrix> block_coeff = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix> (block_ops->getCoeffPtr(coeff)); int row = 0; for (int i=0; i<mean->NumMyRows(); i++) { int num_col; mean->NumMyRowEntries(i, num_col); for (int j=0; j<num_col; j++) (*block_vec_poly)[coeff][row++] = (*block_coeff)[i][j]; } } int myPID = sg_comm->MyPID(); // Compute KL expansion of solution sg_J_vec_poly Stokhos::PCEAnasaziKL pceKL(*block_vec_poly, num_KL); Teuchos::ParameterList anasazi_params = pceKL.getDefaultParams(); bool result = pceKL.computeKL(anasazi_params); if (!result && myPID == 0) std::cout << "KL Eigensolver did not converge!" << std::endl; Teuchos::RCP<Epetra_MultiVector> evecs = pceKL.getEigenvectors(); Teuchos::Array<double> evals = pceKL.getEigenvalues(); //num_KL_computed = evecs->NumVectors(); if (myPID == 0) std::cout << "num computed eigenvectors = " << evecs->NumVectors() << std::endl; double kl_tol = params->get("KL Tolerance", 1e-6); num_KL_computed = 0; while (num_KL_computed < evals.size() && std::sqrt(evals[num_KL_computed]/evals[0]) > kl_tol) num_KL_computed++; if (num_KL_computed == evals.size() && myPID == 0) std::cout << "Can't achieve KL tolerance " << kl_tol << ". Smallest eigenvalue / largest eigenvalue = " << std::sqrt(evals[num_KL_computed-1]/evals[0]) << std::endl; if (myPID == 0) std::cout << "num KL eigenvectors = " << num_KL_computed << std::endl; // Compute dot products of Jacobian blocks and KL eigenvectors dot_products.resize(num_KL_computed); for (int rv=0; rv < num_KL_computed; rv++) { dot_products[rv].resize(num_blocks-1); for (int coeff=1; coeff < num_blocks; coeff++) { double dot; (*block_vec_poly)[coeff].Dot(*((*evecs)(rv)), &dot); dot_products[rv][coeff-1] = dot; } } // Compute KL coefficients const Teuchos::Array<double>& norms = sg_basis->norm_squared(); sparse_kl_coeffs = Teuchos::rcp(new Stokhos::Sparse3Tensor<int,double>); for (Cijk_type::i_iterator i_it=Cijk->i_begin(); i_it!=Cijk->i_end(); ++i_it) { int i = epetraCijk->GRID(index(i_it)); sparse_kl_coeffs->sum_term(i, i, 0, norms[i]); } Cijk_type::k_iterator l_begin = ++(Cijk->k_begin()); Cijk_type::k_iterator l_end = Cijk->k_end(); for (Cijk_type::k_iterator l_it=l_begin; l_it!=l_end; ++l_it) { int l = index(l_it); for (Cijk_type::kj_iterator j_it = Cijk->j_begin(l_it); j_it != Cijk->j_end(l_it); ++j_it) { int j = epetraCijk->GCID(index(j_it)); for (Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it); i_it != Cijk->i_end(j_it); ++i_it) { int i = epetraCijk->GRID(index(i_it)); double c = value(i_it); for (int k=1; k<num_KL_computed+1; k++) { double dp = dot_products[k-1][l-1]; double v = dp*c; if (std::abs(v) > drop_tolerance) sparse_kl_coeffs->sum_term(i,j,k,v); } } } } sparse_kl_coeffs->fillComplete(); bool save_tensor = params->get("Save Sparse 3 Tensor To File", false); if (save_tensor) { static int idx = 0; std::string basename = params->get("Sparse 3 Tensor Base Filename", "sparse_KL_coeffs"); std::stringstream ss; ss << basename << "_" << idx++ << ".mm"; sparse3Tensor2MatrixMarket(*sparse_kl_coeffs, *(epetraCijk->getStochasticRowMap()), ss.str()); } // Transform eigenvectors back to matrices kl_blocks.resize(num_KL_computed); Teuchos::RCP<Epetra_BlockMap> kl_map = Teuchos::rcp(new Epetra_LocalMap(num_KL_computed+1, 0, sg_comm->TimeDomainComm())); kl_ops = Teuchos::rcp(new Stokhos::EpetraOperatorOrthogPoly( sg_basis, kl_map, domain_base_map, range_base_map, range_sg_map, sg_comm)); kl_ops->setCoeffPtr(0, mean); for (int rv=0; rv<num_KL_computed; rv++) { if (kl_blocks[rv] == Teuchos::null) kl_blocks[rv] = Teuchos::rcp(new Epetra_CrsMatrix(*mean)); int row = 0; for (int i=0; i<mean->NumMyRows(); i++) { int num_col; mean->NumMyRowEntries(i, num_col); for (int j=0; j<num_col; j++) (*kl_blocks[rv])[i][j] = (*evecs)[rv][row++]; } kl_ops->setCoeffPtr(rv+1, kl_blocks[rv]); } Teuchos::RCP<Stokhos::EpetraSparse3Tensor> reducedEpetraCijk = Teuchos::rcp(new Stokhos::EpetraSparse3Tensor( sg_basis, sparse_kl_coeffs, sg_comm, epetraCijk->getStochasticRowMap(), sparse_kl_coeffs, 0, -1)); reducedEpetraCijk->transformToLocal(); // Create matrix-free op kl_mat_free_op = Teuchos::rcp(new Stokhos::MatrixFreeOperator( sg_comm, sg_basis, reducedEpetraCijk, domain_base_map, range_base_map, domain_sg_map, range_sg_map, params)); kl_mat_free_op->setupOperator(kl_ops); // Check accuracy of KL expansion if (do_error_tests) { Teuchos::Array<double> point(sg_basis->dimension()); for (int i=0; i<sg_basis->dimension(); i++) point[i] = 0.5; Teuchos::Array<double> basis_vals(sg_basis->size()); sg_basis->evaluateBases(point, basis_vals); Epetra_Vector val(*block_vec_map); Epetra_Vector val_kl(*block_vec_map); block_vec_poly->evaluate(basis_vals, val); val_kl.Update(1.0, (*block_vec_poly)[0], 0.0); Teuchos::Array< Stokhos::OrthogPolyApprox<int,double> > rvs(num_KL_computed); Teuchos::Array<double> val_rvs(num_KL_computed); for (int rv=0; rv<num_KL_computed; rv++) { rvs[rv].reset(sg_basis); rvs[rv][0] = 0.0; for (int coeff=1; coeff<num_blocks; coeff++) rvs[rv][coeff] = dot_products[rv][coeff-1]; val_rvs[rv] = rvs[rv].evaluate(point, basis_vals); val_kl.Update(val_rvs[rv], *((*evecs)(rv)), 1.0); } double nrm; val.NormInf(&nrm); val.Update(-1.0, val_kl, 1.0); double diff; val.NormInf(&diff); if (myPID == 0) std::cout << "Infinity norm of random field difference = " << diff/nrm << std::endl; // Check accuracy of operator Epetra_Vector op_input(*domain_sg_map), op_result(*range_sg_map), op_kl_result(*range_sg_map); op_input.PutScalar(1.0); Stokhos::MatrixFreeOperator op(sg_comm, sg_basis, epetraCijk, domain_base_map, range_base_map, domain_sg_map, range_sg_map, params); op.setupOperator(block_ops); op.Apply(op_input, op_result); this->Apply(op_input, op_kl_result); op_result.NormInf(&nrm); op_result.Update(-1.0, op_kl_result, 1.0); op_result.NormInf(&diff); if (myPID == 0) std::cout << "Infinity norm of operator difference = " << diff/nrm << std::endl; } #else TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stokhos::KLReducedMatrixFreeOperator is available " << "only when configured with Anasazi support!") #endif }