예제 #1
0
//---------------------------------------------------------------------------//
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);
        }
    }
예제 #5
0
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;
}
예제 #6
0
파일: program.cpp 프로젝트: IMTtugraz/AGILE
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;
}
예제 #7
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();
  }
예제 #8
0
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;

}   
예제 #9
0
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;    
}
예제 #10
0
파일: eqnsys.cpp 프로젝트: FoxMarts/qucs
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
}
예제 #11
0
파일: eqnsys.cpp 프로젝트: FoxMarts/qucs
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
}
예제 #12
0
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 );
}