//---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( OperatorTools, file_test ) { Epetra_SerialComm comm; Teuchos::RCP<Epetra_CrsMatrix> A; EpetraExt::readEpetraLinearSystem( "In_nos1.mtx", comm, &A ); Epetra_Vector scaling_vec( A->RowMap() ) ; A->InvRowSums(scaling_vec); A->RightScale(scaling_vec); Teuchos::RCP<Epetra_Vector> bvec = Teuchos::rcp( new Epetra_Vector( A->RowMap(), false ) ); bvec->Random(); Teuchos::RCP<Epetra_Vector> xvec = Teuchos::rcp( new Epetra_Vector( A->RowMap(), false ) ); xvec->Random(); Teuchos::RCP<Epetra_LinearProblem> linear_problem = Teuchos::rcp( new Epetra_LinearProblem( A.getRawPtr(), xvec.getRawPtr(), bvec.getRawPtr() ) ); HMCSA::JacobiPreconditioner preconditioner( linear_problem ); preconditioner.precondition(); Teuchos::RCP<Epetra_CrsMatrix> precond_A = preconditioner.getOperator(); double spec_rad_precond = HMCSA::OperatorTools::spectralRadius( precond_A ); std::cout << "Preconditioned Operator Spectral Radius: " << spec_rad_precond << std::endl; }
void PreconditionerBlockMS<space_type>::init( void ) { if( Environment::worldComm().isMasterRank() ) std::cout << "Init preconditioner blockms\n"; LOG(INFO) << "Init ...\n"; tic(); BoundaryConditions M_bc = M_model.boundaryConditions(); LOG(INFO) << "Create sub Matrix\n"; map_vector_field<FEELPP_DIM,1,2> m_dirichlet_u { M_bc.getVectorFields<FEELPP_DIM> ( "u", "Dirichlet" ) }; map_scalar_field<2> m_dirichlet_p { M_bc.getScalarFields<2> ( "phi", "Dirichlet" ) }; /* * AA = [[ A - k^2 M, B^t], * [ B , 0 ]] * We need to extract A-k^2 M and add it M to form A+(1-k^2) M = A+g M */ // Is the zero() necessary ? M_11->zero(); this->matrix()->updateSubMatrix(M_11, M_Vh_indices, M_Vh_indices, false); // M_11 = A-k^2 M LOG(INFO) << "Use relax = " << M_relax << std::endl; M_11->addMatrix(M_relax,M_mass); // A-k^2 M + M_relax*M = A+(M_relax-k^2) M auto f2A = form2(_test=M_Vh, _trial=M_Vh,_matrix=M_11); auto f1A = form1(_test=M_Vh); for(auto const & it : m_dirichlet_u ) f2A += on(_range=markedfaces(M_Vh->mesh(),it.first), _expr=it.second,_rhs=f1A, _element=u, _type="elimination_symmetric"); /* * Rebuilding sub-backend */ backend(_name=M_prefix_11, _rebuild=true); backend(_name=M_prefix_22, _rebuild=true); // We have to set the G, Px,Py,Pz or X,Y,Z matrices to AMS if(soption(_name="pc-type", _prefix=M_prefix_11) == "ams") { #if FEELPP_DIM == 3 initAMS(); { if(boption(_name="setAlphaBeta",_prefix=M_prefix_11)) { auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")), _backend=backend(_name=M_prefix_11), _prefix=M_prefix_11, _matrix=M_11 ); prec->setMatrix(M_11); prec->attachAuxiliarySparseMatrix("a_alpha",M_a_alpha); prec->attachAuxiliarySparseMatrix("a_beta",M_a_beta); } } #else std::cerr << "ams preconditioner is not interfaced in two dimensions\n"; #endif } toc("[PreconditionerBlockMS] Init",FLAGS_v>0); LOG(INFO) << "Init done\n"; }
VectorType solve(MatrixType const & system_matrix, VectorType const & rhs, viennashe::solvers::linear_solver_config const & config, viennashe::solvers::serial_linear_solver_tag ) { typedef typename VectorType::value_type NumericT; // // Step 1: Convert data to ViennaCL types: // viennacl::compressed_matrix<NumericT> A(system_matrix.size1(), system_matrix.size2()); viennacl::vector<NumericT> b(system_matrix.size1()); viennacl::fast_copy(&(rhs[0]), &(rhs[0]) + rhs.size(), b.begin()); detail::copy(system_matrix, A); // // Step 2: Setup preconditioner and run solver // log::info<log_linear_solver>() << "* solve(): Computing preconditioner (single-threaded)... " << std::endl; //viennacl::linalg::ilut_tag precond_tag(config.ilut_entries(), // config.ilut_drop_tolerance()); viennacl::linalg::ilu0_tag precond_tag; viennacl::linalg::ilu0_precond<viennacl::compressed_matrix<NumericT> > preconditioner(A, precond_tag); log::info<log_linear_solver>() << "* solve(): Solving system (single-threaded)... " << std::endl; viennacl::linalg::bicgstab_tag solver_tag(config.tolerance(), config.max_iters()); //log::debug<log_linear_solver>() << "Compressed matrix: " << system_matrix << std::endl; //log::debug<log_linear_solver>() << "Compressed rhs: " << rhs << std::endl; viennacl::vector<NumericT> vcl_result = viennacl::linalg::solve(A, b, solver_tag, preconditioner); //log::debug<log_linear_solver>() << "Number of iterations (ILUT): " << solver_tag.iters() << std::endl; // // Step 3: Convert data back: // VectorType result(vcl_result.size()); viennacl::fast_copy(vcl_result.begin(), vcl_result.end(), &(result[0])); viennashe::util::check_vector_for_valid_entries(result); // // As a check, compute residual: // log::info<log_linear_solver>() << "* solve(): residual: " << viennacl::linalg::norm_2(viennacl::linalg::prod(A, vcl_result) - b) / viennacl::linalg::norm_2(b) << " after " << solver_tag.iters() << " iterations." << std::endl; //log::debug<log_linear_solver>() << "SHE result (compressed): " << compressed_result << std::endl; return result; }
void PreconditionerBlockMS<space_type>::initAMS( void ) { M_grad = Grad( _domainSpace=M_Qh, _imageSpace=M_Vh); // This preconditioner is linked to that backend : the backend will // automatically use the preconditioner. auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")), _backend=backend(_name=M_prefix_11), _prefix=M_prefix_11, _matrix=M_11 ); prec->setMatrix(M_11); prec->attachAuxiliarySparseMatrix("G",M_grad.matPtr()); if(boption(M_prefix_11+".useEdge")) { LOG(INFO) << "[ AMS ] : using SetConstantEdgeVector \n"; ozz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(1),cst(0),cst(0))); zoz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(1),cst(0))); zzo.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(0),cst(1))); *M_ozz = ozz; M_ozz->close(); *M_zoz = zoz; M_zoz->close(); *M_zzo = zzo; M_zzo->close(); prec->attachAuxiliaryVector("Px",M_ozz); prec->attachAuxiliaryVector("Py",M_zoz); prec->attachAuxiliaryVector("Pz",M_zzo); } else { LOG(INFO) << "[ AMS ] : using SetCoordinates \n"; X.on(_range=elements(M_Vh->mesh()),_expr=Px()); Y.on(_range=elements(M_Vh->mesh()),_expr=Py()); Z.on(_range=elements(M_Vh->mesh()),_expr=Pz()); *M_X = X; M_X->close(); *M_Y = Y; M_Y->close(); *M_Z = Z; M_Z->close(); prec->attachAuxiliaryVector("X",M_X); prec->attachAuxiliaryVector("Y",M_Y); prec->attachAuxiliaryVector("Z",M_Z); } }
TEUCHOS_UNIT_TEST( MCSA, one_step_solve_test) { int N = 100; int problem_size = N*N; // Build the diffusion operator. double bc_val = 10.0; double dx = 0.01; double dy = 0.01; double dt = 0.01; double alpha = 0.01; HMCSA::DiffusionOperator diffusion_operator( 5, HMCSA::HMCSA_DIRICHLET, HMCSA::HMCSA_DIRICHLET, HMCSA::HMCSA_DIRICHLET, HMCSA::HMCSA_DIRICHLET, bc_val, bc_val, bc_val, bc_val, N, N, dx, dy, dt, alpha ); Teuchos::RCP<Epetra_CrsMatrix> A = diffusion_operator.getCrsMatrix(); Epetra_Map map = A->RowMap(); // Solution Vectors. std::vector<double> x_vector( problem_size ); Epetra_Vector x( View, map, &x_vector[0] ); std::vector<double> x_aztec_vector( problem_size ); Epetra_Vector x_aztec( View, map, &x_aztec_vector[0] ); // Build source - set intial and Dirichlet boundary conditions. std::vector<double> b_vector( problem_size, 1.0 ); int idx; for ( int j = 1; j < N-1; ++j ) { int i = 0; idx = i + j*N; b_vector[idx] = bc_val; } for ( int j = 1; j < N-1; ++j ) { int i = N-1; idx = i + j*N; b_vector[idx] = bc_val; } for ( int i = 0; i < N; ++i ) { int j = 0; idx = i + j*N; b_vector[idx] = bc_val; } for ( int i = 0; i < N; ++i ) { int j = N-1; idx = i + j*N; b_vector[idx] = bc_val; } Epetra_Vector b( View, map, &b_vector[0] ); // MCSA Linear problem. Teuchos::RCP<Epetra_LinearProblem> linear_problem = Teuchos::rcp( new Epetra_LinearProblem( A.getRawPtr(), &x, &b ) ); // MCSA Jacobi precondition. Teuchos::RCP<Epetra_CrsMatrix> H = buildH( A ); double spec_rad_H = HMCSA::OperatorTools::spectralRadius( H ); std::cout << std::endl << std::endl << "---------------------" << std::endl << "Iteration matrix spectral radius: " << spec_rad_H << std::endl; HMCSA::JacobiPreconditioner preconditioner( linear_problem ); preconditioner.precondition(); H = buildH( preconditioner.getOperator() ); double spec_rad_precond_H = HMCSA::OperatorTools::spectralRadius( H ); std::cout << "Preconditioned iteration matrix spectral radius: " << spec_rad_precond_H << std::endl << "---------------------" << std::endl; }
int main(int argc, char* argv[]) { // Initialization of the network, the communicator and the allocation of // the GPU is done as in previous tutorials. agile::NetworkEnvironment environment(argc, argv); typedef agile::GPUCommunicator<unsigned, float, float> communicator_type; communicator_type com; com.allocateGPU(); agile::GPUEnvironment::printInformation(std::cout); std::cout << std::endl; // We are interested in solving the linear problem \f$ Ax = y \f$, with a // given matrix \f$ A \f$ and a right-hand side vector \f$ y \f$. The unknown // is the vector \f$ x \f$. // Now, we can generate a matrix that shall be inverted (actually we do not // invert the matrix but use the CG algorithm). Note that CG requires a // symmetric positive definite (SPD) matrix and it is not too trivial to // write down a SPD matrix. If you fail to provide a SPD matrix to the CG // algorithm there is no guarantee that it will converge. You might be lucky, // you might be not... const unsigned SIZE = 20; float A_host[SIZE][SIZE]; for (unsigned row = 0; row < SIZE; ++row) for (unsigned column = 0; column <= row; ++column) { A_host[row][column] = (float(SIZE) - float(row) + float(SIZE) / 2.0) * (float(column) + 1.0); A_host[column][row] = A_host[row][column]; if (row == column) A_host[row][column] = 2.0 * float(SIZE) + float(row) + float(column); } // The matrix is still in the host's memory and has to be transfered to the // GPU. This is done automatically by the constructor of \p GPUMatrixPitched. agile::GPUMatrixPitched<float> A(SIZE, SIZE, (float*)A_host); // Next we need a reference solution. We can create any vector we like at // this place. std::vector<float> x_reference_host(SIZE); for (unsigned counter = 0; counter < SIZE; ++counter) x_reference_host[counter] = float(SIZE) - float(counter) + float(SIZE/3); // This vector has to be transfered to the GPU memory too. For vectors, this // can be achieved by the member function \p assignFromHost. agile::GPUVector<float> x_reference; x_reference.assignFromHost(x_reference_host.begin(), x_reference_host.end()); // We wrap the GPU matrix from above into a forward operator called // \p ForwardMatrix. Forward operators are simply objects that implement // the parenthesis-operator \p operator() which takes an // \p accumulated vector and returns a \p distributed one. In all other // respects the operator is a black box for us. // The \p ForwardMatrix operator requires a reference to the communicator // when constructing the object so that it has access to the network. typedef agile::ForwardMatrix<communicator_type, agile::GPUMatrixPitched<float> > forward_type; forward_type forward(com, A); // What we also want to use a preconditioner, which means that we change from // the original problem \f$ Ax = y \f$ to the equivalent one // \f$ PAx = Py \f$, where \f$ P \f$ is a preconditioner. The rationale is // that most often the matrix \f$ A \f$ is ill-conditioned and the CG algorithm // does not converge properly at all or it needs many iterations. The use of // a preconditioner makes the whole system better conditioned. The simplest // choice is to use the identity \f$ P = I \f$ (which means no preconditioning // at all). The best choice would be \f$ P = A^{-1} \f$ as we would have the // solution for \f$ x \f$ in the first step already (but then we need again // to find the inverse of \f$ A \f$ which we wanted to avoid). An // 'intermediate' possibility is to take \f$ P = diag(A)^{-1} \f$ which is // easy and fast to invert and gives better results than the identity. // A preconditioner belongs to the inverse operator. All inverse operators // implement a parenthesis-operator which takes a \p distributed vector // as input and returns an \p accumulated one (opposite to the forward // operators, thus). #if JACOBI_PRECONDITIONER typedef agile::JacobiPreconditioner<communicator_type, float> preconditioner_type; std::vector<float> diagonal(SIZE); for (unsigned row = 0; row < SIZE; ++row) diagonal[row] = A_host[row][row]; preconditioner_type preconditioner(com, diagonal); #else typedef agile::InverseIdentity<communicator_type> preconditioner_type; preconditioner_type preconditioner(com); #endif // The last operator needed is a measure. A measure operator has again // a parenthesis-operator. This timeis takes an \p accumulated vector as first // input and a \p distributed one as second input and returns a scalar // measuring somehow the size of the vectors. An example is the scalar // product operator. typedef agile::ScalarProductMeasure<communicator_type> measure_type; measure_type scalar_product(com); // Finally, generate the PCG solver. It needs the absolute and relative // tolerances as input so that it knows when the solution is good enough for // our purposes. Furthermore it requires the maximum amount of iterations // after which it simply capitulates without having found a solution. const double REL_TOLERANCE = 1e-12; const double ABS_TOLERANCE = 1e-6; const unsigned MAX_ITERATIONS = 100; agile::PreconditionedConjugateGradient<communicator_type, forward_type, preconditioner_type, measure_type> pcg(com, forward, preconditioner, scalar_product, REL_TOLERANCE, ABS_TOLERANCE, MAX_ITERATIONS); // What we have not generated, yet, is the right hand side \f$ y \f$. This is // simply one call to our forward operator. agile::GPUVector<float> y(SIZE); forward(x_reference, y); // We need one more vector to hold the result of the CG algorithm. Note that // we also supply the initial guess for the solution via this vector. agile::GPUVector<float> x(SIZE); // Finally, we have constructed, initialized, wrapped... everything. The only // thing left to do is to call the CG operator. pcg(y, x); // Print some statistics (and hope that the operator actually converged). if (pcg.convergence()) std::cout << "CG converged in "; else std::cout << "Error: CG did not converge in "; std::cout << pcg.getIteration() + 1 << " iterations." << std::endl; std::cout << "Initial residual = " << pcg.getRho0() << std::endl; std::cout << "Final residual = " << pcg.getRho() << std::endl; std::cout << "Ratio rho_k / rho_0 = " << pcg.getRho() / pcg.getRho0() << std::endl; // As the vectors in this example were quite small we can even print them to // standard output. std::cout << "Reference: " << std::endl << " "; for (unsigned counter = 0; counter < x_reference_host.size(); ++counter) std::cout << x_reference_host[counter] << " "; std::cout << std::endl; // The solution is still on the GPU and has to be transfered to the CPU memory. // This is accomplished using \p copyToHost. std::vector<float> x_host; x.copyToHost(x_host); // Output the solution, too. std::cout << "CG solution: " << std::endl << " "; for (unsigned counter = 0; counter < x_host.size(); ++counter) std::cout << x_host[counter] << " "; std::cout << std::endl; // Finally, we also compute the difference between the reference solution and // the true solution (of course, we do this on the GPU). agile::GPUVector<float> difference(SIZE); subVector(x_reference, x, difference); // To measure the distance, we use the scalar product measure we have // introduced above. Note, that this operator wants the first vector in // accumulated format and the second one in distributed format. The solution // we got from the CG algorithm is accumulated (because CG is an inverse // operator). This means, we have to distribute the solution to have mixed // formats. agile::GPUVector<float> difference_dist(difference); com.distribute(difference_dist); std::cout << "L2 of difference: " << std::sqrt(std::abs(scalar_product(difference, difference_dist))) << std::endl; // So, that's it. return 0; }
void solve_intern(MatrixT& A, VectorT& b, VectorT& x, LinerSolverT& linear_solver) { viennafvm::Timer timer; if(pc_id_ == viennafvm::linsolv::viennacl::preconditioner_ids::none) { // std::cout << "using pc: none .. " << std::endl; last_pc_time_ = 0.0; timer.start(); x = ::viennacl::linalg::solve(A, b, linear_solver); last_solver_time_ = timer.get(); } else if(pc_id_ == viennafvm::linsolv::viennacl::preconditioner_ids::ilu0) { // std::cout << "using pc: ilu0 .. " << std::endl; ::viennacl::linalg::ilu0_tag pc_config; pc_config.use_level_scheduling(false); timer.start(); ::viennacl::linalg::ilu0_precond<MatrixT> preconditioner(A, pc_config); last_pc_time_ = timer.get(); timer.start(); x = ::viennacl::linalg::solve(A, b, linear_solver, preconditioner); last_solver_time_ = timer.get(); } else if(pc_id_ == viennafvm::linsolv::viennacl::preconditioner_ids::ilut) { // std::cout << "using pc: ilut .. " << std::endl; ::viennacl::linalg::ilut_tag pc_config; pc_config.set_drop_tolerance(1.0e-4); pc_config.set_entries_per_row(40); pc_config.use_level_scheduling(false); timer.start(); ::viennacl::linalg::ilut_precond<MatrixT> preconditioner(A, pc_config); last_pc_time_ = timer.get(); timer.start(); x = ::viennacl::linalg::solve(A, b, linear_solver, preconditioner); last_solver_time_ = timer.get(); } else if(pc_id_ == viennafvm::linsolv::viennacl::preconditioner_ids::block_ilu) { // std::cout << "using pc: block ilu .. " << std::endl; ::viennacl::linalg::ilu0_tag pc_config; pc_config.use_level_scheduling(false); timer.start(); ::viennacl::linalg::block_ilu_precond<MatrixT, ::viennacl::linalg::ilu0_tag> preconditioner(A, pc_config); last_pc_time_ = timer.get(); timer.start(); x = ::viennacl::linalg::solve(A, b, linear_solver, preconditioner); last_solver_time_ = timer.get(); } else if(pc_id_ == viennafvm::linsolv::viennacl::preconditioner_ids::jacobi) { // std::cout << "using pc: jacobi .. " << std::endl; timer.start(); ::viennacl::linalg::jacobi_precond<MatrixT> preconditioner(A, ::viennacl::linalg::jacobi_tag()); last_pc_time_ = timer.get(); timer.start(); x = ::viennacl::linalg::solve(A, b, linear_solver, preconditioner); last_solver_time_ = timer.get(); } else if(pc_id_ == viennafvm::linsolv::viennacl::preconditioner_ids::row_scaling) { // std::cout << "using pc: row_scaling .. " << std::endl; timer.start(); ::viennacl::linalg::row_scaling<MatrixT> preconditioner(A, ::viennacl::linalg::row_scaling_tag()); last_pc_time_ = timer.get(); timer.start(); x = ::viennacl::linalg::solve(A, b, linear_solver, preconditioner); last_solver_time_ = timer.get(); } else { std::cerr << "[ERROR] ViennaFVM::LinearSolver: preconditioner not supported .. " << std::endl; return; } last_iterations_ = linear_solver.iters(); last_error_ = linear_solver.error(); }
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { mwSize n; float *b , *x; ldl_p chol; mwSize i; mwIndex *jld; s_hlevel *H; int nlevels; mxArray *C; /* Input validation */ if (nrhs !=2) mexErrMsgTxt("Wrong number of input arguments"); if (!mxIsCell(H_IN)) mexErrMsgTxt("First argument must be a Hierarchy cell"); if (!mxIsSingle(b_IN)) mexErrMsgTxt("Second argument must be a non-sparse single precision vector"); if ( (mxGetN(b_IN)!=1)) mexErrMsgTxt("Second argument must be a column vector"); n = mxGetM(b_IN); nlevels = (int) MAX(mxGetM(H_IN),mxGetN(H_IN)); H = malloc(nlevels*sizeof(s_hlevel)); if (nlevels>1) { C = mxGetCell(H_IN,nlevels-2); H[nlevels-2].islast = (boolean) *(mxGetPr(mxGetField(C,0,"islast"))); if (H[nlevels-2].islast) nlevels = nlevels-1; } for (i=0; i<nlevels; i++) { C = mxGetCell(H_IN,i); H[i].islast = (boolean) *(mxGetPr(mxGetField(C,0,"islast"))); H[i].iterative = (boolean) *(mxGetPr(mxGetField(C,0,"iterative"))); if (i<(nlevels-1)) { H[i].cI = (mIndex *) mxGetPr(mxGetField(C,0,"cI")); H[i].nc = (mSize) *(mxGetPr(mxGetField(C,0,"nc"))); H[i].invD = (float *) mxGetPr(mxGetField(C,0,"invD")); H[i].dc = (boolean) *(mxGetPr(mxGetField(C,0,"dc"))); H[i].repeat = (int) *(mxGetPr(mxGetField(C,0,"repeat"))); H[i].lws1 = (float *) mxGetPr(mxGetField(C,0,"lws1")); H[i].lws2 = (float *) mxGetPr(mxGetField(C,0,"lws2")); H[i].sws1 = (float *) mxGetPr(mxGetField(C,0,"sws1")); H[i].sws2 = (float *) mxGetPr(mxGetField(C,0,"sws2")); H[i].sws3 = (float *) mxGetPr(mxGetField(C,0,"sws3")); } if (i==0) H[i].laplacian = (boolean) *(mxGetPr(mxGetField(C,0,"laplacian"))); H[i].A.a = (float *) mxGetPr(mxGetField(mxGetField(C,0,"A"),0,"a")); H[i].A.ia = (mIndex *) mxGetPr(mxGetField(mxGetField(C,0,"A"),0,"ia")); H[i].A.ja = (mIndex *) mxGetPr(mxGetField(mxGetField(C,0,"A"),0,"ja")); H[i].A.n = (mSize) *(mxGetPr(mxGetField(mxGetField(C,0,"A"),0,"n"))); H[i].A.issym = (boolean) *(mxGetPr(mxGetField(mxGetField(C,0,"A"),0,"issym"))); if (i==(nlevels-1)){ if (!H[i].iterative){ H[i].chol.ld.a = (double *) mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ld"),0,"a")); H[i].chol.ld.ia = (mIndex *) mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ld"),0,"ia")); H[i].chol.ld.ja = (mIndex *) mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ld"),0,"ja")); H[i].chol.ld.n = (mSize ) *(mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ld"),0,"n"))); H[i].chol.ldT.a = (double *) mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ldT"),0,"a")); H[i].chol.ldT.ia = (mIndex *) mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ldT"),0,"ia")); H[i].chol.ldT.ja = (mIndex *) mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ldT"),0,"ja")); H[i].chol.ldT.n = (mSize ) *(mxGetPr(mxGetField(mxGetField(mxGetField(C,0,"chol"),0,"ldT"),0,"n"))); H[i].chol.p = (mIndex *) mxGetPr(mxGetField(mxGetField(C,0,"chol"),0,"p")); H[i].chol.invp = (mIndex *) mxGetPr(mxGetField(mxGetField(C,0,"chol"),0,"invp")); } else { H[i].invD = (float *) mxGetPr(mxGetField(C,0,"invD")); H[i].lws1 = (float *) mxGetPr(mxGetField(C,0,"lws1")); H[i].lws2 = (float *) mxGetPr(mxGetField(C,0,"lws2")); H[i].sws1 = (float *) mxGetPr(mxGetField(C,0,"sws1")); H[i].sws2 = (float *) mxGetPr(mxGetField(C,0,"sws2")); H[i].sws3 = (float *) mxGetPr(mxGetField(C,0,"sws3")); } } } b = (float *) mxGetPr(b_IN); x_OUT = mxCreateNumericArray(1,&n,mxSINGLE_CLASS,mxREAL); x = (float *) mxGetPr(x_OUT); preconditioner( H, b, 0, 1,x); free(H); return; }
TEUCHOS_UNIT_TEST( MCSA, MCSA_test) { int problem_size = 16; Epetra_SerialComm comm; Epetra_Map map( problem_size, 0, comm ); std::vector<double> x_vector( problem_size ); Epetra_Vector x( View, map, &x_vector[0] ); std::vector<double> x_aztec_vector( problem_size ); Epetra_Vector x_aztec( View, map, &x_aztec_vector[0] ); std::vector<double> b_vector( problem_size, 0.4 ); Epetra_Vector b( View, map, &b_vector[0] ); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, map, problem_size ) ); double lower_diag = -0.1; double diag = 2.4; double upper_diag = -0.1; int global_row = 0; int lower_row = 0; int upper_row = 0; for ( int i = 0; i < problem_size; ++i ) { global_row = A->GRID(i); lower_row = i-1; upper_row = i+1; if ( lower_row > -1 ) { A->InsertGlobalValues( global_row, 1, &lower_diag, &lower_row ); } A->InsertGlobalValues( global_row, 1, &diag, &global_row ); if ( upper_row < problem_size ) { A->InsertGlobalValues( global_row, 1, &upper_diag, &upper_row ); } } A->FillComplete(); double spec_rad_A = HMCSA::OperatorTools::spectralRadius( A ); std::cout << std::endl << "Operator spectral radius: " << spec_rad_A << std::endl; Teuchos::RCP<Epetra_LinearProblem> linear_problem = Teuchos::rcp( new Epetra_LinearProblem( A.getRawPtr(), &x, &b ) ); HMCSA::JacobiPreconditioner preconditioner( linear_problem ); preconditioner.precondition(); HMCSA::MCSA mcsa_solver( linear_problem ); mcsa_solver.iterate( 100, 1.0e-8, 100, 1.0e-8 ); std::cout << "MCSA ITERS: " << mcsa_solver.getNumIters() << std::endl; Epetra_LinearProblem aztec_linear_problem( A.getRawPtr(), &x_aztec, &b ); AztecOO aztec_solver( aztec_linear_problem ); aztec_solver.SetAztecOption( AZ_solver, AZ_gmres ); aztec_solver.Iterate( 100, 1.0e-8 ); std::vector<double> error_vector( problem_size ); Epetra_Vector error( View, map, &error_vector[0] ); for (int i = 0; i < problem_size; ++i) { error[i] = x[i] - x_aztec[i]; } double error_norm; error.Norm2( &error_norm ); std::cout << std::endl << "Aztec GMRES vs. MCSA absolute error L2 norm: " << error_norm << std::endl; }
void eqnsys<nr_type_t>::solve_sor (void) { nr_type_t f; int error, conv, i, c, r; int MaxIter = N; // -> less than N^3 operations nr_double_t reltol = 1e-4; nr_double_t abstol = NR_TINY; nr_double_t diff, crit, l = 1, d, s; // ensure that all diagonal values are non-zero ensure_diagonal (); // try to raise diagonal dominance preconditioner (); // decide here about possible convergence if ((crit = convergence_criteria ()) >= 1) { #if DEBUG && 0 logprint (LOG_STATUS, "NOTIFY: convergence criteria: %g >= 1 (%dx%d)\n", crit, N, N); #endif //solve_lu (); //return; } // normalize the equation system to have ones on its diagonal for (r = 0; r < N; r++) { f = A_(r, r); assert (f != 0); // singular matrix for (c = 0; c < N; c++) A_(r, c) /= f; B_(r) /= f; } // the current X vector is a good initial guess for the iteration tvector<nr_type_t> * Xprev = new tvector<nr_type_t> (*X); // start iterating here i = 0; error = 0; do { // compute new solution vector for (r = 0; r < N; r++) { for (f = 0, c = 0; c < N; c++) { if (c < r) f += A_(r, c) * X_(c); else if (c > r) f += A_(r, c) * Xprev->get (c); } X_(r) = (1 - l) * Xprev->get (r) + l * (B_(r) - f); } // check for convergence for (s = 0, d = 0, conv = 1, r = 0; r < N; r++) { diff = abs (X_(r) - Xprev->get (r)); if (diff >= abstol + reltol * abs (X_(r))) { conv = 0; break; } d += diff; s += abs (X_(r)); if (!std::isfinite (diff)) { error++; break; } } if (!error) { // adjust relaxation based on average errors if ((s == 0 && d == 0) || d >= abstol * N + reltol * s) { // values <= 1 -> non-convergence to convergence if (l >= 0.6) l -= 0.1; if (l >= 1.0) l = 1.0; } else { // values >= 1 -> faster convergence if (l < 1.5) l += 0.01; if (l < 1.0) l = 1.0; } } // save last values *Xprev = *X; } while (++i < MaxIter && !conv); delete Xprev; if (!conv || error) { logprint (LOG_ERROR, "WARNING: no convergence after %d sor iterations (l = %g)\n", i, l); solve_lu_crout (); } #if DEBUG && 0 else { logprint (LOG_STATUS, "NOTIFY: sor convergence after %d iterations\n", i); } #endif }
void eqnsys<nr_type_t>::solve_iterative (void) { nr_type_t f; int error, conv, i, c, r; int MaxIter = N; // -> less than N^3 operations nr_double_t reltol = 1e-4; nr_double_t abstol = NR_TINY; nr_double_t diff, crit; // ensure that all diagonal values are non-zero ensure_diagonal (); // try to raise diagonal dominance preconditioner (); // decide here about possible convergence if ((crit = convergence_criteria ()) >= 1) { #if DEBUG && 0 logprint (LOG_STATUS, "NOTIFY: convergence criteria: %g >= 1 (%dx%d)\n", crit, N, N); #endif //solve_lu (); //return; } // normalize the equation system to have ones on its diagonal for (r = 0; r < N; r++) { f = A_(r, r); assert (f != 0); // singular matrix for (c = 0; c < N; c++) A_(r, c) /= f; B_(r) /= f; } // the current X vector is a good initial guess for the iteration tvector<nr_type_t> * Xprev = new tvector<nr_type_t> (*X); // start iterating here i = 0; error = 0; do { // compute new solution vector for (r = 0; r < N; r++) { for (f = 0, c = 0; c < N; c++) { if (algo == ALGO_GAUSS_SEIDEL) { // Gauss-Seidel if (c < r) f += A_(r, c) * X_(c); else if (c > r) f += A_(r, c) * Xprev->get (c); } else { // Jacobi if (c != r) f += A_(r, c) * Xprev->get (c); } } X_(r) = B_(r) - f; } // check for convergence for (conv = 1, r = 0; r < N; r++) { diff = abs (X_(r) - Xprev->get (r)); if (diff >= abstol + reltol * abs (X_(r))) { conv = 0; break; } if (!std::isfinite (diff)) { error++; break; } } // save last values *Xprev = *X; } while (++i < MaxIter && !conv); delete Xprev; if (!conv || error) { logprint (LOG_ERROR, "WARNING: no convergence after %d %s iterations\n", i, algo == ALGO_JACOBI ? "jacobi" : "gauss-seidel"); solve_lu_crout (); } #if DEBUG && 0 else { logprint (LOG_STATUS, "NOTIFY: %s convergence after %d iterations\n", algo == ALGO_JACOBI ? "jacobi" : "gauss-seidel", i); } #endif }
PreconditionerBlockMS<space_type>::PreconditionerBlockMS(space_ptrtype Xh, // (u)x(p) ModelProperties model, // model std::string const& p, // prefix sparse_matrix_ptrtype AA ) // The matrix : M_backend(backend()), // the backend associated to the PC M_Xh( Xh ), M_Vh( Xh->template functionSpace<0>() ), // Potential M_Qh( Xh->template functionSpace<1>() ), // Lagrange M_Vh_indices( M_Vh->nLocalDofWithGhost() ), M_Qh_indices( M_Qh->nLocalDofWithGhost() ), M_uin( M_backend->newVector( M_Vh ) ), M_uout( M_backend->newVector( M_Vh ) ), M_pin( M_backend->newVector( M_Qh ) ), M_pout( M_backend->newVector( M_Qh ) ), U( M_Xh, "U" ), M_mass(M_backend->newMatrix(M_Vh,M_Vh)), M_L(M_backend->newMatrix(M_Qh,M_Qh)), M_er( 1. ), M_model( model ), M_prefix( p ), M_prefix_11( p+".11" ), M_prefix_22( p+".22" ), u(M_Vh, "u"), ozz(M_Vh, "ozz"), zoz(M_Vh, "zoz"), zzo(M_Vh, "zzo"), M_ozz(M_backend->newVector( M_Vh )), M_zoz(M_backend->newVector( M_Vh )), M_zzo(M_backend->newVector( M_Vh )), X(M_Qh, "X"), Y(M_Qh, "Y"), Z(M_Qh, "Z"), M_X(M_backend->newVector( M_Qh )), M_Y(M_backend->newVector( M_Qh )), M_Z(M_backend->newVector( M_Qh )), phi(M_Qh, "phi") { tic(); LOG(INFO) << "[PreconditionerBlockMS] setup starts"; this->setMatrix( AA ); this->setName(M_prefix); /* Indices are need to extract sub matrix */ std::iota( M_Vh_indices.begin(), M_Vh_indices.end(), 0 ); std::iota( M_Qh_indices.begin(), M_Qh_indices.end(), M_Vh->nLocalDofWithGhost() ); M_11 = AA->createSubMatrix( M_Vh_indices, M_Vh_indices, true, true); /* Boundary conditions */ BoundaryConditions M_bc = M_model.boundaryConditions(); map_vector_field<FEELPP_DIM,1,2> m_dirichlet_u { M_bc.getVectorFields<FEELPP_DIM> ( "u", "Dirichlet" ) }; map_scalar_field<2> m_dirichlet_p { M_bc.getScalarFields<2> ( "phi", "Dirichlet" ) }; /* Compute the mass matrix (needed in first block, constant) */ auto f2A = form2(_test=M_Vh, _trial=M_Vh, _matrix=M_mass); auto f1A = form1(_test=M_Vh); f2A = integrate(_range=elements(M_Vh->mesh()), _expr=inner(idt(u),id(u))); // M for(auto const & it : m_dirichlet_u ) { LOG(INFO) << "Applying " << it.second << " on " << it.first << " for "<<M_prefix_11<<"\n"; f2A += on(_range=markedfaces(M_Vh->mesh(),it.first), _expr=it.second,_rhs=f1A, _element=u, _type="elimination_symmetric"); } /* Compute the L (= er * grad grad) matrix (the second block) */ auto f2L = form2(_test=M_Qh,_trial=M_Qh, _matrix=M_L); for(auto it : M_model.materials() ) { f2L += integrate(_range=markedelements(M_Qh->mesh(),marker(it)), _expr=M_er*inner(gradt(phi), grad(phi))); } auto f1LQ = form1(_test=M_Qh); for(auto const & it : m_dirichlet_p) { LOG(INFO) << "Applying " << it.second << " on " << it.first << " for "<<M_prefix_22<<"\n"; f2L += on(_range=markedfaces(M_Qh->mesh(),it.first),_element=phi, _expr=it.second, _rhs=f1LQ, _type="elimination_symmetric"); } if(soption(_name="pc-type", _prefix=M_prefix_11) == "ams") #if FEELPP_DIM == 3 { M_grad = Grad( _domainSpace=M_Qh, _imageSpace=M_Vh); // This preconditioner is linked to that backend : the backend will // automatically use the preconditioner. auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")), _backend=backend(_name=M_prefix_11), _prefix=M_prefix_11, _matrix=M_11 ); prec->setMatrix(M_11); prec->attachAuxiliarySparseMatrix("G",M_grad.matPtr()); if(boption(M_prefix_11+".useEdge")) { LOG(INFO) << "[ AMS ] : using SetConstantEdgeVector \n"; ozz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(1),cst(0),cst(0))); zoz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(1),cst(0))); zzo.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(0),cst(1))); *M_ozz = ozz; M_ozz->close(); *M_zoz = zoz; M_zoz->close(); *M_zzo = zzo; M_zzo->close(); prec->attachAuxiliaryVector("Px",M_ozz); prec->attachAuxiliaryVector("Py",M_zoz); prec->attachAuxiliaryVector("Pz",M_zzo); } else { LOG(INFO) << "[ AMS ] : using SetCoordinates \n"; X.on(_range=elements(M_Vh->mesh()),_expr=Px()); Y.on(_range=elements(M_Vh->mesh()),_expr=Py()); Z.on(_range=elements(M_Vh->mesh()),_expr=Pz()); *M_X = X; M_X->close(); *M_Y = Y; M_Y->close(); *M_Z = Z; M_Z->close(); prec->attachAuxiliaryVector("X",M_X); prec->attachAuxiliaryVector("Y",M_Y); prec->attachAuxiliaryVector("Z",M_Z); } } #else std::cerr << "ams preconditioner is not interfaced in two dimensions\n"; #endif toc( "[PreconditionerBlockMS] setup done ", FLAGS_v > 0 ); }