Dear John,

At a glance I think that the problem could be that you're trying to work to a tolerance of less than the machine tolerance. The smallest difference between two values that can be represented on a standard machine is ~1.1e-16. Although one can store a value smaller than this, it may be that the operations required to solve with the CG method are not able to produce a solution with the end precision that you require and the final residual is tiny but cannot decrease to the margin you want. This would explain why if you raise the tolerance by an order of magnitude then convergence can be achieved - the norm of the schur RHS vector must be very small already.

You can check what the actual value is with the numerical limits call:
#include< limits>
std::numerical_limits<double>::epsilon()

See http://www.cplusplus.com/reference/std/limits/numeric_limits/ , http://www.cplusplus.com/reference/clibrary/cfloat/ for more info.

It is unclear to me as to why the solver wouldn't run to full number of allowed iterations though -- between the CG solver and solver control classes, it doesn't appear as if there is a check/throw for divergence or slow convergence that would stop the solver iterating.

Regards,
J-P

On 20/12/2011 13:15, John Chapman wrote:
Dear deal.ii,

I am having a problem with the CG Solver. Here is a code snippet:

SolverControl solver_control (solution[ts].block(1).size(),1e-8*schur_rhs.l2_norm());

std::cout << "iterations = " << solution[ts].block(1).size() << std::endl;
    std::cout << "tolerance = " << 1e-8*schur_rhs.l2_norm()<<std::endl;

    SolverCG<>  cg (solver_control);

cg.solve (schur_complement, solution[ts].block(1), schur_rhs, preconditioner);

This is the output:

iterations = 48
tolerance = 4.92837e-10

----------------------------------------------------
Exception on processing:
Iterative method reported convergence failure in step 48 with residual 3.18991e-17
Aborting!
----------------------------------------------------

This seems strange as the algorithm is clearly achieving the tolerance. If I reduce the tolerance to 1e-7*schur_rhs.l2_norm() then the algorithm reaches the tolerance in 11 iterations and continues with the code.

Further interesting behaviour is that if I adjust the iterations by hand, e.g., SolverControl solver_control (100,1e-8*schur_rhs.l2_norm()) the code still terminates after 48 iterations (or solution[ts].block(1).size() if the problem size is altered). This is also the case if I just use a default solver_control.

I will post the full solver code below which is based on that of step-21.

Many thanks,

John Chapman



template <int dim>
void TwoPhaseFlowProblem<dim>::solve_velocity_pressure (const unsigned int ts)
{

const InverseMatrix<SparseMatrix<double> > m_inverse(system_matrix.block(0,0));
  // vector size of velocity components
  Vector<double> tmp (solution[ts].block(0).size());
  // vector size of pressure components
  Vector<double> schur_rhs (solution[ts].block(1).size());

  // Solve for pressure using Schur Complement
  {
    m_inverse.vmult (tmp, system_rhs.block(0));
    system_matrix.block(1,0).vmult (schur_rhs, tmp);
    schur_rhs -= system_rhs.block(1);

    SchurComplement schur_complement (system_matrix, m_inverse);

ApproximateSchurComplement approximate_schur_complement (system_matrix);

    InverseMatrix<ApproximateSchurComplement>
                    preconditioner (approximate_schur_complement);

    SolverControl solver_control (solution[ts].block(1).size(),
                                  1e-8*schur_rhs.l2_norm());

std::cout << "iterations = " << solution[ts].block(1).size() << std::endl;
    std::cout << "tolerance = " << 1e-8*schur_rhs.l2_norm()<<std::endl;

    SolverCG<>  cg (solver_control);

cg.solve (schur_complement, solution[ts].block(1), schur_rhs, preconditioner);

    std::cout << "   "
<< solver_control.last_step()
<< " CG Schur complement iterations for pressure." << std::endl;
  }

  // Now the velocity using an inverse
  {
    system_matrix.block(0,1).vmult (tmp, solution[ts].block(1));
    tmp *= -1;
    tmp += system_rhs.block(0);

    m_inverse.vmult (solution[ts].block(0), tmp);
  }

  constraints.distribute (solution[ts]);
}







_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii
_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii

Reply via email to