void
TimeIterationPolicyLinear<mesh_Type, AssemblyPolicy, SolverPolicy>::
iterate ( vectorPtr_Type solution,
          bcContainerPtr_Type bchandler,
          const Real& currentTime )
{
    Real rhsIterNorm ( 0.0 );

    //
    // STEP 1: Updating the system
    //
    displayer().leaderPrint ( "Updating the system... " );
    *M_rhs = 0.0;
    M_systemMatrix.reset ( new matrix_Type ( *M_solutionMap ) );
    AssemblyPolicy::assembleSystem ( M_systemMatrix, M_rhs, solution, SolverPolicy::preconditioner() );
    displayer().leaderPrint ( "done\n" );

    //
    // STEP 2: Applying the boundary conditions
    //
    displayer().leaderPrint ( "Applying BC... " );
    bcManage ( *M_systemMatrix, *M_rhs, *uFESpace()->mesh(), uFESpace()->dof(), *bchandler, uFESpace()->feBd(), 1.0, currentTime );
    M_systemMatrix->globalAssemble();
    displayer().leaderPrint ( "done\n" );

    // Extra information if we want to know the exact residual
    if ( M_computeResidual )
    {
        rhsIterNorm = M_rhs->norm2();
    }

    //
    // STEP 3: Solving the system
    //
    displayer().leaderPrint ( "Solving the system... \n" );
    SolverPolicy::solve ( M_systemMatrix, M_rhs, solution );

    if ( M_computeResidual )
    {
        vector_Type Ax ( solution->map() );
        vector_Type res ( *M_rhs );
        M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() );
        res.epetraVector().Update ( -1, Ax.epetraVector(), 1 );
        Real residual;
        res.norm2 ( &residual );
        residual /= rhsIterNorm;
        displayer().leaderPrint ( "Scaled residual: ", residual, "\n" );
    }
}
示例#2
0
Real
LinearSolver::computeResidual ( vectorPtr_Type solutionPtr )
{
    if ( !M_operator || !M_rhs )
    {
        M_displayer->leaderPrint ( "SLV-  WARNING: LinearSolver can not compute the residual if the operator and the RHS are not set!\n" );
        return -1;
    }

    vector_Type Ax ( solutionPtr->map() );
    vector_Type residual ( *M_rhs );

    M_operator->Apply ( solutionPtr->epetraVector(), Ax.epetraVector() );

    residual.epetraVector().Update ( 1, Ax.epetraVector(), -1 );

    Real residualNorm;

    residual.norm2 ( &residualNorm );

    return residualNorm;
}
void
TimeIterationPolicyNonlinear<mesh_Type, AssemblyPolicy, SolverPolicy>::
iterate ( vectorPtr_Type solution,
          bcContainerPtr_Type bchandler,
          const Real& currentTime )
{
    int subiter = 0;

    Real normRhs ( 0.0 );
    Real nonLinearResidual ( 0.0 );
    Real rhsIterNorm ( 0.0 );

    do
    {
        //
        // STEP 1: Updating the system
        //
        displayer().leaderPrint ( "Updating the system... " );
        *M_rhs = 0.0;
        M_systemMatrix.reset ( new matrix_Type ( *M_solutionMap ) );
        AssemblyPolicy::assembleSystem ( M_systemMatrix, M_rhs, solution, SolverPolicy::preconditioner() );
        displayer().leaderPrint ( "done\n" );

        //
        // STEP 2: Applying the boundary conditions
        //
        displayer().leaderPrint ( "Applying BC... " );
        bcManage ( *M_systemMatrix, *M_rhs, *uFESpace()->mesh(), uFESpace()->dof(), *bchandler, uFESpace()->feBd(), 1.0, currentTime );
        M_systemMatrix->globalAssemble();
        displayer().leaderPrint ( "done\n" );

        // Norm of the rhs needed for the nonlinear convergence test
        if ( subiter == 0 )
        {
            normRhs = M_rhs->norm2();
        }

        //
        // STEP 3: Computing the residual
        //

        // Computing the RHS as RHS=b-Ax_k
        vector_Type Ax ( solution->map() );
        M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() );

        Ax.epetraVector().Update (-1, M_rhs->epetraVector(), 1);
        nonLinearResidual = Ax.norm2();

        displayer().leaderPrint ( "Nonlinear residual          : ", nonLinearResidual, "\n" );
        displayer().leaderPrint ( "Nonlinear residual (scaled) : ", nonLinearResidual / normRhs, "\n" );

        if ( nonLinearResidual > M_nonLinearTolerance * normRhs )
        {
            displayer().leaderPrint ( "---\nSubiteration [", ++subiter, "]\n" );

            // Extra information if we want to know the exact residual
            if ( M_computeResidual )
            {
                rhsIterNorm = M_rhs->norm2();
            }

            //
            // Solving the system
            //
            displayer().leaderPrint ( "Solving the system... \n" );
            *solution = 0.0;
            SolverPolicy::solve ( M_systemMatrix, M_rhs, solution );
            // int numIter = SolverPolicy::solve( M_systemMatrix, M_rhs, solution );
            // numIterSum += numIter; //

            if ( M_computeResidual )
            {
                vector_Type Ax ( solution->map() );
                vector_Type res ( *M_rhs );
                M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() );
                res.epetraVector().Update ( -1, Ax.epetraVector(), 1 );
                Real residual;
                res.norm2 ( &residual );
                residual /= rhsIterNorm;
                displayer().leaderPrint ( "Scaled residual: ", residual, "\n" );
            }
        }
    }
    while ( nonLinearResidual > M_nonLinearTolerance * normRhs );

    displayer().leaderPrint ( "Nonlinear iterations           : ", subiter, "\n" );
}
示例#4
0
// ===================================================
// Methods
// ===================================================
Int
LinearSolver::solve ( vectorPtr_Type solutionPtr )
{
    // Build preconditioners if needed
    bool retry ( true );
    if ( !isPreconditionerSet() || !M_reusePreconditioner  )
    {
        buildPreconditioner();

        // There will be no retry if the preconditioner is recomputed
        retry = false;
    }
    else
    {
        if ( !M_silent )
        {
            M_displayer->leaderPrint ( "SLV-  Reusing precond ...\n" );
        }
    }

    if ( M_rhs.get() == 0 || M_operator == 0 )
    {
        M_displayer->leaderPrint ( "SLV-  ERROR: LinearSolver failed to set up correctly!\n" );
        return -1;
    }

    // Setup the Solver Operator
    setupSolverOperator();

    // Reset status informations
    bool failure = false;
    this->resetStatus();
    M_solverOperator->resetStatus();

    // Solve the linear system
    LifeChrono chrono;
    chrono.start();

    M_solverOperator->ApplyInverse ( M_rhs->epetraVector(), solutionPtr->epetraVector() );
    M_converged         = M_solverOperator->hasConverged();
    M_lossOfPrecision   = M_solverOperator->isLossOfAccuracyDetected();
    chrono.stop();
    if ( !M_silent )
    {
        M_displayer->leaderPrintMax ( "SLV-  Solution time: " , chrono.diff(), " s." );
    }

    // Getting informations post-solve
    Int numIters = M_solverOperator->numIterations();

    // Second run recomputing the preconditioner
    // This is done only if the preconditioner has not been
    // already recomputed and if it is a LifeV preconditioner.
    if ( M_converged != SolverOperator_Type::yes
            && retry
            && M_preconditioner )
    {
        M_displayer->leaderPrint ( "SLV-  Iterative solver failed, numiter = " , numIters, "\n" );
        M_displayer->leaderPrint ( "SLV-  retrying:\n" );

        buildPreconditioner();

        // Solving again, but only once (retry = false)
        chrono.start();
        M_solverOperator->ApplyInverse ( M_rhs->epetraVector(), solutionPtr->epetraVector() );
        M_converged         = M_solverOperator->hasConverged();
        M_lossOfPrecision   = M_solverOperator->isLossOfAccuracyDetected();
        chrono.stop();
        if ( !M_silent )
        {
            M_displayer->leaderPrintMax ( "SLV-  Solution time: " , chrono.diff(), " s." );
        }
    }

    if ( M_lossOfPrecision == SolverOperator_Type::yes )
    {
        M_displayer->leaderPrint ( "SLV-  WARNING: Loss of accuracy detected!\n" );
        failure = true;
    }

    if ( M_converged == SolverOperator_Type::yes )
    {
        if ( !M_silent )
        {
            M_displayer->leaderPrint ( "SLV-  Convergence in " , numIters, " iterations\n" );
        }
        M_maxNumItersReached = SolverOperator_Type::no;
    }
    else
    {
        M_displayer->leaderPrint ( "SLV-  WARNING: Solver failed to converged to the desired precision!\n" );
        M_maxNumItersReached = SolverOperator_Type::yes;
        failure = true;
    }

    // If quitOnFailure is enabled and if some problems occur
    // the simulation is stopped
    if ( M_quitOnFailure && failure )
    {
        exit ( -1 );
    }

    // Reset the solver to free the internal pointers
    M_solverOperator->resetSolver();

    // If the number of iterations reaches the threshold of maxIterForReuse
    // we reset the preconditioners to force to solver to recompute it next
    // time
    if ( numIters > M_maxItersForReuse )
    {
        resetPreconditioner();
    }

    return numIters;
}