Teuchos::RCP< Stokhos::Sparse3Tensor<ordinal_type, value_type> > Stokhos::TotalOrderBasis<ordinal_type, value_type, ordering_type>:: computeTripleProductTensor() const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Triple-Product Tensor Fill Time"); #endif TotalOrderPredicate<ordinal_type> predicate(p, max_orders); return ProductBasisUtils::computeTripleProductTensor( bases, basis_set, basis_map, predicate, predicate, sparse_tol); }
void Stokhos::ApproxSchurComplementPreconditioner:: divide_diagonal_block(int row_begin, int row_end, const EpetraExt::BlockMultiVector& Input, EpetraExt::BlockMultiVector& Result) const { for (int i=row_begin; i<row_end; i++) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR( "Stokhos: ASC Deterministic Preconditioner Time"); #endif mean_prec->ApplyInverse(*(Input.GetBlock(i)), *(Result.GetBlock(i))); } }
void Stokhos::StieltjesPCEBasis<ordinal_type, value_type>:: stieltjes(ordinal_type nstart, ordinal_type nfinish, const Teuchos::Array<value_type>& weights, const Teuchos::Array<value_type>& points, Teuchos::Array<value_type>& a, Teuchos::Array<value_type>& b, Teuchos::Array<value_type>& nrm, Teuchos::Array< Teuchos::Array<value_type> >& phi_vals) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::StieltjesPCEBasis -- Discretized Stieltjes Procedure"); #endif value_type val1, val2; ordinal_type start = nstart; if (nstart == 0) { if (project_integrals) integrateBasisSquaredProj(0, a, b, weights, points, phi_vals, val1, val2); else integrateBasisSquared(0, a, b, weights, points, phi_vals, val1, val2); nrm[0] = val1; a[0] = val2/val1; b[0] = value_type(1); start = 1; } for (ordinal_type i=start; i<nfinish; i++) { if (project_integrals) integrateBasisSquaredProj(i, a, b, weights, points, phi_vals, val1, val2); else integrateBasisSquared(i, a, b, weights, points, phi_vals, val1, val2); // std::cout << "i = " << i << " val1 = " << val1 << " val2 = " << val2 // << std::endl; TEUCHOS_TEST_FOR_EXCEPTION(val1 < 0.0, std::logic_error, "Stokhos::StieltjesPCEBasis::stieltjes(): " << " Polynomial " << i << " out of " << nfinish << " has norm " << val1 << "! Try increasing number of quadrature points"); nrm[i] = val1; a[i] = val2/val1; b[i] = nrm[i]/nrm[i-1]; // std::cout << "i = " << i << " alpha = " << a[i] << " beta = " << b[i] // << " nrm = " << nrm[i] << std::endl; } }
void Stokhos::FullyAssembledOperator:: setupOperator( const Teuchos::RCP<Stokhos::EpetraOperatorOrthogPoly >& ops) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SG Fully Assembled Operator Assembly"); #endif block_ops = ops; // Zero out matrix this->PutScalar(0.0); // Compute loop bounds Cijk_type::k_iterator k_begin = Cijk->k_begin(); Cijk_type::k_iterator k_end = Cijk->k_end(); if (!include_mean && index(k_begin) == 0) ++k_begin; if (only_use_linear) { int dim = sg_basis->dimension(); k_end = Cijk->find_k(dim+1); } // Assemble matrix const Teuchos::Array<double>& norms = sg_basis->norm_squared(); for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) { int k = index(k_it); Teuchos::RCP<Epetra_RowMatrix> block = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(block_ops->getCoeffPtr(k), true); for (Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_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); if (scale_op) c /= norms[i]; this->SumIntoGlobalBlock(c, *block, i, j); } } } this->FillComplete(*domain_sg_map, *range_sg_map); }
void Stokhos::StieltjesPCEBasis<ordinal_type, value_type>:: getQuadPoints(ordinal_type quad_order, Teuchos::Array<value_type>& quad_points, Teuchos::Array<value_type>& quad_weights, Teuchos::Array< Teuchos::Array<value_type> >& quad_values) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::StieltjesPCEBasis -- compute Gauss points"); #endif // Use underlying pce's quad points, weights, values if (use_pce_quad_points) { quad_points = pce_vals; quad_weights = pce_weights; quad_values = phi_vals; return; } // Call base class ordinal_type num_points = static_cast<ordinal_type>(std::ceil((quad_order+1)/2.0)); // We can't reliably generate quadrature points of order > 2*p //if (!project_integrals && quad_order > 2*this->p) if (quad_order > 2*this->p) quad_order = 2*this->p; Stokhos::RecurrenceBasis<ordinal_type,value_type>::getQuadPoints(quad_order, quad_points, quad_weights, quad_values); // Fill in the rest of the points with zero weight if (quad_weights.size() < num_points) { ordinal_type old_size = quad_weights.size(); quad_weights.resize(num_points); quad_points.resize(num_points); quad_values.resize(num_points); for (ordinal_type i=old_size; i<num_points; i++) { quad_weights[i] = value_type(0); quad_points[i] = quad_points[0]; quad_values[i].resize(this->p+1); this->evaluateBases(quad_points[i], quad_values[i]); } } }
bool NOX::Epetra::LinearSystemMPBD:: applyJacobianInverse(Teuchos::ParameterList ¶ms, const NOX::Epetra::Vector &input, NOX::Epetra::Vector &result) { TEUCHOS_FUNC_TIME_MONITOR("Total deterministic solve Time"); // Extract blocks EpetraExt::BlockVector input_block(View, *base_map, input.getEpetraVector()); EpetraExt::BlockVector result_block(View, *base_map, result.getEpetraVector()); result_block.PutScalar(0.0); Teuchos::ParameterList& block_solver_params = params.sublist("Deterministic Solver Parameters"); // Solve block linear systems bool final_status = true; bool status; for (int i=0; i<num_mp_blocks; i++) { NOX::Epetra::Vector nox_input(input_block.GetBlock(i), NOX::Epetra::Vector::CreateView); NOX::Epetra::Vector nox_result(result_block.GetBlock(i), NOX::Epetra::Vector::CreateView); block_solver->setJacobianOperatorForSolve(block_ops->getCoeffPtr(i)); if (precStrategy == STANDARD) block_solver->setPrecOperatorForSolve(precs[i]); else if (precStrategy == ON_THE_FLY) { block_solver->createPreconditioner(*(prec_x->GetBlock(i)), block_solver_params, false); } status = block_solver->applyJacobianInverse(block_solver_params, nox_input, nox_result); final_status = final_status && status; } return final_status; }
void Stokhos::MonoProjPCEBasis<ordinal_type, value_type>:: getQuadPoints(ordinal_type quad_order, Teuchos::Array<value_type>& quad_points, Teuchos::Array<value_type>& quad_weights, Teuchos::Array< Teuchos::Array<value_type> >& quad_values) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::MonoProjPCEBasis -- compute Gauss points"); #endif // Call base class ordinal_type num_points = static_cast<ordinal_type>(std::ceil((quad_order+1)/2.0)); // We can't always reliably generate quadrature points of order > 2*p // when using sparse grids for the underlying quadrature if (limit_integration_order && quad_order > 2*this->p) quad_order = 2*this->p; Stokhos::RecurrenceBasis<ordinal_type,value_type>::getQuadPoints(quad_order, quad_points, quad_weights, quad_values); // Fill in the rest of the points with zero weight if (quad_weights.size() < num_points) { ordinal_type old_size = quad_weights.size(); quad_weights.resize(num_points); quad_points.resize(num_points); quad_values.resize(num_points); for (ordinal_type i=old_size; i<num_points; i++) { quad_weights[i] = value_type(0); quad_points[i] = quad_points[0]; quad_values[i].resize(this->p+1); evaluateBases(quad_points[i], quad_values[i]); } } }
void Stokhos::PseudoSpectralOrthogPolyExpansion<ordinal_type, value_type, point_compare_type, node_type>:: divideEqual( Stokhos::OrthogPolyApprox<ordinal_type, value_type, node_type>& c, const Stokhos::OrthogPolyApprox<ordinal_type, value_type, node_type>& x) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::OrthogPolyExpansionBase::divideEqual(OPA)"); #endif if (x.size() == 1) { ordinal_type p = c.size(); value_type* cc = c.coeff(); const value_type* xc = x.coeff(); for (ordinal_type i=0; i<p; i++) cc[i] /= xc[0]; } else { if (use_quad_for_division) binary_op(div_quad_func(), c, c, x); else OrthogPolyExpansionBase<ordinal_type, value_type, node_type>::divideEqual(c, x); } }
void Stokhos::StieltjesPCEBasis<ordinal_type, value_type>:: getQuadPoints(ordinal_type quad_order, Teuchos::Array<value_type>& quad_points, Teuchos::Array<value_type>& quad_weights, Teuchos::Array< Teuchos::Array<value_type> >& quad_values) const { TEUCHOS_FUNC_TIME_MONITOR("Stokhos::StieltjesPCEBasis -- compute Gauss points"); // Use underlying pce's quad points, weights, values if (use_pce_quad_points) { quad_points = pce_vals; quad_weights = pce_weights; quad_values = phi_vals; return; } // Call base class ordinal_type num_points = static_cast<ordinal_type>(std::ceil((quad_order+1)/2.0)); if (quad_order > 2*this->p) quad_order = 2*this->p; Stokhos::RecurrenceBasis<ordinal_type,value_type>::getQuadPoints(quad_order, quad_points, quad_weights, quad_values); if (quad_weights.size() < num_points) { ordinal_type old_size = quad_weights.size(); quad_weights.resize(num_points); quad_points.resize(num_points); quad_values.resize(num_points); for (ordinal_type i=old_size; i<num_points; i++) { quad_values[i].resize(this->p+1); evaluateBases(quad_points[i], quad_values[i]); } } }
void Stokhos::PseudoSpectralOrthogPolyExpansion<ordinal_type, value_type, point_compare_type, node_type>:: nary_op(const FuncT& func, OrthogPolyApprox<ordinal_type, value_type, node_type>& c, const OrthogPolyApprox<ordinal_type, value_type, node_type>** na) { const int N = FuncT::N; bool is_constant = true; for (int i=0; i<N; i++) { if (na[i]->size() > 1) { is_constant = false; break; } } ordinal_type pc; if (is_constant) pc = 1; else pc = sz; if (c.size() != pc) c.resize(pc); if (pc == 1) { value_type val[N]; for (int i=0; i<N; i++) val[i] = (*na[i])[0]; c[0] = func(val); return; } if (N >= navals.size()) navals.resize(N+1); if (navals[N].size() != N) { navals[N].resize(N); for (int i=0; i<N; i++) navals[N][i].resize(nqp); } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::PSExp -- N(" << N << ")-ary Polynomial Evaluation"); #endif // Evaluate input for (int i=0; i<N; i++) { SDV sdv(Teuchos::View, const_cast<value_type*>(na[i]->coeff()), na[i]->size()); ps_op->transformPCE2QP(1.0, sdv, navals[N][i], 0.0, false); } } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::PSExp -- N(" << N << ")-ary Function Evaluation"); #endif // Evaluate function value_type val[N]; for (ordinal_type qp=0; qp<nqp; qp++) { for (int i=0; i<N; i++) val[i] = navals[N][i][qp]; fvals[qp] = func(val); } } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::PSExp -- N(" << N << ")-ary Polynomial Integration"); #endif // Integrate SDV c_sdv(Teuchos::View, c.coeff(), pc); ps_op->transformQP2PCE(1.0, fvals, c_sdv, 0.0, false); } }
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 }
int Stokhos::ApproxSchurComplementPreconditioner:: ApplyInverse(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Approximate Schur Complement Time"); #endif // We have to be careful if Input and Result are the same vector. // If this is the case, the only possible solution is to make a copy const Epetra_MultiVector *input = &Input; bool made_copy = false; if (Input.Values() == Result.Values()) { input = new Epetra_MultiVector(Input); made_copy = true; } // Allocate temporary storage int m = input->NumVectors(); if (rhs_block == Teuchos::null || rhs_block->NumVectors() != m) rhs_block = Teuchos::rcp(new EpetraExt::BlockMultiVector(*base_map, *sg_map, m)); if (tmp == Teuchos::null || tmp->NumVectors() != m*max_num_mat_vec) tmp = Teuchos::rcp(new Epetra_MultiVector(*base_map, m*max_num_mat_vec)); j_ptr.resize(m*max_num_mat_vec); mj_indices.resize(m*max_num_mat_vec); // Extract blocks EpetraExt::BlockMultiVector input_block(View, *base_map, *input); EpetraExt::BlockMultiVector result_block(View, *base_map, Result); result_block.PutScalar(0.0); // Set right-hand-side to input_block rhs_block->Update(1.0, input_block, 0.0); // At level l, linear system has the structure // [ A_{l-1} B_l ][ u_l^{l-1} ] = [ r_l^{l-1} ] // [ C_l D_l ][ u_l^l ] [ r_l^l ] for (int l=P; l>=1; l--) { // Compute D_l^{-1} r_l^l divide_diagonal_block(block_indices[l], block_indices[l+1], *rhs_block, result_block); // Compute r_l^{l-1} = r_l^{l-1} - B_l D_l^{-1} r_l^l multiply_block(upper_block_Cijk[l], -1.0, result_block, *rhs_block); } // Solve A_0 u_0 = r_0 divide_diagonal_block(0, 1, *rhs_block, result_block); for (int l=1; l<=P; l++) { // Compute r_l^l - C_l*u_l^{l-1} multiply_block(lower_block_Cijk[l], -1.0, result_block, *rhs_block); // Compute D_l^{-1} (r_l^l - C_l*u_l^{l-1}) divide_diagonal_block(block_indices[l], block_indices[l+1], *rhs_block, result_block); } if (made_copy) delete input; return 0; }
int main(int argc, char *argv[]) { int n = 32; // spatial discretization (per dimension) int num_KL = 2; // number of KL terms int p = 3; // polynomial order double mu = 0.1; // mean of exponential random field double s = 0.2; // std. dev. of exponential r.f. bool nonlinear_expansion = false; // nonlinear expansion of diffusion coeff // (e.g., log-normal) bool symmetric = false; // use symmetric formulation double g_mean_exp = 0.172988; // expected response mean double g_std_dev_exp = 0.0380007; // expected response std. dev. double g_tol = 1e-6; // tolerance on determining success // Initialize MPI #ifdef HAVE_MPI MPI_Init(&argc,&argv); #endif int MyPID; try { { TEUCHOS_FUNC_TIME_MONITOR("Total PCE Calculation Time"); // Create a communicator for Epetra objects Teuchos::RCP<const Epetra_Comm> globalComm; #ifdef HAVE_MPI globalComm = Teuchos::rcp(new Epetra_MpiComm(MPI_COMM_WORLD)); #else globalComm = Teuchos::rcp(new Epetra_SerialComm); #endif MyPID = globalComm->MyPID(); // Create Stochastic Galerkin basis and expansion Teuchos::Array< Teuchos::RCP<const Stokhos::OneDOrthogPolyBasis<int,double> > > bases(num_KL); for (int i=0; i<num_KL; i++) bases[i] = Teuchos::rcp(new Stokhos::LegendreBasis<int,double>(p,true)); Teuchos::RCP<const Stokhos::CompletePolynomialBasis<int,double> > basis = Teuchos::rcp(new Stokhos::CompletePolynomialBasis<int,double>(bases, 1e-12)); int sz = basis->size(); Teuchos::RCP<Stokhos::Sparse3Tensor<int,double> > Cijk; if (nonlinear_expansion) Cijk = basis->computeTripleProductTensor(sz); else Cijk = basis->computeTripleProductTensor(num_KL+1); Teuchos::RCP<Stokhos::OrthogPolyExpansion<int,double> > expansion = Teuchos::rcp(new Stokhos::AlgebraicOrthogPolyExpansion<int,double>(basis, Cijk)); if (MyPID == 0) std::cout << "Stochastic Galerkin expansion size = " << sz << std::endl; // Create stochastic parallel distribution int num_spatial_procs = -1; Teuchos::ParameterList parallelParams; parallelParams.set("Number of Spatial Processors", num_spatial_procs); // parallelParams.set("Rebalance Stochastic Graph", true); // Teuchos::ParameterList& isorropia_params = // parallelParams.sublist("Isorropia"); // isorropia_params.set("Balance objective", "nonzeros"); Teuchos::RCP<Stokhos::ParallelData> sg_parallel_data = Teuchos::rcp(new Stokhos::ParallelData(basis, Cijk, globalComm, parallelParams)); Teuchos::RCP<const EpetraExt::MultiComm> sg_comm = sg_parallel_data->getMultiComm(); Teuchos::RCP<const Epetra_Comm> app_comm = sg_parallel_data->getSpatialComm(); // Create application Teuchos::RCP<twoD_diffusion_ME> model = Teuchos::rcp(new twoD_diffusion_ME(app_comm, n, num_KL, mu, s, basis, nonlinear_expansion, symmetric)); // Setup stochastic Galerkin algorithmic parameters Teuchos::RCP<Teuchos::ParameterList> sgParams = Teuchos::rcp(new Teuchos::ParameterList); if (!nonlinear_expansion) { sgParams->set("Parameter Expansion Type", "Linear"); sgParams->set("Jacobian Expansion Type", "Linear"); } Teuchos::ParameterList precParams; precParams.set("default values", "SA"); precParams.set("ML output", 0); precParams.set("max levels",5); precParams.set("increasing or decreasing","increasing"); precParams.set("aggregation: type", "Uncoupled"); precParams.set("smoother: type","ML symmetric Gauss-Seidel"); precParams.set("smoother: sweeps",2); precParams.set("smoother: pre or post", "both"); precParams.set("coarse: max size", 200); //precParams.set("PDE equations",sz); #ifdef HAVE_ML_AMESOS precParams.set("coarse: type","Amesos-KLU"); #else precParams.set("coarse: type","Jacobi"); #endif // Create stochastic Galerkin model evaluator Teuchos::RCP<Stokhos::SGModelEvaluator_Interlaced> sg_model = Teuchos::rcp(new Stokhos::SGModelEvaluator_Interlaced( model, basis, Teuchos::null, expansion, sg_parallel_data, sgParams)); // Set up stochastic parameters Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_p_poly = sg_model->create_p_sg(0); for (int i=0; i<num_KL; i++) { sg_p_poly->term(i,0)[i] = 0.0; sg_p_poly->term(i,1)[i] = 1.0; } // Create vectors and operators Teuchos::RCP<const Epetra_Vector> sg_p = sg_p_poly->getBlockVector(); Teuchos::RCP<Epetra_Vector> sg_x = Teuchos::rcp(new Epetra_Vector(*(sg_model->get_x_map()))); sg_x->PutScalar(0.0); Teuchos::RCP<Epetra_Vector> sg_f = Teuchos::rcp(new Epetra_Vector(*(sg_model->get_f_map()))); Teuchos::RCP<Epetra_Vector> sg_dx = Teuchos::rcp(new Epetra_Vector(*(sg_model->get_x_map()))); Teuchos::RCP<Epetra_CrsMatrix> sg_J = Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(sg_model->create_W()); Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> sg_M = Teuchos::rcp(new ML_Epetra::MultiLevelPreconditioner(*sg_J, precParams, false)); // Setup InArgs and OutArgs EpetraExt::ModelEvaluator::InArgs sg_inArgs = sg_model->createInArgs(); EpetraExt::ModelEvaluator::OutArgs sg_outArgs = sg_model->createOutArgs(); sg_inArgs.set_p(1, sg_p); sg_inArgs.set_x(sg_x); sg_outArgs.set_f(sg_f); sg_outArgs.set_W(sg_J); // Evaluate model sg_model->evalModel(sg_inArgs, sg_outArgs); sg_M->ComputePreconditioner(); // Print initial residual norm double norm_f; sg_f->Norm2(&norm_f); if (MyPID == 0) std::cout << "\nInitial residual norm = " << norm_f << std::endl; // Setup AztecOO solver AztecOO aztec; if (symmetric) aztec.SetAztecOption(AZ_solver, AZ_cg); else aztec.SetAztecOption(AZ_solver, AZ_gmres); aztec.SetAztecOption(AZ_precond, AZ_none); aztec.SetAztecOption(AZ_kspace, 20); aztec.SetAztecOption(AZ_conv, AZ_r0); aztec.SetAztecOption(AZ_output, 1); aztec.SetUserOperator(sg_J.get()); aztec.SetPrecOperator(sg_M.get()); aztec.SetLHS(sg_dx.get()); aztec.SetRHS(sg_f.get()); // Solve linear system aztec.Iterate(1000, 1e-12); // Update x sg_x->Update(-1.0, *sg_dx, 1.0); // Save solution to file EpetraExt::VectorToMatrixMarketFile("stochastic_solution_interlaced.mm", *sg_x); // Save RHS to file EpetraExt::VectorToMatrixMarketFile("stochastic_RHS_interlaced.mm", *sg_f); // Save operator to file EpetraExt::RowMatrixToMatrixMarketFile("stochastic_operator_interlaced.mm", *sg_J); // Save mean and variance to file Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_x_poly = sg_model->create_x_sg(View, sg_x.get()); Epetra_Vector mean(*(model->get_x_map())); Epetra_Vector std_dev(*(model->get_x_map())); sg_x_poly->computeMean(mean); sg_x_poly->computeStandardDeviation(std_dev); EpetraExt::VectorToMatrixMarketFile("mean_gal_interlaced.mm", mean); EpetraExt::VectorToMatrixMarketFile("std_dev_gal_interlaced.mm", std_dev); // Compute new residual & response function EpetraExt::ModelEvaluator::OutArgs sg_outArgs2 = sg_model->createOutArgs(); Teuchos::RCP<Epetra_Vector> sg_g = Teuchos::rcp(new Epetra_Vector(*(sg_model->get_g_map(0)))); sg_f->PutScalar(0.0); sg_outArgs2.set_f(sg_f); sg_outArgs2.set_g(0, sg_g); sg_model->evalModel(sg_inArgs, sg_outArgs2); // Print initial residual norm sg_f->Norm2(&norm_f); if (MyPID == 0) std::cout << "\nFinal residual norm = " << norm_f << std::endl; // Print mean and standard deviation of responses Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_g_poly = sg_model->create_g_sg(0, View, sg_g.get()); Epetra_Vector g_mean(*(model->get_g_map(0))); Epetra_Vector g_std_dev(*(model->get_g_map(0))); sg_g_poly->computeMean(g_mean); sg_g_poly->computeStandardDeviation(g_std_dev); std::cout.precision(16); // std::cout << "\nResponse Expansion = " << std::endl; // std::cout.precision(12); // sg_g_poly->print(std::cout); std::cout << "\nResponse Mean = " << std::endl << g_mean << std::endl; std::cout << "Response Std. Dev. = " << std::endl << g_std_dev << std::endl; // Determine if example passed bool passed = false; if (norm_f < 1.0e-10 && std::abs(g_mean[0]-g_mean_exp) < g_tol && std::abs(g_std_dev[0]-g_std_dev_exp) < g_tol) passed = true; if (MyPID == 0) { if (passed) std::cout << "Example Passed!" << std::endl; else std::cout << "Example Failed!" << std::endl; } } Teuchos::TimeMonitor::summarize(std::cout); Teuchos::TimeMonitor::zeroOutTimers(); } catch (std::exception& e) { std::cout << e.what() << std::endl; } catch (string& s) { std::cout << s << std::endl; } catch (char *s) { std::cout << s << std::endl; } catch (...) { std::cout << "Caught unknown exception!" <<std:: endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif }
Stokhos::SparseGridQuadrature<ordinal_type, value_type>:: SparseGridQuadrature( const Teuchos::RCP<const ProductBasis<ordinal_type,value_type> >& product_basis, ordinal_type sparse_grid_level, value_type duplicate_tol, ordinal_type growth_rate) : coordinate_bases(product_basis->getCoordinateBases()) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Sparse Grid Generation"); #endif ordinal_type d = product_basis->dimension(); ordinal_type p = product_basis->order(); ordinal_type sz = product_basis->size(); ordinal_type level = sparse_grid_level; // Make level = order the default, which is correct for Gaussian abscissas // slow, linear growth, and total-order basis if (level == 0) { level = p; } //std::cout << "Sparse grid level = " << level << std::endl; // Compute quad points, weights, values Teuchos::Array<typename OneDOrthogPolyBasis<ordinal_type,value_type>::LevelToOrderFnPtr> growth_rules(d); Teuchos::Array< void (*) ( int order, int dim, double x[] ) > compute1DPoints(d); Teuchos::Array< void (*) ( int order, int dim, double w[] ) > compute1DWeights(d); for (ordinal_type i=0; i<d; i++) { compute1DPoints[i] = &(getMyPoints); compute1DWeights[i] = &(getMyWeights); growth_rules[i] = coordinate_bases[i]->getSparseGridGrowthRule(); } // Set the static sparse grid quadrature pointer to this // (this will cause a conflict if another sparse grid quadrature object // is trying to access the VPISparseGrid library, but that's all we can // do at this point). sgq = this; int num_total_pts = webbur::sgmg_size_total(d, level, growth_rate, &growth_rules[0]); ordinal_type ntot = webbur::sgmg_size(d, level, &compute1DPoints[0], duplicate_tol, growth_rate, &growth_rules[0]); Teuchos::Array<int> sparse_order(ntot*d); Teuchos::Array<int> sparse_index(ntot*d); Teuchos::Array<int> sparse_unique_index(num_total_pts); quad_points.resize(ntot); quad_weights.resize(ntot); quad_values.resize(ntot); Teuchos::Array<value_type> gp(ntot*d); webbur::sgmg_unique_index(d, level, &compute1DPoints[0], duplicate_tol, ntot, num_total_pts, growth_rate, &growth_rules[0], &sparse_unique_index[0]); webbur::sgmg_index(d, level, ntot, num_total_pts, &sparse_unique_index[0], growth_rate, &growth_rules[0], &sparse_order[0], &sparse_index[0]); webbur::sgmg_weight(d, level, &compute1DWeights[0], ntot, num_total_pts, &sparse_unique_index[0], growth_rate, &growth_rules[0], &quad_weights[0]); webbur::sgmg_point(d, level, &compute1DPoints[0], ntot, &sparse_order[0], &sparse_index[0], growth_rate, &growth_rules[0], &gp[0]); for (ordinal_type i=0; i<ntot; i++) { quad_values[i].resize(sz); quad_points[i].resize(d); for (ordinal_type j=0; j<d; j++) quad_points[i][j] = gp[i*d+j]; product_basis->evaluateBases(quad_points[i], quad_values[i]); } //std::cout << "Number of quadrature points = " << ntot << std::endl; }
static bool run_impl(int n, int sz, int nblocks, int nthreads, bool reset, bool print) { // Allocate memory inputs and outpus int len = nblocks*nthreads*sz*n; std::cout << "total size = " << len << std::endl; int stride = 1; double *x = new double[len]; double *y = new double[len]; double *y_mp = new double[len]; // Initialize x for (int i=0; i<len; i++) x[i] = static_cast<double>(i+1)/static_cast<double>(len); // Invoke kernel { TEUCHOS_FUNC_TIME_MONITOR("Host calculation"); for (int offset=0; offset<len; offset += sz*n) kernel(offset, stride, n, sz, x, y); } // Invoke kernel { TEUCHOS_FUNC_TIME_MONITOR("Host calculation (MP)"); for (int offset=0; offset<len; offset += sz*n) mpkernel<vector_type>(offset, stride, n, sz, x, y_mp, reset, print); } // Check results agree double rtol = 1e-15; double atol = 1e-15; bool agree = true; for (int i=0; i<len; i++) { if (std::abs(y[i]-y_mp[i]) > std::abs(y[i])*rtol + atol) { agree = false; break; } } if (print) { std::cout << "x = [ "; for (int i=0; i<len; i++) std::cout << x[i] << " "; std::cout << "]" << std::endl; std::cout << "y [ "; for (int i=0; i<len; i++) std::cout << y[i] << " "; std::cout << "]" << std::endl; std::cout << "y_mp = [ "; for (int i=0; i<len; i++) std::cout << y_mp[i] << " "; std::cout << "]" << std::endl; } // Clean up memory delete [] x; delete [] y; delete [] y_mp; return agree; }
int main(int argc, char *argv[]) { int n = 32; // spatial discretization (per dimension) int num_KL = 2; // number of KL terms int p = 3; // polynomial order double mu = 0.1; // mean of exponential random field double s = 0.2; // std. dev. of exponential r.f. bool nonlinear_expansion = false; // nonlinear expansion of diffusion coeff // (e.g., log-normal) bool matrix_free = true; // use matrix-free stochastic operator bool symmetric = false; // use symmetric formulation double g_mean_exp = 0.172988; // expected response mean double g_std_dev_exp = 0.0380007; // expected response std. dev. double g_tol = 1e-6; // tolerance on determining success // Initialize MPI #ifdef HAVE_MPI MPI_Init(&argc,&argv); #endif int MyPID; try { { TEUCHOS_FUNC_TIME_MONITOR("Total PCE Calculation Time"); // Create a communicator for Epetra objects Teuchos::RCP<const Epetra_Comm> globalComm; #ifdef HAVE_MPI globalComm = Teuchos::rcp(new Epetra_MpiComm(MPI_COMM_WORLD)); #else globalComm = Teuchos::rcp(new Epetra_SerialComm); #endif MyPID = globalComm->MyPID(); // Create Stochastic Galerkin basis and expansion Teuchos::Array< Teuchos::RCP<const Stokhos::OneDOrthogPolyBasis<int,double> > > bases(num_KL); for (int i=0; i<num_KL; i++) bases[i] = Teuchos::rcp(new Stokhos::LegendreBasis<int,double>(p, true)); Teuchos::RCP<const Stokhos::CompletePolynomialBasis<int,double> > basis = Teuchos::rcp(new Stokhos::CompletePolynomialBasis<int,double>(bases)); int sz = basis->size(); Teuchos::RCP<Stokhos::Sparse3Tensor<int,double> > Cijk; if (nonlinear_expansion) Cijk = basis->computeTripleProductTensor(); else Cijk = basis->computeLinearTripleProductTensor(); Teuchos::RCP<Stokhos::OrthogPolyExpansion<int,double> > expansion = Teuchos::rcp(new Stokhos::AlgebraicOrthogPolyExpansion<int,double>(basis, Cijk)); if (MyPID == 0) std::cout << "Stochastic Galerkin expansion size = " << sz << std::endl; // Create stochastic parallel distribution int num_spatial_procs = -1; if (argc > 1) num_spatial_procs = std::atoi(argv[1]); Teuchos::ParameterList parallelParams; parallelParams.set("Number of Spatial Processors", num_spatial_procs); Teuchos::RCP<Stokhos::ParallelData> sg_parallel_data = Teuchos::rcp(new Stokhos::ParallelData(basis, Cijk, globalComm, parallelParams)); Teuchos::RCP<const EpetraExt::MultiComm> sg_comm = sg_parallel_data->getMultiComm(); Teuchos::RCP<const Epetra_Comm> app_comm = sg_parallel_data->getSpatialComm(); // Create application Teuchos::RCP<twoD_diffusion_ME> model = Teuchos::rcp(new twoD_diffusion_ME(app_comm, n, num_KL, mu, s, basis, nonlinear_expansion, symmetric)); // Setup stochastic Galerkin algorithmic parameters Teuchos::RCP<Teuchos::ParameterList> sgParams = Teuchos::rcp(new Teuchos::ParameterList); Teuchos::ParameterList& sgOpParams = sgParams->sublist("SG Operator"); Teuchos::ParameterList& sgPrecParams = sgParams->sublist("SG Preconditioner"); if (!nonlinear_expansion) { sgParams->set("Parameter Expansion Type", "Linear"); sgParams->set("Jacobian Expansion Type", "Linear"); } if (matrix_free) { sgOpParams.set("Operator Method", "Matrix Free"); sgPrecParams.set("Preconditioner Method", "Approximate Gauss-Seidel"); sgPrecParams.set("Symmetric Gauss-Seidel", symmetric); sgPrecParams.set("Mean Preconditioner Type", "ML"); Teuchos::ParameterList& precParams = sgPrecParams.sublist("Mean Preconditioner Parameters"); precParams.set("default values", "SA"); precParams.set("ML output", 0); precParams.set("max levels",5); precParams.set("increasing or decreasing","increasing"); precParams.set("aggregation: type", "Uncoupled"); precParams.set("smoother: type","ML symmetric Gauss-Seidel"); precParams.set("smoother: sweeps",2); precParams.set("smoother: pre or post", "both"); precParams.set("coarse: max size", 200); #ifdef HAVE_ML_AMESOS precParams.set("coarse: type","Amesos-KLU"); #else precParams.set("coarse: type","Jacobi"); #endif } else { sgOpParams.set("Operator Method", "Fully Assembled"); sgPrecParams.set("Preconditioner Method", "None"); } // Create stochastic Galerkin model evaluator Teuchos::RCP<Stokhos::SGModelEvaluator> sg_model = Teuchos::rcp(new Stokhos::SGModelEvaluator(model, basis, Teuchos::null, expansion, sg_parallel_data, sgParams)); // Set up stochastic parameters // The current implementation of the model doesn't actually use these // values, but is hard-coded to certain uncertainty models Teuchos::Array<double> point(num_KL, 1.0); Teuchos::Array<double> basis_vals(sz); basis->evaluateBases(point, basis_vals); Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_p_init = sg_model->create_p_sg(0); for (int i=0; i<num_KL; i++) { sg_p_init->term(i,0)[i] = 0.0; sg_p_init->term(i,1)[i] = 1.0 / basis_vals[i+1]; } sg_model->set_p_sg_init(0, *sg_p_init); // Setup stochastic initial guess Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_x_init = sg_model->create_x_sg(); sg_x_init->init(0.0); sg_model->set_x_sg_init(*sg_x_init); // Set up NOX parameters Teuchos::RCP<Teuchos::ParameterList> noxParams = Teuchos::rcp(new Teuchos::ParameterList); // Set the nonlinear solver method noxParams->set("Nonlinear Solver", "Line Search Based"); // Set the printing parameters in the "Printing" sublist Teuchos::ParameterList& printParams = noxParams->sublist("Printing"); printParams.set("MyPID", MyPID); printParams.set("Output Precision", 3); printParams.set("Output Processor", 0); printParams.set("Output Information", NOX::Utils::OuterIteration + NOX::Utils::OuterIterationStatusTest + NOX::Utils::InnerIteration + NOX::Utils::LinearSolverDetails + NOX::Utils::Warning + NOX::Utils::Error); // Create printing utilities NOX::Utils utils(printParams); // Sublist for line search Teuchos::ParameterList& searchParams = noxParams->sublist("Line Search"); searchParams.set("Method", "Full Step"); // Sublist for direction Teuchos::ParameterList& dirParams = noxParams->sublist("Direction"); dirParams.set("Method", "Newton"); Teuchos::ParameterList& newtonParams = dirParams.sublist("Newton"); newtonParams.set("Forcing Term Method", "Constant"); // Sublist for linear solver for the Newton method Teuchos::ParameterList& lsParams = newtonParams.sublist("Linear Solver"); if (symmetric) lsParams.set("Aztec Solver", "CG"); else lsParams.set("Aztec Solver", "GMRES"); lsParams.set("Max Iterations", 1000); lsParams.set("Size of Krylov Subspace", 100); lsParams.set("Tolerance", 1e-12); lsParams.set("Output Frequency", 1); if (matrix_free) lsParams.set("Preconditioner", "User Defined"); else { lsParams.set("Preconditioner", "ML"); Teuchos::ParameterList& precParams = lsParams.sublist("ML"); ML_Epetra::SetDefaults("DD", precParams); lsParams.set("Write Linear System", false); } // Sublist for convergence tests Teuchos::ParameterList& statusParams = noxParams->sublist("Status Tests"); statusParams.set("Test Type", "Combo"); statusParams.set("Number of Tests", 2); statusParams.set("Combo Type", "OR"); Teuchos::ParameterList& normF = statusParams.sublist("Test 0"); normF.set("Test Type", "NormF"); normF.set("Tolerance", 1e-10); normF.set("Scale Type", "Scaled"); Teuchos::ParameterList& maxIters = statusParams.sublist("Test 1"); maxIters.set("Test Type", "MaxIters"); maxIters.set("Maximum Iterations", 1); // Create NOX interface Teuchos::RCP<NOX::Epetra::ModelEvaluatorInterface> nox_interface = Teuchos::rcp(new NOX::Epetra::ModelEvaluatorInterface(sg_model)); // Create NOX linear system object Teuchos::RCP<const Epetra_Vector> u = sg_model->get_x_init(); Teuchos::RCP<Epetra_Operator> A = sg_model->create_W(); Teuchos::RCP<NOX::Epetra::Interface::Required> iReq = nox_interface; Teuchos::RCP<NOX::Epetra::Interface::Jacobian> iJac = nox_interface; Teuchos::RCP<NOX::Epetra::LinearSystemAztecOO> linsys; if (matrix_free) { Teuchos::RCP<Epetra_Operator> M = sg_model->create_WPrec()->PrecOp; Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> iPrec = nox_interface; linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams, iJac, A, iPrec, M, *u)); } else { linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams, iReq, iJac, A, *u)); } // Build NOX group Teuchos::RCP<NOX::Epetra::Group> grp = Teuchos::rcp(new NOX::Epetra::Group(printParams, iReq, *u, linsys)); // Create the Solver convergence test Teuchos::RCP<NOX::StatusTest::Generic> statusTests = NOX::StatusTest::buildStatusTests(statusParams, utils); // Create the solver Teuchos::RCP<NOX::Solver::Generic> solver = NOX::Solver::buildSolver(grp, statusTests, noxParams); // Solve the system NOX::StatusTest::StatusType status = solver->solve(); // Get final solution const NOX::Epetra::Group& finalGroup = dynamic_cast<const NOX::Epetra::Group&>(solver->getSolutionGroup()); const Epetra_Vector& finalSolution = (dynamic_cast<const NOX::Epetra::Vector&>(finalGroup.getX())).getEpetraVector(); // Save final solution to file EpetraExt::VectorToMatrixMarketFile("nox_stochastic_solution.mm", finalSolution); // Save mean and variance to file Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_x_poly = sg_model->create_x_sg(View, &finalSolution); Epetra_Vector mean(*(model->get_x_map())); Epetra_Vector std_dev(*(model->get_x_map())); sg_x_poly->computeMean(mean); sg_x_poly->computeStandardDeviation(std_dev); EpetraExt::VectorToMatrixMarketFile("mean_gal.mm", mean); EpetraExt::VectorToMatrixMarketFile("std_dev_gal.mm", std_dev); // Evaluate SG responses at SG parameters EpetraExt::ModelEvaluator::InArgs sg_inArgs = sg_model->createInArgs(); EpetraExt::ModelEvaluator::OutArgs sg_outArgs = sg_model->createOutArgs(); Teuchos::RCP<const Epetra_Vector> sg_p = sg_model->get_p_init(1); Teuchos::RCP<Epetra_Vector> sg_g = Teuchos::rcp(new Epetra_Vector(*(sg_model->get_g_map(0)))); sg_inArgs.set_p(1, sg_p); sg_inArgs.set_x(Teuchos::rcp(&finalSolution,false)); sg_outArgs.set_g(0, sg_g); sg_model->evalModel(sg_inArgs, sg_outArgs); // Print mean and standard deviation of response Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_g_poly = sg_model->create_g_sg(0, View, sg_g.get()); Epetra_Vector g_mean(*(model->get_g_map(0))); Epetra_Vector g_std_dev(*(model->get_g_map(0))); sg_g_poly->computeMean(g_mean); sg_g_poly->computeStandardDeviation(g_std_dev); std::cout.precision(16); // std::cout << "\nResponse Expansion = " << std::endl; // std::cout.precision(12); // sg_g_poly->print(std::cout); std::cout << std::endl; std::cout << "Response Mean = " << std::endl << g_mean << std::endl; std::cout << "Response Std. Dev. = " << std::endl << g_std_dev << std::endl; // Determine if example passed bool passed = false; if (status == NOX::StatusTest::Converged && std::abs(g_mean[0]-g_mean_exp) < g_tol && std::abs(g_std_dev[0]-g_std_dev_exp) < g_tol) passed = true; if (MyPID == 0) { if (passed) std::cout << "Example Passed!" << std::endl; else std::cout << "Example Failed!" << std::endl; } } Teuchos::TimeMonitor::summarize(std::cout); Teuchos::TimeMonitor::zeroOutTimers(); } catch (std::exception& e) { std::cout << e.what() << std::endl; } catch (string& s) { std::cout << s << std::endl; } catch (char *s) { std::cout << s << std::endl; } catch (...) { std::cout << "Caught unknown exception!" <<std:: endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif }
bool run_kernels(Kokkos::ParallelWorkRequest config, int num_elements, int num_samples, bool reset, bool print, const std::string& device_name) { typedef vector_kernel<Scalar,ArrayVector,ScalarVector,Device> vec_kernel; typedef scalar_kernel<Scalar,Device> sca_kernel; typedef typename vec_kernel::view_type view_type; typedef typename view_type::HostMirror host_view_type; view_type x = view_type("x", num_elements, num_samples); view_type y_vec = view_type("y", num_elements, num_samples); view_type y_sca = view_type("y", num_elements, num_samples); host_view_type hx = Kokkos::create_mirror(x); // Initialize x for (int element=0; element<num_elements; element++) { for (int sample=0; sample<num_samples; sample++) { hx(element,sample) = static_cast<Scalar>(element+sample+1) / static_cast<Scalar>(num_elements*num_samples); } } // Copy x to device Kokkos::deep_copy(x, hx); // Run vector and scalar kernels { TEUCHOS_FUNC_TIME_MONITOR(device_name + " calculation"); sca_kernel::run(config, x, y_sca, reset, print); } { TEUCHOS_FUNC_TIME_MONITOR(device_name + " calculation (MP)"); vec_kernel::run(config, x, y_vec, reset, print); } // Copy results back to host host_view_type hy_vec = Kokkos::create_mirror(y_vec); host_view_type hy_sca = Kokkos::create_mirror(y_sca); Kokkos::deep_copy(hy_vec, y_vec); Kokkos::deep_copy(hy_sca, y_sca); // Check results agree double rtol = 1e-15; double atol = 1e-15; bool agree = true; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) { if (std::abs(hy_vec(e,s)-hy_sca(e,s)) > std::abs(hy_sca(e,s))*rtol+atol) { agree = false; break; } } } // Print results if requested if (print) { std::cout << "x = [ "; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) std::cout << hx(e,s) << " "; std::cout << ";" << std::endl; } std::cout << "]" << std::endl; std::cout << "y [ "; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) std::cout << hy_sca(e,s) << " "; std::cout << ";" << std::endl; } std::cout << "]" << std::endl; std::cout << "y_mp = [ "; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) std::cout << hy_vec(e,s) << " "; std::cout << ";" << std::endl; } std::cout << "]" << std::endl; } return agree; }
bool run_view_kernel( Kokkos::ParallelWorkRequest config, int num_elements , int num_samples , bool reset, bool print, const std::string& device_name ) { typedef typename Kokkos::Impl::if_c< SamplesPerThread , Stokhos::StaticFixedStorage< int , Scalar , SamplesPerThread , Device > , Stokhos::DynamicStorage< int , Scalar , Device > >::type storage_type ; typedef Kokkos::View< Sacado::MP::Vector< storage_type > * , Device > view_type ; typedef view_kernel< view_type > kernel; typedef typename view_type::HostMirror host_view_type; const bool input_error = SamplesPerThread && ( num_samples != int(config.team_size * SamplesPerThread) ); if ( print || input_error ) { std::cout << "run_view_kernel" ; if ( input_error ) { std::cout << " : ERROR num_samples != static(SamplesPerThread) * team_size : " ; } std::cout << " num_elements(" << num_elements << ")" << " num_samples(" << num_samples << ")" << " league_size(" << config.league_size << ")" << " team_size(" << config.team_size << ")" ; if ( SamplesPerThread ) { std::cout << " static(" << SamplesPerThread << ")" ; } else { std::cout << " dynamic" ; } std::cout << std::endl ; if ( input_error ) { return false ; } } view_type x( "x", num_elements, num_samples); view_type y( "y", num_elements, num_samples); host_view_type hy_ans("y_ans", num_elements, num_samples); host_view_type hx = Kokkos::create_mirror(x); // Initialize x for (int element=0; element<num_elements; element++) { for (int sample=0; sample<num_samples; sample++) { hx(element,sample) = static_cast<Scalar>(element+sample+1) / static_cast<Scalar>(num_elements*num_samples); simple_function<Scalar>( hx(element,sample) , hy_ans(element,sample) ); } } // Copy x to device Kokkos::deep_copy(x, hx); // Run vector and scalar kernels { TEUCHOS_FUNC_TIME_MONITOR(device_name + " calculation"); kernel::run(config, x, y, reset, print); } // Copy results back to host host_view_type hy = Kokkos::create_mirror(y); Kokkos::deep_copy(hy, y); // Check results agree double rtol = 1e-15; double atol = 1e-15; bool agree = true; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) { if (std::abs(hy(e,s)-hy_ans(e,s)) > std::abs(hy_ans(e,s))*rtol+atol) { agree = false; break; } } } // Print results if requested if (print) { std::cout << "x = [ "; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) std::cout << hx(e,s) << " "; std::cout << ";" << std::endl; } std::cout << "]" << std::endl; std::cout << "y = [ "; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) std::cout << hy(e,s) << " "; std::cout << ";" << std::endl; } std::cout << "]" << std::endl; std::cout << "hy_ans = [ "; for (int e=0; e<num_elements; e++) { for (int s=0; s<num_samples; s++) std::cout << hy_ans(e,s) << " "; std::cout << ";" << std::endl; } std::cout << "]" << std::endl; } return agree; }
int Stokhos::MatrixFreeOperator:: Apply(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SG Operator Apply()"); #endif // Note for transpose: // The stochastic matrix is symmetric, however the matrix blocks may not // be. So the algorithm here is the same whether we are using the transpose // or not. We just apply the transpose of the blocks in the case of // applying the global transpose, and make sure the imported Input // vectors use the right map. // We have to be careful if Input and Result are the same vector. // If this is the case, the only possible solution is to make a copy const Epetra_MultiVector *input = &Input; bool made_copy = false; if (Input.Values() == Result.Values() && !is_stoch_parallel) { input = new Epetra_MultiVector(Input); made_copy = true; } // Initialize Result.PutScalar(0.0); const Epetra_Map* input_base_map = domain_base_map.get(); const Epetra_Map* result_base_map = range_base_map.get(); if (useTranspose == true) { input_base_map = range_base_map.get(); result_base_map = domain_base_map.get(); } // Allocate temporary storage int m = Input.NumVectors(); if (useTranspose == false && (tmp == Teuchos::null || tmp->NumVectors() != m*max_num_mat_vec)) tmp = Teuchos::rcp(new Epetra_MultiVector(*result_base_map, m*max_num_mat_vec)); else if (useTranspose == true && (tmp_trans == Teuchos::null || tmp_trans->NumVectors() != m*max_num_mat_vec)) tmp_trans = Teuchos::rcp(new Epetra_MultiVector(*result_base_map, m*max_num_mat_vec)); Epetra_MultiVector *tmp_result; if (useTranspose == false) tmp_result = tmp.get(); else tmp_result = tmp_trans.get(); // Map input into column map const Epetra_MultiVector *tmp_col; if (!is_stoch_parallel) tmp_col = input; else { if (useTranspose == false) { if (input_col == Teuchos::null || input_col->NumVectors() != m) input_col = Teuchos::rcp(new Epetra_MultiVector(*global_col_map, m)); input_col->Import(*input, *col_importer, Insert); tmp_col = input_col.get(); } else { if (input_col_trans == Teuchos::null || input_col_trans->NumVectors() != m) input_col_trans = Teuchos::rcp(new Epetra_MultiVector(*global_col_map_trans, m)); input_col_trans->Import(*input, *col_importer_trans, Insert); tmp_col = input_col_trans.get(); } } // Extract blocks EpetraExt::BlockMultiVector sg_input(View, *input_base_map, *tmp_col); EpetraExt::BlockMultiVector sg_result(View, *result_base_map, Result); for (int i=0; i<input_block.size(); i++) input_block[i] = sg_input.GetBlock(i); for (int i=0; i<result_block.size(); i++) result_block[i] = sg_result.GetBlock(i); // Apply block SG operator via // w_i = // \sum_{j=0}^P \sum_{k=0}^L J_k v_j < \psi_i \psi_j \psi_k > / <\psi_i^2> // for i=0,...,P where P = expansion_size, L = num_blocks, w_j is the jth // input block, w_i is the ith result block, and J_k is the kth block operator // k_begin and k_end are initialized in the constructor const Teuchos::Array<double>& norms = sg_basis->norm_squared(); for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) { int k = index(k_it); Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it); Cijk_type::kj_iterator j_end = Cijk->j_end(k_it); int nj = Cijk->num_j(k_it); if (nj > 0) { Teuchos::Array<double*> j_ptr(nj*m); Teuchos::Array<int> mj_indices(nj*m); int l = 0; for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) { int j = index(j_it); for (int mm=0; mm<m; mm++) { j_ptr[l*m+mm] = (*input_block[j])[mm]; mj_indices[l*m+mm] = l*m+mm; } l++; } Epetra_MultiVector input_tmp(View, *input_base_map, &j_ptr[0], nj*m); Epetra_MultiVector result_tmp(View, *tmp_result, &mj_indices[0], nj*m); if (use_block_apply) { (*block_ops)[k].Apply(input_tmp, result_tmp); } else { for (int jj=0; jj<nj*m; jj++) (*block_ops)[k].Apply(*(input_tmp(jj)), *(result_tmp(jj))); } l = 0; for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) { int j = 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 = index(i_it); double c = value(i_it); if (scale_op) { int i_gid; if (useTranspose) i_gid = epetraCijk->GCID(j); else i_gid = epetraCijk->GRID(i); c /= norms[i_gid]; } for (int mm=0; mm<m; mm++) (*result_block[i])(mm)->Update(c, *result_tmp(l*m+mm), 1.0); } l++; } } } // Destroy blocks for (int i=0; i<input_block.size(); i++) input_block[i] = Teuchos::null; for (int i=0; i<result_block.size(); i++) result_block[i] = Teuchos::null; if (made_copy) delete input; return 0; }
void Stokhos::CGDivisionExpansionStrategy<ordinal_type,value_type,node_type>:: divide(Stokhos::OrthogPolyApprox<ordinal_type, value_type, node_type>& c, const value_type& alpha, const Stokhos::OrthogPolyApprox<ordinal_type, value_type, node_type>& a, const Stokhos::OrthogPolyApprox<ordinal_type, value_type, node_type>& b, const value_type& beta) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::CGDivisionStrategy::divide()"); #endif ordinal_type sz = basis->size(); ordinal_type pa = a.size(); ordinal_type pb = b.size(); ordinal_type pc; if (pb > 1) pc = sz; else pc = pa; if (c.size() != pc) c.resize(pc); const value_type* ca = a.coeff(); const value_type* cb = b.coeff(); value_type* cc = c.coeff(); if (pb > 1) { // Compute A A->putScalar(0.0); typename Cijk_type::k_iterator k_begin = Cijk->k_begin(); typename Cijk_type::k_iterator k_end = Cijk->k_end(); if (pb < Cijk->num_k()) k_end = Cijk->find_k(pb); value_type cijk; ordinal_type i,j,k; for (typename Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) { k = index(k_it); for (typename Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_it); ++j_it) { j = index(j_it); for (typename Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it); i_it != Cijk->i_end(j_it); ++i_it) { i = index(i_it); cijk = value(i_it); (*A)(i,j) += cijk*cb[k]; } } } // Compute B B->putScalar(0.0); for (ordinal_type i=0; i<pa; i++) (*B)(i,0) = ca[i]*basis->norm_squared(i); Teuchos::SerialDenseMatrix<ordinal_type,value_type> D(sz, 1); //Equilibrate the linear system if (equil == 1){ //Create diag mtx of max row entries for (ordinal_type i=0; i<sz; i++){ Teuchos::SerialDenseMatrix<ordinal_type, value_type> r(Teuchos::View, *A, 1, sz, i, 0); D(i,0)=sqrt(r.normOne()); } //Compute inv(D)*A*inv(D) for (ordinal_type i=0; i<sz; i++){ for (ordinal_type j=0; j<sz; j++){ (*A)(i,j)=(*A)(i,j)/(D(i,0)*D(j,0)); } } //Scale b by inv(D) for (ordinal_type i=0; i<sz; i++){ (*B)(i,0)=(*B)(i,0)/D(i,0); } } if (linear == 1){ //Compute M, the linear matrix to be used in the preconditioner pb = basis->dimension()+1; M->putScalar(0.0); if (pb < Cijk->num_k()) k_end = Cijk->find_k(pb); for (typename Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) { k = index(k_it); for ( typename Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_it); ++j_it) { j = index(j_it); for ( typename Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it); i_it != Cijk->i_end(j_it); ++i_it) { i = index(i_it); cijk = value(i_it); (*M)(i,j) += cijk*cb[k]; } } } //Scale M if (equil == 1){ //Compute inv(D)*M*inv(D) for (ordinal_type i=0; i<sz; i++){ for (ordinal_type j=0; j<sz; j++){ (*M)(i,j)=(*M)(i,j)/(D(i,0)*D(j,0)); } } } CG(*A,*X,*B, max_it, tol, prec_iter, basis->order(), basis->dimension(), PrecNum, *M, diag); } else{ CG(*A,*X,*B, max_it, tol, prec_iter, basis->order(), basis->dimension(), PrecNum, *A, diag); } if (equil == 1 ) { //Rescale X for (ordinal_type i=0; i<sz; i++){ (*X)(i,0)=(*X)(i,0)/D(i,0); } } // Compute c for (ordinal_type i=0; i<pc; i++) cc[i] = alpha*(*X)(i,0) + beta*cc[i]; } else { for (ordinal_type i=0; i<pc; i++) cc[i] = alpha*ca[i]/cb[0] + beta*cc[i]; } }
int main(int argc, char *argv[]) { // Initialize MPI #ifdef HAVE_MPI MPI_Init(&argc,&argv); #endif // Create a communicator for Epetra objects Teuchos::RCP<const Epetra_Comm> globalComm; #ifdef HAVE_MPI globalComm = Teuchos::rcp(new Epetra_MpiComm(MPI_COMM_WORLD)); #else globalComm = Teuchos::rcp(new Epetra_SerialComm); #endif int MyPID = globalComm->MyPID(); try { // Setup command line options Teuchos::CommandLineProcessor CLP; CLP.setDocString( "This example runs a variety of stochastic Galerkin solvers.\n"); int n = 32; CLP.setOption("num_mesh", &n, "Number of mesh points in each direction"); bool symmetric = false; CLP.setOption("symmetric", "unsymmetric", &symmetric, "Symmetric discretization"); int num_spatial_procs = -1; CLP.setOption("num_spatial_procs", &num_spatial_procs, "Number of spatial processors (set -1 for all available procs)"); bool rebalance_stochastic_graph = false; CLP.setOption("rebalance", "no-rebalance", &rebalance_stochastic_graph, "Rebalance parallel stochastic graph (requires Isorropia)"); SG_RF randField = UNIFORM; CLP.setOption("rand_field", &randField, num_sg_rf, sg_rf_values, sg_rf_names, "Random field type"); double mean = 0.2; CLP.setOption("mean", &mean, "Mean"); double sigma = 0.1; CLP.setOption("std_dev", &sigma, "Standard deviation"); double weightCut = 1.0; CLP.setOption("weight_cut", &weightCut, "Weight cut"); int num_KL = 2; CLP.setOption("num_kl", &num_KL, "Number of KL terms"); int p = 3; CLP.setOption("order", &p, "Polynomial order"); bool normalize_basis = true; CLP.setOption("normalize", "unnormalize", &normalize_basis, "Normalize PC basis"); SG_Solver solve_method = SG_KRYLOV; CLP.setOption("sg_solver", &solve_method, num_sg_solver, sg_solver_values, sg_solver_names, "SG solver method"); Krylov_Method outer_krylov_method = GMRES; CLP.setOption("outer_krylov_method", &outer_krylov_method, num_krylov_method, krylov_method_values, krylov_method_names, "Outer Krylov method (for Krylov-based SG solver)"); Krylov_Solver outer_krylov_solver = AZTECOO; CLP.setOption("outer_krylov_solver", &outer_krylov_solver, num_krylov_solver, krylov_solver_values, krylov_solver_names, "Outer linear solver"); double outer_tol = 1e-12; CLP.setOption("outer_tol", &outer_tol, "Outer solver tolerance"); int outer_its = 1000; CLP.setOption("outer_its", &outer_its, "Maximum outer iterations"); Krylov_Method inner_krylov_method = GMRES; CLP.setOption("inner_krylov_method", &inner_krylov_method, num_krylov_method, krylov_method_values, krylov_method_names, "Inner Krylov method (for G-S, Jacobi, etc...)"); Krylov_Solver inner_krylov_solver = AZTECOO; CLP.setOption("inner_krylov_solver", &inner_krylov_solver, num_krylov_solver, krylov_solver_values, krylov_solver_names, "Inner linear solver"); double inner_tol = 3e-13; CLP.setOption("inner_tol", &inner_tol, "Inner solver tolerance"); int inner_its = 1000; CLP.setOption("inner_its", &inner_its, "Maximum inner iterations"); SG_Op opMethod = MATRIX_FREE; CLP.setOption("sg_operator_method", &opMethod, num_sg_op, sg_op_values, sg_op_names, "Operator method"); SG_Prec precMethod = AGS; CLP.setOption("sg_prec_method", &precMethod, num_sg_prec, sg_prec_values, sg_prec_names, "Preconditioner method"); double gs_prec_tol = 1e-1; CLP.setOption("gs_prec_tol", &gs_prec_tol, "Gauss-Seidel preconditioner tolerance"); int gs_prec_its = 1; CLP.setOption("gs_prec_its", &gs_prec_its, "Maximum Gauss-Seidel preconditioner iterations"); CLP.parse( argc, argv ); if (MyPID == 0) { std::cout << "Summary of command line options:" << std::endl << "\tnum_mesh = " << n << std::endl << "\tsymmetric = " << symmetric << std::endl << "\tnum_spatial_procs = " << num_spatial_procs << std::endl << "\trebalance = " << rebalance_stochastic_graph << std::endl << "\trand_field = " << sg_rf_names[randField] << std::endl << "\tmean = " << mean << std::endl << "\tstd_dev = " << sigma << std::endl << "\tweight_cut = " << weightCut << std::endl << "\tnum_kl = " << num_KL << std::endl << "\torder = " << p << std::endl << "\tnormalize_basis = " << normalize_basis << std::endl << "\tsg_solver = " << sg_solver_names[solve_method] << std::endl << "\touter_krylov_method = " << krylov_method_names[outer_krylov_method] << std::endl << "\touter_krylov_solver = " << krylov_solver_names[outer_krylov_solver] << std::endl << "\touter_tol = " << outer_tol << std::endl << "\touter_its = " << outer_its << std::endl << "\tinner_krylov_method = " << krylov_method_names[inner_krylov_method] << std::endl << "\tinner_krylov_solver = " << krylov_solver_names[inner_krylov_solver] << std::endl << "\tinner_tol = " << inner_tol << std::endl << "\tinner_its = " << inner_its << std::endl << "\tsg_operator_method = " << sg_op_names[opMethod] << std::endl << "\tsg_prec_method = " << sg_prec_names[precMethod] << std::endl << "\tgs_prec_tol = " << gs_prec_tol << std::endl << "\tgs_prec_its = " << gs_prec_its << std::endl; } bool nonlinear_expansion = false; if (randField == UNIFORM || randField == RYS) nonlinear_expansion = false; else if (randField == LOGNORMAL) nonlinear_expansion = true; bool scaleOP = true; { TEUCHOS_FUNC_TIME_MONITOR("Total PCE Calculation Time"); // Create Stochastic Galerkin basis and expansion Teuchos::Array< Teuchos::RCP<const Stokhos::OneDOrthogPolyBasis<int,double> > > bases(num_KL); for (int i=0; i<num_KL; i++) if (randField == UNIFORM) bases[i] = Teuchos::rcp(new Stokhos::LegendreBasis<int,double>(p,normalize_basis)); else if (randField == RYS) bases[i] = Teuchos::rcp(new Stokhos::RysBasis<int,double>(p,weightCut,normalize_basis)); else if (randField == LOGNORMAL) bases[i] = Teuchos::rcp(new Stokhos::HermiteBasis<int,double>(p,normalize_basis)); // bases[i] = Teuchos::rcp(new Stokhos::DiscretizedStieltjesBasis<int,double>("beta",p,&uniform_weight,-weightCut,weightCut,true)); Teuchos::RCP<const Stokhos::CompletePolynomialBasis<int,double> > basis = Teuchos::rcp(new Stokhos::CompletePolynomialBasis<int,double>(bases)); int sz = basis->size(); Teuchos::RCP<Stokhos::Sparse3Tensor<int,double> > Cijk; if (nonlinear_expansion) Cijk = basis->computeTripleProductTensor(sz); else Cijk = basis->computeTripleProductTensor(num_KL+1); Teuchos::RCP<Stokhos::OrthogPolyExpansion<int,double> > expansion = Teuchos::rcp(new Stokhos::AlgebraicOrthogPolyExpansion<int,double>(basis, Cijk)); if (MyPID == 0) std::cout << "Stochastic Galerkin expansion size = " << sz << std::endl; // Create stochastic parallel distribution Teuchos::ParameterList parallelParams; parallelParams.set("Number of Spatial Processors", num_spatial_procs); parallelParams.set("Rebalance Stochastic Graph", rebalance_stochastic_graph); Teuchos::RCP<Stokhos::ParallelData> sg_parallel_data = Teuchos::rcp(new Stokhos::ParallelData(basis, Cijk, globalComm, parallelParams)); Teuchos::RCP<const EpetraExt::MultiComm> sg_comm = sg_parallel_data->getMultiComm(); Teuchos::RCP<const Epetra_Comm> app_comm = sg_parallel_data->getSpatialComm(); // Create application Teuchos::RCP<twoD_diffusion_ME> model = Teuchos::rcp(new twoD_diffusion_ME(app_comm, n, num_KL, sigma, mean, basis, nonlinear_expansion, symmetric)); // Set up NOX parameters Teuchos::RCP<Teuchos::ParameterList> noxParams = Teuchos::rcp(new Teuchos::ParameterList); // Set the nonlinear solver method noxParams->set("Nonlinear Solver", "Line Search Based"); // Set the printing parameters in the "Printing" sublist Teuchos::ParameterList& printParams = noxParams->sublist("Printing"); printParams.set("MyPID", MyPID); printParams.set("Output Precision", 3); printParams.set("Output Processor", 0); printParams.set("Output Information", NOX::Utils::OuterIteration + NOX::Utils::OuterIterationStatusTest + NOX::Utils::InnerIteration + //NOX::Utils::Parameters + NOX::Utils::Details + NOX::Utils::LinearSolverDetails + NOX::Utils::Warning + NOX::Utils::Error); // Create printing utilities NOX::Utils utils(printParams); // Sublist for line search Teuchos::ParameterList& searchParams = noxParams->sublist("Line Search"); searchParams.set("Method", "Full Step"); // Sublist for direction Teuchos::ParameterList& dirParams = noxParams->sublist("Direction"); dirParams.set("Method", "Newton"); Teuchos::ParameterList& newtonParams = dirParams.sublist("Newton"); newtonParams.set("Forcing Term Method", "Constant"); // Sublist for linear solver for the Newton method Teuchos::ParameterList& lsParams = newtonParams.sublist("Linear Solver"); // Alternative linear solver list for Stratimikos Teuchos::ParameterList& stratLinSolParams = newtonParams.sublist("Stratimikos Linear Solver"); // Teuchos::ParameterList& noxStratParams = // stratLinSolParams.sublist("NOX Stratimikos Options"); Teuchos::ParameterList& stratParams = stratLinSolParams.sublist("Stratimikos"); // Sublist for convergence tests Teuchos::ParameterList& statusParams = noxParams->sublist("Status Tests"); statusParams.set("Test Type", "Combo"); statusParams.set("Number of Tests", 2); statusParams.set("Combo Type", "OR"); Teuchos::ParameterList& normF = statusParams.sublist("Test 0"); normF.set("Test Type", "NormF"); normF.set("Tolerance", outer_tol); normF.set("Scale Type", "Scaled"); Teuchos::ParameterList& maxIters = statusParams.sublist("Test 1"); maxIters.set("Test Type", "MaxIters"); maxIters.set("Maximum Iterations", 1); // Create NOX interface Teuchos::RCP<NOX::Epetra::ModelEvaluatorInterface> det_nox_interface = Teuchos::rcp(new NOX::Epetra::ModelEvaluatorInterface(model)); // Create NOX linear system object Teuchos::RCP<const Epetra_Vector> det_u = model->get_x_init(); Teuchos::RCP<Epetra_Operator> det_A = model->create_W(); Teuchos::RCP<NOX::Epetra::Interface::Required> det_iReq = det_nox_interface; Teuchos::RCP<NOX::Epetra::Interface::Jacobian> det_iJac = det_nox_interface; Teuchos::ParameterList det_printParams; det_printParams.set("MyPID", MyPID); det_printParams.set("Output Precision", 3); det_printParams.set("Output Processor", 0); det_printParams.set("Output Information", NOX::Utils::Error); Teuchos::ParameterList det_lsParams; Teuchos::ParameterList& det_stratParams = det_lsParams.sublist("Stratimikos"); if (inner_krylov_solver == AZTECOO) { det_stratParams.set("Linear Solver Type", "AztecOO"); Teuchos::ParameterList& aztecOOParams = det_stratParams.sublist("Linear Solver Types").sublist("AztecOO").sublist("Forward Solve"); Teuchos::ParameterList& aztecOOSettings = aztecOOParams.sublist("AztecOO Settings"); if (inner_krylov_method == GMRES) { aztecOOSettings.set("Aztec Solver","GMRES"); } else if (inner_krylov_method == CG) { aztecOOSettings.set("Aztec Solver","CG"); } aztecOOSettings.set("Output Frequency", 0); aztecOOSettings.set("Size of Krylov Subspace", 100); aztecOOParams.set("Max Iterations", inner_its); aztecOOParams.set("Tolerance", inner_tol); Teuchos::ParameterList& verbParams = det_stratParams.sublist("Linear Solver Types").sublist("AztecOO").sublist("VerboseObject"); verbParams.set("Verbosity Level", "none"); } else if (inner_krylov_solver == BELOS) { det_stratParams.set("Linear Solver Type", "Belos"); Teuchos::ParameterList& belosParams = det_stratParams.sublist("Linear Solver Types").sublist("Belos"); Teuchos::ParameterList* belosSolverParams = NULL; if (inner_krylov_method == GMRES || inner_krylov_method == FGMRES) { belosParams.set("Solver Type","Block GMRES"); belosSolverParams = &(belosParams.sublist("Solver Types").sublist("Block GMRES")); if (inner_krylov_method == FGMRES) belosSolverParams->set("Flexible Gmres", true); } else if (inner_krylov_method == CG) { belosParams.set("Solver Type","Block CG"); belosSolverParams = &(belosParams.sublist("Solver Types").sublist("Block CG")); } else if (inner_krylov_method == RGMRES) { belosParams.set("Solver Type","GCRODR"); belosSolverParams = &(belosParams.sublist("Solver Types").sublist("GCRODR")); } belosSolverParams->set("Convergence Tolerance", inner_tol); belosSolverParams->set("Maximum Iterations", inner_its); belosSolverParams->set("Output Frequency",0); belosSolverParams->set("Output Style",1); belosSolverParams->set("Verbosity",0); Teuchos::ParameterList& verbParams = belosParams.sublist("VerboseObject"); verbParams.set("Verbosity Level", "none"); } det_stratParams.set("Preconditioner Type", "ML"); Teuchos::ParameterList& det_ML = det_stratParams.sublist("Preconditioner Types").sublist("ML").sublist("ML Settings"); ML_Epetra::SetDefaults("SA", det_ML); det_ML.set("ML output", 0); det_ML.set("max levels",5); det_ML.set("increasing or decreasing","increasing"); det_ML.set("aggregation: type", "Uncoupled"); det_ML.set("smoother: type","ML symmetric Gauss-Seidel"); det_ML.set("smoother: sweeps",2); det_ML.set("smoother: pre or post", "both"); det_ML.set("coarse: max size", 200); #ifdef HAVE_ML_AMESOS det_ML.set("coarse: type","Amesos-KLU"); #else det_ML.set("coarse: type","Jacobi"); #endif Teuchos::RCP<NOX::Epetra::LinearSystem> det_linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemStratimikos( det_printParams, det_lsParams, det_iJac, det_A, *det_u)); // Setup stochastic Galerkin algorithmic parameters Teuchos::RCP<Teuchos::ParameterList> sgParams = Teuchos::rcp(new Teuchos::ParameterList); Teuchos::ParameterList& sgOpParams = sgParams->sublist("SG Operator"); Teuchos::ParameterList& sgPrecParams = sgParams->sublist("SG Preconditioner"); if (!nonlinear_expansion) { sgParams->set("Parameter Expansion Type", "Linear"); sgParams->set("Jacobian Expansion Type", "Linear"); } if (opMethod == MATRIX_FREE) sgOpParams.set("Operator Method", "Matrix Free"); else if (opMethod == KL_MATRIX_FREE) sgOpParams.set("Operator Method", "KL Matrix Free"); else if (opMethod == KL_REDUCED_MATRIX_FREE) { sgOpParams.set("Operator Method", "KL Reduced Matrix Free"); if (randField == UNIFORM || randField == RYS) sgOpParams.set("Number of KL Terms", num_KL); else sgOpParams.set("Number of KL Terms", basis->size()); sgOpParams.set("KL Tolerance", outer_tol); sgOpParams.set("Sparse 3 Tensor Drop Tolerance", outer_tol); sgOpParams.set("Do Error Tests", true); } else if (opMethod == FULLY_ASSEMBLED) sgOpParams.set("Operator Method", "Fully Assembled"); else TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Error! Unknown operator method " << opMethod << "." << std::endl); if (precMethod == MEAN) { sgPrecParams.set("Preconditioner Method", "Mean-based"); sgPrecParams.set("Mean Preconditioner Type", "ML"); Teuchos::ParameterList& precParams = sgPrecParams.sublist("Mean Preconditioner Parameters"); precParams = det_ML; } else if(precMethod == GS) { sgPrecParams.set("Preconditioner Method", "Gauss-Seidel"); sgPrecParams.sublist("Deterministic Solver Parameters") = det_lsParams; sgPrecParams.set("Deterministic Solver", det_linsys); sgPrecParams.set("Max Iterations", gs_prec_its); sgPrecParams.set("Tolerance", gs_prec_tol); } else if (precMethod == AGS) { sgPrecParams.set("Preconditioner Method", "Approximate Gauss-Seidel"); if (outer_krylov_method == CG) sgPrecParams.set("Symmetric Gauss-Seidel", true); sgPrecParams.set("Mean Preconditioner Type", "ML"); Teuchos::ParameterList& precParams = sgPrecParams.sublist("Mean Preconditioner Parameters"); precParams = det_ML; } else if (precMethod == AJ) { sgPrecParams.set("Preconditioner Method", "Approximate Jacobi"); sgPrecParams.set("Mean Preconditioner Type", "ML"); Teuchos::ParameterList& precParams = sgPrecParams.sublist("Mean Preconditioner Parameters"); precParams = det_ML; Teuchos::ParameterList& jacobiOpParams = sgPrecParams.sublist("Jacobi SG Operator"); jacobiOpParams.set("Only Use Linear Terms", true); } else if (precMethod == ASC) { sgPrecParams.set("Preconditioner Method", "Approximate Schur Complement"); sgPrecParams.set("Mean Preconditioner Type", "ML"); Teuchos::ParameterList& precParams = sgPrecParams.sublist("Mean Preconditioner Parameters"); precParams = det_ML; } else if (precMethod == KP) { sgPrecParams.set("Preconditioner Method", "Kronecker Product"); sgPrecParams.set("Only Use Linear Terms", true); sgPrecParams.set("Mean Preconditioner Type", "ML"); Teuchos::ParameterList& meanPrecParams = sgPrecParams.sublist("Mean Preconditioner Parameters"); meanPrecParams = det_ML; sgPrecParams.set("G Preconditioner Type", "Ifpack"); Teuchos::ParameterList& GPrecParams = sgPrecParams.sublist("G Preconditioner Parameters"); if (outer_krylov_method == GMRES || outer_krylov_method == FGMRES) GPrecParams.set("Ifpack Preconditioner", "ILUT"); if (outer_krylov_method == CG) GPrecParams.set("Ifpack Preconditioner", "ICT"); GPrecParams.set("Overlap", 1); GPrecParams.set("fact: drop tolerance", 1e-4); GPrecParams.set("fact: ilut level-of-fill", 1.0); GPrecParams.set("schwarz: combine mode", "Add"); } else if (precMethod == NONE) { sgPrecParams.set("Preconditioner Method", "None"); } else TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Error! Unknown preconditioner method " << precMethod << "." << std::endl); // Create stochastic Galerkin model evaluator Teuchos::RCP<Stokhos::SGModelEvaluator> sg_model = Teuchos::rcp(new Stokhos::SGModelEvaluator(model, basis, Teuchos::null, expansion, sg_parallel_data, sgParams, scaleOP)); EpetraExt::ModelEvaluator::InArgs sg_inArgs = sg_model->createInArgs(); EpetraExt::ModelEvaluator::OutArgs sg_outArgs = sg_model->createOutArgs(); // Set up stochastic parameters Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_p_init = sg_model->create_p_sg(0); for (int i=0; i<num_KL; i++) { sg_p_init->term(i,0)[i] = 0.0; sg_p_init->term(i,1)[i] = 1.0; } sg_model->set_p_sg_init(0, *sg_p_init); // Setup stochastic initial guess Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_x_init = sg_model->create_x_sg(); sg_x_init->init(0.0); sg_model->set_x_sg_init(*sg_x_init); // Create NOX interface Teuchos::RCP<NOX::Epetra::ModelEvaluatorInterface> nox_interface = Teuchos::rcp(new NOX::Epetra::ModelEvaluatorInterface(sg_model)); // Create NOX stochastic linear system object Teuchos::RCP<const Epetra_Vector> u = sg_model->get_x_init(); Teuchos::RCP<const Epetra_Map> base_map = model->get_x_map(); Teuchos::RCP<const Epetra_Map> sg_map = sg_model->get_x_map(); Teuchos::RCP<Epetra_Operator> A = sg_model->create_W(); Teuchos::RCP<NOX::Epetra::Interface::Required> iReq = nox_interface; Teuchos::RCP<NOX::Epetra::Interface::Jacobian> iJac = nox_interface; // Build linear solver Teuchos::RCP<NOX::Epetra::LinearSystem> linsys; if (solve_method==SG_KRYLOV) { bool has_M = sg_outArgs.supports(EpetraExt::ModelEvaluator::OUT_ARG_WPrec); Teuchos::RCP<Epetra_Operator> M; Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> iPrec; if (has_M) { M = sg_model->create_WPrec()->PrecOp; iPrec = nox_interface; } stratParams.set("Preconditioner Type", "None"); if (outer_krylov_solver == AZTECOO) { stratParams.set("Linear Solver Type", "AztecOO"); Teuchos::ParameterList& aztecOOParams = stratParams.sublist("Linear Solver Types").sublist("AztecOO").sublist("Forward Solve"); Teuchos::ParameterList& aztecOOSettings = aztecOOParams.sublist("AztecOO Settings"); if (outer_krylov_method == GMRES) { aztecOOSettings.set("Aztec Solver","GMRES"); } else if (outer_krylov_method == CG) { aztecOOSettings.set("Aztec Solver","CG"); } aztecOOSettings.set("Output Frequency", 1); aztecOOSettings.set("Size of Krylov Subspace", 100); aztecOOParams.set("Max Iterations", outer_its); aztecOOParams.set("Tolerance", outer_tol); stratLinSolParams.set("Preconditioner", "User Defined"); if (has_M) linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemStratimikos( printParams, stratLinSolParams, iJac, A, iPrec, M, *u, true)); else linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemStratimikos( printParams, stratLinSolParams, iJac, A, *u)); } else if (outer_krylov_solver == BELOS){ stratParams.set("Linear Solver Type", "Belos"); Teuchos::ParameterList& belosParams = stratParams.sublist("Linear Solver Types").sublist("Belos"); Teuchos::ParameterList* belosSolverParams = NULL; if (outer_krylov_method == GMRES || outer_krylov_method == FGMRES) { belosParams.set("Solver Type","Block GMRES"); belosSolverParams = &(belosParams.sublist("Solver Types").sublist("Block GMRES")); if (outer_krylov_method == FGMRES) belosSolverParams->set("Flexible Gmres", true); } else if (outer_krylov_method == CG) { belosParams.set("Solver Type","Block CG"); belosSolverParams = &(belosParams.sublist("Solver Types").sublist("Block CG")); } else if (inner_krylov_method == RGMRES) { belosParams.set("Solver Type","GCRODR"); belosSolverParams = &(belosParams.sublist("Solver Types").sublist("GCRODR")); } belosSolverParams->set("Convergence Tolerance", outer_tol); belosSolverParams->set("Maximum Iterations", outer_its); belosSolverParams->set("Output Frequency",1); belosSolverParams->set("Output Style",1); belosSolverParams->set("Verbosity",33); stratLinSolParams.set("Preconditioner", "User Defined"); if (has_M) linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemStratimikos( printParams, stratLinSolParams, iJac, A, iPrec, M, *u, true)); else linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemStratimikos( printParams, stratLinSolParams, iJac, A, *u)); } } else if (solve_method==SG_GS) { lsParams.sublist("Deterministic Solver Parameters") = det_lsParams; lsParams.set("Max Iterations", outer_its); lsParams.set("Tolerance", outer_tol); linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemSGGS( printParams, lsParams, det_linsys, iReq, iJac, basis, sg_parallel_data, A, base_map, sg_map)); } else { lsParams.sublist("Deterministic Solver Parameters") = det_lsParams; lsParams.set("Max Iterations", outer_its); lsParams.set("Tolerance", outer_tol); Teuchos::ParameterList& jacobiOpParams = lsParams.sublist("Jacobi SG Operator"); jacobiOpParams.set("Only Use Linear Terms", true); linsys = Teuchos::rcp(new NOX::Epetra::LinearSystemSGJacobi( printParams, lsParams, det_linsys, iReq, iJac, basis, sg_parallel_data, A, base_map, sg_map)); } // Build NOX group Teuchos::RCP<NOX::Epetra::Group> grp = Teuchos::rcp(new NOX::Epetra::Group(printParams, iReq, *u, linsys)); // Create the Solver convergence test Teuchos::RCP<NOX::StatusTest::Generic> statusTests = NOX::StatusTest::buildStatusTests(statusParams, utils); // Create the solver Teuchos::RCP<NOX::Solver::Generic> solver = NOX::Solver::buildSolver(grp, statusTests, noxParams); // Solve the system NOX::StatusTest::StatusType status; { TEUCHOS_FUNC_TIME_MONITOR("Total Solve Time"); status = solver->solve(); } // Get final solution const NOX::Epetra::Group& finalGroup = dynamic_cast<const NOX::Epetra::Group&>(solver->getSolutionGroup()); const Epetra_Vector& finalSolution = (dynamic_cast<const NOX::Epetra::Vector&>(finalGroup.getX())).getEpetraVector(); // Save final solution to file EpetraExt::VectorToMatrixMarketFile("nox_solver_stochastic_solution.mm", finalSolution); // Save mean and variance to file Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_x_poly = sg_model->create_x_sg(View, &finalSolution); Epetra_Vector mean(*(model->get_x_map())); Epetra_Vector std_dev(*(model->get_x_map())); sg_x_poly->computeMean(mean); sg_x_poly->computeStandardDeviation(std_dev); EpetraExt::VectorToMatrixMarketFile("mean_gal.mm", mean); EpetraExt::VectorToMatrixMarketFile("std_dev_gal.mm", std_dev); // Evaluate SG responses at SG parameters Teuchos::RCP<const Epetra_Vector> sg_p = sg_model->get_p_init(1); Teuchos::RCP<Epetra_Vector> sg_g = Teuchos::rcp(new Epetra_Vector(*(sg_model->get_g_map(0)))); sg_inArgs.set_p(1, sg_p); sg_inArgs.set_x(Teuchos::rcp(&finalSolution,false)); sg_outArgs.set_g(0, sg_g); sg_model->evalModel(sg_inArgs, sg_outArgs); // Print mean and standard deviation of response Teuchos::RCP<Stokhos::EpetraVectorOrthogPoly> sg_g_poly = sg_model->create_g_sg(0, View, sg_g.get()); Epetra_Vector g_mean(*(model->get_g_map(0))); Epetra_Vector g_std_dev(*(model->get_g_map(0))); sg_g_poly->computeMean(g_mean); sg_g_poly->computeStandardDeviation(g_std_dev); std::cout.precision(16); // std::cout << "\nResponse Expansion = " << std::endl; // std::cout.precision(12); // sg_g_poly->print(std::cout); std::cout << "\nResponse Mean = " << std::endl << g_mean << std::endl; std::cout << "Response Std. Dev. = " << std::endl << g_std_dev << std::endl; if (status == NOX::StatusTest::Converged && MyPID == 0) utils.out() << "Example Passed!" << std::endl; } Teuchos::TimeMonitor::summarize(std::cout); Teuchos::TimeMonitor::zeroOutTimers(); } catch (std::exception& e) { std::cout << e.what() << std::endl; } catch (string& s) { std::cout << s << std::endl; } catch (char *s) { std::cout << s << std::endl; } catch (...) { std::cout << "Caught unknown exception!" <<std:: endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif }
void Stokhos::SGQuadModelEvaluator:: evalModel(const InArgs& inArgs, const OutArgs& outArgs) const { // Create underlying inargs InArgs me_inargs = me->createInArgs(); if (me_inargs.supports(IN_ARG_x)) me_inargs.set_x(inArgs.get_x()); if (me_inargs.supports(IN_ARG_x_dot)) me_inargs.set_x_dot(inArgs.get_x_dot()); if (me_inargs.supports(IN_ARG_alpha)) me_inargs.set_alpha(inArgs.get_alpha()); if (me_inargs.supports(IN_ARG_beta)) me_inargs.set_beta(inArgs.get_beta()); if (me_inargs.supports(IN_ARG_t)) me_inargs.set_t(inArgs.get_t()); for (int i=0; i<num_p; i++) me_inargs.set_p(i, inArgs.get_p(i)); // Create underlying outargs OutArgs me_outargs = me->createOutArgs(); if (me_outargs.supports(OUT_ARG_f)) me_outargs.set_f(outArgs.get_f()); if (me_outargs.supports(OUT_ARG_W)) me_outargs.set_W(outArgs.get_W()); for (int j=0; j<num_p; j++) if (!outArgs.supports(OUT_ARG_DfDp, j).none()) me_outargs.set_DfDp(j, outArgs.get_DfDp(j)); for (int i=0; i<num_g; i++) { me_outargs.set_g(i, outArgs.get_g(i)); if (!outArgs.supports(OUT_ARG_DgDx, i).none()) me_outargs.set_DgDx(i, outArgs.get_DgDx(i)); if (!outArgs.supports(OUT_ARG_DgDx_dot, i).none()) me_outargs.set_DgDx(i, outArgs.get_DgDx_dot(i)); for (int j=0; j<num_p; j++) if (!outArgs.supports(OUT_ARG_DgDp, i, j).none()) me_outargs.set_DgDp(i, j, outArgs.get_DgDp(i,j)); } bool do_quad = false; InArgs::sg_const_vector_t x_sg; InArgs::sg_const_vector_t x_dot_sg; Teuchos::Array<InArgs::sg_const_vector_t> p_sg(num_p); OutArgs::sg_vector_t f_sg; OutArgs::sg_operator_t W_sg; Teuchos::Array<SGDerivative> dfdp_sg(num_p); Teuchos::Array<OutArgs::sg_vector_t> g_sg(num_g); Teuchos::Array<SGDerivative> dgdx_sg(num_g); Teuchos::Array<SGDerivative> dgdx_dot_sg(num_g); Teuchos::Array< Teuchos::Array<SGDerivative> > dgdp_sg(num_g); TEUCHOS_TEST_FOR_EXCEPTION(inArgs.get_sg_basis() == Teuchos::null, std::logic_error, "Error! Stokhos::SGQuadModelEvaluator::evalModel(): " << "SG basis inArg cannot be null!"); TEUCHOS_TEST_FOR_EXCEPTION(inArgs.get_sg_quadrature() == Teuchos::null, std::logic_error, "Error! Stokhos::SGQuadModelEvaluator::evalModel(): " << "SG quadrature inArg cannot be null!"); Teuchos::RCP<const Stokhos::OrthogPolyBasis<int,double> > basis = inArgs.get_sg_basis(); Teuchos::RCP< const Stokhos::Quadrature<int,double> > quad = inArgs.get_sg_quadrature(); if (inArgs.supports(IN_ARG_x_sg)) { x_sg = inArgs.get_x_sg(); if (x_sg != Teuchos::null) { do_quad = true; } } if (inArgs.supports(IN_ARG_x_dot_sg)) { x_dot_sg = inArgs.get_x_dot_sg(); if (x_dot_sg != Teuchos::null) { do_quad = true; } } for (int i=0; i<num_p; i++) { p_sg[i] = inArgs.get_p_sg(i); if (p_sg[i] != Teuchos::null) { do_quad = true; } } if (outArgs.supports(OUT_ARG_f_sg)) { f_sg = outArgs.get_f_sg(); if (f_sg != Teuchos::null) f_sg->init(0.0); } if (outArgs.supports(OUT_ARG_W_sg)) { W_sg = outArgs.get_W_sg(); if (W_sg != Teuchos::null) W_sg->init(0.0); } for (int i=0; i<num_p; i++) { if (!outArgs.supports(OUT_ARG_DfDp_sg, i).none()) { dfdp_sg[i] = outArgs.get_DfDp_sg(i); if (dfdp_sg[i].getMultiVector() != Teuchos::null) dfdp_sg[i].getMultiVector()->init(0.0); else if (dfdp_sg[i].getLinearOp() != Teuchos::null) dfdp_sg[i].getLinearOp()->init(0.0); } } for (int i=0; i<num_g; i++) { g_sg[i] = outArgs.get_g_sg(i); if (g_sg[i] != Teuchos::null) g_sg[i]->init(0.0); if (!outArgs.supports(OUT_ARG_DgDx_sg, i).none()) { dgdx_sg[i] = outArgs.get_DgDx_sg(i); if (dgdx_sg[i].getMultiVector() != Teuchos::null) dgdx_sg[i].getMultiVector()->init(0.0); else if (dgdx_sg[i].getLinearOp() != Teuchos::null) dgdx_sg[i].getLinearOp()->init(0.0); } if (!outArgs.supports(OUT_ARG_DgDx_dot_sg, i).none()) { dgdx_dot_sg[i] = outArgs.get_DgDx_dot_sg(i); if (dgdx_dot_sg[i].getMultiVector() != Teuchos::null) dgdx_dot_sg[i].getMultiVector()->init(0.0); else if (dgdx_dot_sg[i].getLinearOp() != Teuchos::null) dgdx_dot_sg[i].getLinearOp()->init(0.0); } dgdp_sg[i].resize(num_p); for (int j=0; j<num_p; j++) { if (!outArgs.supports(OUT_ARG_DgDp_sg, i, j).none()) { dgdp_sg[i][j] = outArgs.get_DgDp_sg(i,j); if (dgdp_sg[i][j].getMultiVector() != Teuchos::null) dgdp_sg[i][j].getMultiVector()->init(0.0); else if (dgdp_sg[i][j].getLinearOp() != Teuchos::null) dgdp_sg[i][j].getLinearOp()->init(0.0); } } } if (do_quad) { // Get quadrature data const Teuchos::Array< Teuchos::Array<double> >& quad_points = quad->getQuadPoints(); const Teuchos::Array<double>& quad_weights = quad->getQuadWeights(); const Teuchos::Array< Teuchos::Array<double> > & quad_values = quad->getBasisAtQuadPoints(); const Teuchos::Array<double>& basis_norms = basis->norm_squared(); // Perform integrations for (int qp=0; qp<quad_points.size(); qp++) { // StieltjesPCEBasis can introduce quadrature points with zero weight // Don't do those evaluations, since the model might not like the // quadrature points (i.e., zero) if (quad_weights[qp] == 0.0) continue; { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR_DIFF("Stokhos: SGQuadModelEvaluator -- Polynomial Evaluation", PolyEvaluation); #endif // Evaluate inputs at quadrature points if (x_sg != Teuchos::null) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- X Evaluation"); #endif x_sg->evaluate(quad_values[qp], *x_qp); me_inargs.set_x(x_qp); } if (x_dot_sg != Teuchos::null) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- X_dot Evaluation"); #endif x_dot_sg->evaluate(quad_values[qp], *x_dot_qp); me_inargs.set_x_dot(x_qp); } for (int i=0; i<num_p; i++) { if (p_sg[i] != Teuchos::null) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- P Evaluation"); #endif p_sg[i]->evaluate(quad_values[qp], *(p_qp[i])); me_inargs.set_p(i, p_qp[i]); } } if (f_sg != Teuchos::null) me_outargs.set_f(f_qp); if (W_sg != Teuchos::null) me_outargs.set_W(W_qp); for (int i=0; i<num_p; i++) { if (!dfdp_sg[i].isEmpty()) me_outargs.set_DfDp(i, dfdp_qp[i]); } for (int i=0; i<num_g; i++) { if (g_sg[i] != Teuchos::null) me_outargs.set_g(i, g_qp[i]); if (!dgdx_dot_sg[i].isEmpty()) me_outargs.set_DgDx_dot(i, dgdx_dot_qp[i]); if (!dgdx_sg[i].isEmpty()) me_outargs.set_DgDx(i, dgdx_qp[i]); for (int j=0; j<num_p; j++) if (!dgdp_sg[i][j].isEmpty()) me_outargs.set_DgDp(i, j, dgdp_qp[i][j]); } } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- Model Evaluation"); #endif // Evaluate model at quadrature points me->evalModel(me_inargs, me_outargs); } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR_DIFF( "Stokhos: SGQuadModelEvaluator -- Polynomial Integration", Integration); #endif // Sum in results if (f_sg != Teuchos::null) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- F Integration"); #endif f_sg->sumIntoAllTerms(quad_weights[qp], quad_values[qp], basis_norms, *f_qp); } if (W_sg != Teuchos::null) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- W Integration"); #endif W_sg->sumIntoAllTerms(quad_weights[qp], quad_values[qp], basis_norms, *W_qp); } for (int j=0; j<num_p; j++) { if (!dfdp_sg[j].isEmpty()) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR( "Stokhos: SGQuadModelEvaluator -- df/dp Integration"); #endif if (dfdp_sg[j].getMultiVector() != Teuchos::null) { dfdp_sg[j].getMultiVector()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dfdp_qp[j].getMultiVector())); } else if (dfdp_sg[j].getLinearOp() != Teuchos::null) { dfdp_sg[j].getLinearOp()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dfdp_qp[j].getLinearOp())); } } } for (int i=0; i<num_g; i++) { if (g_sg[i] != Teuchos::null) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: SGQuadModelEvaluator -- G Integration"); #endif g_sg[i]->sumIntoAllTerms(quad_weights[qp], quad_values[qp], basis_norms, *g_qp[i]); } if (!dgdx_dot_sg[i].isEmpty()) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR( "Stokhos: SGQuadModelEvaluator -- dg/dx_dot Integration"); #endif if (dgdx_dot_sg[i].getMultiVector() != Teuchos::null) { dgdx_dot_sg[i].getMultiVector()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dgdx_dot_qp[i].getMultiVector())); } else if (dgdx_dot_sg[i].getLinearOp() != Teuchos::null) { dgdx_dot_sg[i].getLinearOp()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dgdx_dot_qp[i].getLinearOp())); } } if (!dgdx_sg[i].isEmpty()) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR( "Stokhos: SGQuadModelEvaluator -- dg/dx Integration"); #endif if (dgdx_sg[i].getMultiVector() != Teuchos::null) { dgdx_sg[i].getMultiVector()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dgdx_qp[i].getMultiVector())); } else if (dgdx_sg[i].getLinearOp() != Teuchos::null) { dgdx_sg[i].getLinearOp()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dgdx_qp[i].getLinearOp())); } } for (int j=0; j<num_p; j++) { if (!dgdp_sg[i][j].isEmpty()) { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR( "Stokhos: SGQuadModelEvaluator -- dg/dp Integration"); #endif if (dgdp_sg[i][j].getMultiVector() != Teuchos::null) { dgdp_sg[i][j].getMultiVector()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dgdp_qp[i][j].getMultiVector())); } else if (dgdp_sg[i][j].getLinearOp() != Teuchos::null) { dgdp_sg[i][j].getLinearOp()->sumIntoAllTerms( quad_weights[qp], quad_values[qp], basis_norms, *(dgdp_qp[i][j].getLinearOp())); } } } } } } } else { // Compute the non-SG functions me->evalModel(me_inargs, me_outargs); } }
void Stokhos::QuadOrthogPolyExpansion<int, float, Stokhos::CUDAStorage<int, float> >:: binary_op(const FuncT& func, OrthogPolyApprox<int, float, CUDAStorage<int,float> >& c, const OrthogPolyApprox<int, float, CUDAStorage<int,float> >& a, const OrthogPolyApprox<int, float, CUDAStorage<int,float> >& b) { int pa = a.size(); int pb = b.size(); int pc; if (pa == 1 && pb == 1) pc = 1; else pc = sz; if (c.size() != pc) c.resize(pc); if (pc == 1) { c[0] = func(a[0], b[0]); return; } float *qv_ptr = thrust::raw_pointer_cast(qv.data()); float *sqv_ptr = thrust::raw_pointer_cast(sqv.data()); const float *a_ptr = thrust::raw_pointer_cast(a.coeff()); const float *b_ptr = thrust::raw_pointer_cast(b.coeff()); float *c_ptr = thrust::raw_pointer_cast(c.coeff()); float *avals_ptr = thrust::raw_pointer_cast(avals.data()); float *bvals_ptr = thrust::raw_pointer_cast(bvals.data()); float *fvals_ptr = thrust::raw_pointer_cast(fvals.data()); { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::QuadExp --Binary Polynomial Evaluation"); #endif // Evaluate input cublasSgemv('T', pa, nqp, 1.0, qv_ptr, sz, a_ptr, 1, 0.0, avals_ptr, 1); cublasSgemv('T', pb, nqp, 1.0, qv_ptr, sz, b_ptr, 1, 0.0, bvals_ptr, 1); } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::QuadExp -- Binary Function Evaluation"); #endif // Evaluate function thrust::transform(avals.begin(), avals.end(), bvals.begin(), fvals.begin(), func); } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::QuadExp -- Binary Polynomial Integration"); #endif // Integrate cublasSgemv('N', pc, nqp, 1.0, sqv_ptr, sz, fvals_ptr, 1, 0.0, c_ptr, 1); } }
void Stokhos::QuadOrthogPolyExpansion<int, float, Stokhos::CUDAStorage<int,float> >:: nary_op(const FuncT& func, OrthogPolyApprox<int, float, Stokhos::CUDAStorage<int,float> >& c, const OrthogPolyApprox<int, float, Stokhos::CUDAStorage<int,float> >** na) { const int N = FuncT::N; bool is_constant = true; for (int i=0; i<N; i++) { if (na[i]->size() > 1) { is_constant = false; break; } } int pc; if (is_constant) pc = 1; else pc = sz; if (c.size() != pc) c.resize(pc); if (pc == 1) { float val[N]; for (int i=0; i<N; i++) val[i] = (*na[i])[0]; c[0] = func(val); return; } if (N >= navals.size()) navals.resize(N+1); if (navals[N].size() != N) { navals[N].resize(N); for (int i=0; i<N; i++) navals[N][i].resize(nqp); } float *qv_ptr = thrust::raw_pointer_cast(qv.data()); float *sqv_ptr = thrust::raw_pointer_cast(sqv.data()); float *c_ptr = thrust::raw_pointer_cast(c.coeff()); float *fvals_ptr = thrust::raw_pointer_cast(fvals.data()); { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::QuadExp -- N(" << N << ")-ary Polynomial Evaluation"); #endif // Evaluate input for (int i=0; i<N; i++) { int pa = na[i]->size(); const float *na_ptr = thrust::raw_pointer_cast(na[i]->coeff()); float *navals_ptr = thrust::raw_pointer_cast(navals[N][i].data()); cublasSgemv('T', pa, nqp, 1.0, qv_ptr, sz, na_ptr, 1, 0.0, navals_ptr, 1); } } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::QuadExp -- N(" << N << ")-ary Function Evaluation"); #endif // Evaluate function thrust::transform( thrust::make_zip_iterator(make_tuple_N<N,navals_type>::begin(navals[N])), thrust::make_zip_iterator(make_tuple_N<N,navals_type>::end(navals[N])), fvals.begin(), func); } { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos::QuadExp -- N(" << N << ")-ary Polynomial Integration"); #endif // Integrate cublasSgemv('N', pc, nqp, 1.0, sqv_ptr, sz, fvals_ptr, 1, 0.0, c_ptr, 1); } }
Stokhos::AnisoSparseGridQuadrature<ordinal_type, value_type>:: AnisoSparseGridQuadrature( const Teuchos::RCP<const ProductBasis<ordinal_type,value_type> >& product_basis, ordinal_type sparse_grid_level, value_type dim_weights[]) : coordinate_bases(product_basis->getCoordinateBases()) { TEUCHOS_FUNC_TIME_MONITOR("Stokhos::AnisoSparseGridQuadrature -- Quad Grid Generation"); ordinal_type d = product_basis->dimension(); ordinal_type p = product_basis->order(); ordinal_type sz = product_basis->size(); ordinal_type level = sparse_grid_level; // Mike's heuristic formula for computing the level if (level == 0) { level = static_cast<ordinal_type>(std::ceil(0.5*(p+d-1))); if (level < d) level = p; } std::cout << "Sparse grid level = " << level << std::endl; // Compute quad points, weights, values Teuchos::Array<int> rules(d), growthRules(d); Teuchos::Array< void (*) ( int order, int dim, double x[] ) > compute1DPoints(d); Teuchos::Array< void (*) ( int order, int dim, double w[] ) > compute1DWeights(d); for (ordinal_type i=0; i<d; i++) { compute1DPoints[i] = &(getMyPoints); compute1DWeights[i] = &(getMyWeights); rules[i] = coordinate_bases[i]->getSparseGridRule(); growthRules[i] = coordinate_bases[i]->getSparseGridGrowthRule(); } // Set the static sparse grid quadrature pointer to this // (this will cause a conflict if another sparse grid quadrature object // is trying to access the VPISparseGrid library, but that's all we can // do at this point). sgq = this; int num_total_pts = webbur::sandia_sgmga_size_total(d,&dim_weights[0],level,&rules[0], &growthRules[0]); ordinal_type ntot = webbur::sandia_sgmga_size(d,&dim_weights[0],level,&rules[0], &compute1DPoints[0], 1e-15,&growthRules[0]); Teuchos::Array<int> sparse_order(ntot*d); Teuchos::Array<int> sparse_index(ntot*d); Teuchos::Array<int> sparse_unique_index(num_total_pts); quad_points.resize(ntot); quad_weights.resize(ntot); quad_values.resize(ntot); Teuchos::Array<value_type> gp(ntot*d); webbur::sandia_sgmga_unique_index(d, &dim_weights[0], level, &rules[0], &compute1DPoints[0], 1e-15, ntot, num_total_pts, &growthRules[0], &sparse_unique_index[0] ); webbur::sandia_sgmga_index(d, &dim_weights[0], level, &rules[0], ntot, num_total_pts, &sparse_unique_index[0], &growthRules[0], &sparse_order[0], &sparse_index[0]); webbur::sandia_sgmga_weight(d,&dim_weights[0],level, &rules[0], &compute1DWeights[0], ntot, num_total_pts, &sparse_unique_index[0], &growthRules[0], &quad_weights[0]); webbur::sandia_sgmga_point(d, &dim_weights[0], level, &rules[0], &compute1DPoints[0], ntot, &sparse_order[0], &sparse_index[0], &growthRules[0], &gp[0]); for (ordinal_type i=0; i<ntot; i++) { quad_values[i].resize(sz); quad_points[i].resize(d); for (ordinal_type j=0; j<d; j++) quad_points[i][j] = gp[i*d+j]; product_basis->evaluateBases(quad_points[i], quad_values[i]); } std::cout << "Number of quadrature points = " << ntot << std::endl; }
int Stokhos::ApproxGaussSeidelPreconditioner:: ApplyInverse(const Epetra_MultiVector& Input, Epetra_MultiVector& Result) const { #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total Approximate Gauss-Seidel Time"); #endif // We have to be careful if Input and Result are the same vector. // If this is the case, the only possible solution is to make a copy const Epetra_MultiVector *input = &Input; bool made_copy = false; if (Input.Values() == Result.Values()) { input = new Epetra_MultiVector(Input); made_copy = true; } int m = input->NumVectors(); if (mat_vec_tmp == Teuchos::null || mat_vec_tmp->NumVectors() != m) mat_vec_tmp = Teuchos::rcp(new Epetra_MultiVector(*base_map, m)); if (rhs_block == Teuchos::null || rhs_block->NumVectors() != m) rhs_block = Teuchos::rcp(new EpetraExt::BlockMultiVector(*base_map, *sg_map, m)); // Extract blocks EpetraExt::BlockMultiVector input_block(View, *base_map, *input); EpetraExt::BlockMultiVector result_block(View, *base_map, Result); result_block.PutScalar(0.0); int k_limit = sg_poly->size(); if (only_use_linear) k_limit = sg_poly->basis()->dimension() + 1; const Teuchos::Array<double>& norms = sg_basis->norm_squared(); rhs_block->Update(1.0, input_block, 0.0); for (Cijk_type::i_iterator i_it=Cijk->i_begin(); i_it!=Cijk->i_end(); ++i_it) { int i = index(i_it); Teuchos::RCP<Epetra_MultiVector> res_i = result_block.GetBlock(i); { // Apply deterministic preconditioner #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total AGS Deterministic Preconditioner Time"); #endif mean_prec->ApplyInverse(*(rhs_block->GetBlock(i)), *res_i); } int i_gid = epetraCijk->GRID(i); for (Cijk_type::ik_iterator k_it = Cijk->k_begin(i_it); k_it != Cijk->k_end(i_it); ++k_it) { int k = index(k_it); if (k!=0 && k<k_limit) { bool do_mat_vec = false; for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_it); ++j_it) { int j = index(j_it); int j_gid = epetraCijk->GCID(j); if (j_gid > i_gid) { bool on_proc = epetraCijk->myGRID(j_gid); if (on_proc) { do_mat_vec = true; break; } } } if (do_mat_vec) { (*sg_poly)[k].Apply(*res_i, *mat_vec_tmp); for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_it); ++j_it) { int j = index(j_it); int j_gid = epetraCijk->GCID(j); double c = value(j_it); if (scale_op) { if (useTranspose) c /= norms[i_gid]; else c /= norms[j_gid]; } if (j_gid > i_gid) { bool on_proc = epetraCijk->myGRID(j_gid); if (on_proc) { rhs_block->GetBlock(j)->Update(-c, *mat_vec_tmp, 1.0); } } } } } } } // For symmetric Gauss-Seidel if (symmetric) { for (Cijk_type::i_reverse_iterator i_it= Cijk->i_rbegin(); i_it!=Cijk->i_rend(); ++i_it) { int i = index(i_it); Teuchos::RCP<Epetra_MultiVector> res_i = result_block.GetBlock(i); { // Apply deterministic preconditioner #ifdef STOKHOS_TEUCHOS_TIME_MONITOR TEUCHOS_FUNC_TIME_MONITOR("Stokhos: Total AGS Deterministic Preconditioner Time"); #endif mean_prec->ApplyInverse(*(rhs_block->GetBlock(i)), *res_i); } int i_gid = epetraCijk->GRID(i); for (Cijk_type::ik_iterator k_it = Cijk->k_begin(i_it); k_it != Cijk->k_end(i_it); ++k_it) { int k = index(k_it); if (k!=0 && k<k_limit) { bool do_mat_vec = false; for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_it); ++j_it) { int j = index(j_it); int j_gid = epetraCijk->GCID(j); if (j_gid < i_gid) { bool on_proc = epetraCijk->myGRID(j_gid); if (on_proc) { do_mat_vec = true; break; } } } if (do_mat_vec) { (*sg_poly)[k].Apply(*res_i, *mat_vec_tmp); for (Cijk_type::ikj_iterator j_it = Cijk->j_begin(k_it); j_it != Cijk->j_end(k_it); ++j_it) { int j = index(j_it); int j_gid = epetraCijk->GCID(j); double c = value(j_it); if (scale_op) c /= norms[j_gid]; if (j_gid < i_gid) { bool on_proc = epetraCijk->myGRID(j_gid); if (on_proc) { rhs_block->GetBlock(j)->Update(-c, *mat_vec_tmp, 1.0); } } } } } } } } if (made_copy) delete input; return 0; }