示例#1
0
int SolverOperator::Apply ( const vector_Type& X, vector_Type& Y ) const
{
    ASSERT_PRE ( X.Map().SameAs ( M_oper->OperatorDomainMap() ), "X and domain map do no coincide \n" );
    ASSERT_PRE ( Y.Map().SameAs ( M_oper->OperatorRangeMap() ) , "Y and range map do no coincide \n" );

    return M_oper->Apply ( X, Y );
}
示例#2
0
// ===================================================
// Methods
// ===================================================
void  FSIExactJacobian::solveJac (vector_Type&         _muk,
                                  const vector_Type&   _res,
                                  const Real         _linearRelTol)
{
    if (this->isFluid() && this->isLeader() )
    {
        std::cout << "  f- ";
    }
    if (this->isSolid() && this->isLeader() )
    {
        std::cout << "  s- ";
    }

    this->displayer().leaderPrint ( "FSI --- solveJac: NormInf res " , _res.normInf(), "\n" );
    _muk *= 0.;

    M_linearSolver.setTolerance ( _linearRelTol );
    M_linearSolver.setMaxNumIterations ( 100 );

    vector_Type res (_res);

    M_linearSolver.setOperator (M_epetraOper);

    this->displayer().leaderPrint ( "FSI --- Solving Jacobian FSI system... " );

    M_recomputeShapeDer = true;
    M_linearSolver.solve (_muk, res);

    this->displayer().leaderPrint ( "FSI --- Solving the Jacobian FSI system done.\n" );
}
示例#3
0
int SolverOperator::ApplyInverse( const vector_Type& X, vector_Type& Y ) const
{
	ASSERT_PRE( Y.Map().SameAs( M_oper->OperatorDomainMap() ), "Y and domain map do no coincide \n" );
	ASSERT_PRE( X.Map().SameAs( M_oper->OperatorRangeMap() ) , "X and range map do no coincide \n" );

	if ( M_useTranspose )
		return -1;
	int result = doApplyInverse( X, Y );

	M_numCumulIterations += M_numIterations;

    if( M_comm->MyPID() == 0 && M_printSubiterationCount )
    {
	    std::cout << "> " << numIterations() << " subiterations" << std::endl;
    }

	return result;
}
示例#4
0
void
computeP0pressure (const feSpacePtr_Type& pFESpacePtr,
                   const feSpacePtr_Type& p0FESpacePtr,
                   const feSpacePtr_Type& uFESpacePtr,
                   const vector_Type&     velAndPressure,
                   vector_Type&           P0pres,
                   Real /*time*/)
{

    int MyPID;
    MPI_Comm_rank (MPI_COMM_WORLD, &MyPID);
    UInt offset = 3 * uFESpacePtr->dof().numTotalDof();

    std::vector<int> gid0Vec (0);
    gid0Vec.reserve (p0FESpacePtr->mesh()->numVolumes() );
    std::vector<Real> val0Vec (0);
    val0Vec.reserve (p0FESpacePtr->mesh()->numVolumes() );

    for (UInt ivol = 0; ivol < pFESpacePtr->mesh()->numVolumes(); ++ivol)
    {

        pFESpacePtr->fe().update ( pFESpacePtr->mesh()->volumeList ( ivol ), UPDATE_DPHI );
        p0FESpacePtr->fe().update ( p0FESpacePtr->mesh()->volumeList ( ivol ) );

        UInt eleID = pFESpacePtr->fe().currentLocalId();

        double tmpsum = 0.;
        for (UInt iNode = 0; iNode < (UInt) pFESpacePtr->fe().nbFEDof(); iNode++)
        {
            int ig = pFESpacePtr->dof().localToGlobalMap ( eleID, iNode );
            tmpsum += velAndPressure (ig + offset);
            gid0Vec.push_back ( p0FESpacePtr->fe().currentId() );
            val0Vec.push_back ( tmpsum / (double) pFESpacePtr->fe().nbFEDof() );
        }
    }
    P0pres.setCoefficients (gid0Vec, val0Vec);
    P0pres.globalAssemble();
    MPI_Barrier (MPI_COMM_WORLD);

}
示例#5
0
MatrixEpetra<Real> ElectroIonicModel::getJac (const vector_Type& v, Real /*h*/)
{
    matrix_Type J (v.map(), M_numberOfEquations, false);
    //  vector<Real> f1(M_numberOfEquations,0.0);
    //  vector<Real> f2(M_numberOfEquations,0.0);
    //  vector< vector<Real> > df ( M_numberOfEquations, vector<Real> (M_numberOfEquations,0.0) );
    //  vector<Real> y1(M_numberOfEquations,0.0);
    //  vector<Real> y2(M_numberOfEquations,0.0);
    //  const Int* k = v.blockMap().MyGlobalElements();
    //
    //  int* Indices = new int[M_numberOfEquations];
    //  double* Values =  new double[M_numberOfEquations];
    //  for(int i=0; i<M_numberOfEquations; i++)
    //      Indices[i] = i;
    //
    //  for(int i=0; i<M_numberOfEquations; i++)
    //  {
    //      for(int j=0; j<M_numberOfEquations; j++)
    //      {
    //          y1[j] = v[ k[j] ] + ((double)(i==j))*h;
    //          y2[j] = v[ k[j] ] - ((double)(i==j))*h;
    //      }
    //      this->computeRhs(y1, f1);
    //      this->computeRhs(y2, f2);
    //
    //      for(int j=0; j<M_numberOfEquations; j++)
    //          df[j][i] = (f1[j]-f2[j])/(2.0*h);
    //  }
    //
    //
    //  for(int i=0; i<M_numberOfEquations; i++)
    //  {
    //      for(int j=0; j<M_numberOfEquations; j++)
    //          Values[j] = df[i][j];
    //      J.matrixPtr()->InsertGlobalValues (i, M_numberOfEquations, Values, Indices);
    //  }
    //
    //  J.globalAssemble();
    //
    //  delete[] Indices;
    //  delete[] Values;

    return J;
}
示例#6
0
int BelosOperator::doApplyInverse ( const vector_Type& X, vector_Type& Y ) const
{

    Teuchos::RCP<vector_Type> Xcopy ( new vector_Type ( X ) );
    Y.PutScalar ( 0.0 );
    bool set = M_linProblem->setProblem ( Teuchos::rcp ( &Y, false ), Xcopy );
    if ( set == false )
    {
        std::cout << std::endl << "SLV-  ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl;
        return -12;
    }

    M_solverManager->setProblem ( M_linProblem );


    // Solving the system
    Belos::ReturnType ret = M_solverManager->solve();

    // Update the number of performed iterations
    M_numIterations = M_solverManager->getNumIters();

    // Update of the status
    if ( M_solverManager->isLOADetected() )
    {
        M_lossOfAccuracy = yes;
    }
    else
    {
        M_lossOfAccuracy = no;
    }

    if ( ret == Belos::Converged )
    {
        M_converged = yes;
        return 0;
    }
    else
    {
        M_converged = no;
        return -1;
    }

}
示例#7
0
void Heart::computeRhs ( vector_Type& rhs,
                         HeartBidomainSolver< mesh_Type >& electricModel,
                         boost::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel,
                         HeartBidomainData& data )
{
    bool verbose = (M_heart_fct->M_comm->MyPID() == 0);
    if (verbose)
    {
        std::cout << "  f-  Computing Rhs ...        " << "\n" << std::flush;
    }
    LifeChrono chrono;
    chrono.start();

    //! u, w with repeated map
    vector_Type uVecRep (electricModel.solutionTransmembranePotential(), Repeated);
    ionicModel->updateRepeated();

    VectorElemental elvec_Iapp ( electricModel.potentialFESpace().fe().nbFEDof(), 2 ),
                    elvec_u ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ),
                    elvec_Iion ( electricModel.potentialFESpace().fe().nbFEDof(), 1 );
    for (UInt iVol = 0; iVol < electricModel.potentialFESpace().mesh()->numVolumes(); ++iVol)
    {
        electricModel.potentialFESpace().fe().updateJacQuadPt ( electricModel.potentialFESpace().mesh()->volumeList ( iVol ) );
        elvec_u.zero();
        elvec_Iion.zero();
        elvec_Iapp.zero();

        UInt eleIDu = electricModel.potentialFESpace().fe().currentLocalId();
        UInt nbNode = ( UInt ) electricModel.potentialFESpace().fe().nbFEDof();
        for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
        {
            Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode );
            elvec_u.vec() [ iNode ] = uVecRep[ig];
        }

        UInt eleID = electricModel.potentialFESpace().fe().currentLocalId();
        ionicModel->updateElementSolution (eleID);
        ionicModel->computeIonicCurrent (data.membraneCapacitance(), elvec_Iion, elvec_u, electricModel.potentialFESpace() );

        //! Computing Iapp
        AssemblyElemental::source (M_heart_fct->stimulus(),
                                   elvec_Iapp,
                                   electricModel.potentialFESpace().fe(),
                                   data.time(), 0);
        AssemblyElemental::source (M_heart_fct->stimulus(),
                                   elvec_Iapp,
                                   electricModel.potentialFESpace().fe(),
                                   data.time(),
                                   1);
        UInt totalUDof  = electricModel.potentialFESpace().map().map (Unique)->NumGlobalElements();

        for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
        {
            Int ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode );
            rhs.sumIntoGlobalValues (ig, elvec_Iapp.vec() [iNode] +
                                     data.volumeSurfaceRatio() * elvec_Iion.vec() [iNode] );
            rhs.sumIntoGlobalValues (ig + totalUDof,
                                     -elvec_Iapp.vec() [iNode + nbNode] -
                                     data.volumeSurfaceRatio() * elvec_Iion.vec() [iNode] );
        }
    }
    rhs.globalAssemble();

    rhs += electricModel.matrMass() * data.volumeSurfaceRatio() *
           data.membraneCapacitance() * electricModel.BDFIntraExtraPotential().time_der (data.timeStep() );

    MPI_Barrier (MPI_COMM_WORLD);

    chrono.stop();
    if (verbose)
    {
        std::cout << "done in " << chrono.diff() << " s." << std::endl;
    }
}
示例#8
0
void Heart::computeRhs ( vector_Type& rhs,
                         HeartMonodomainSolver< mesh_Type >& electricModel,
                         boost::shared_ptr< HeartIonicSolver< mesh_Type > > ionicModel,
                         HeartMonodomainData& data )
{
    bool verbose = (M_heart_fct->M_comm->MyPID() == 0);
    if (verbose)
    {
        std::cout << "  f-  Computing Rhs ...        " << "\n" << std::flush;
    }
    LifeChrono chrono;
    chrono.start();

    //! u, w with repeated map
    vector_Type uVecRep (electricModel.solutionTransmembranePotential(), Repeated);
    ionicModel->updateRepeated();
    VectorElemental elvec_Iapp ( electricModel.potentialFESpace().fe().nbFEDof(), 2 ),
                    elvec_u ( electricModel.potentialFESpace().fe().nbFEDof(), 1 ),
                    elvec_Iion ( electricModel.potentialFESpace().fe().nbFEDof(), 1 );

    for (UInt iVol = 0; iVol < electricModel.potentialFESpace().mesh()->numVolumes(); ++iVol)
    {
        electricModel.potentialFESpace().fe().updateJacQuadPt ( electricModel.potentialFESpace().mesh()->volumeList ( iVol ) );
        elvec_Iapp.zero();
        elvec_u.zero();
        elvec_Iion.zero();

        UInt eleIDu = electricModel.potentialFESpace().fe().currentLocalId();
        UInt nbNode = ( UInt ) electricModel.potentialFESpace().fe().nbFEDof();

        //! Filling local elvec_u with potential values in the nodes
        for ( UInt iNode = 0 ; iNode < nbNode ; iNode++ )
        {
            Int  ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, iNode );
            elvec_u.vec() [ iNode ] = uVecRep[ig];
        }

        ionicModel->updateElementSolution (eleIDu);
        ionicModel->computeIonicCurrent (data.membraneCapacitance(), elvec_Iion, elvec_u, electricModel.potentialFESpace() );

        //! Computing the current source of the righthand side, repeated
        AssemblyElemental::source (M_heart_fct->stimulus(),
                                   elvec_Iapp,
                                   electricModel.potentialFESpace().fe(),
                                   data.time(),
                                   0);
        AssemblyElemental::source (M_heart_fct->stimulus(),
                                   elvec_Iapp,
                                   electricModel.potentialFESpace().fe(),
                                   data.time(),
                                   1);

        //! Assembling the righthand side
        for ( UInt i = 0 ; i < electricModel.potentialFESpace().fe().nbFEDof() ; i++ )
        {
            Int  ig = electricModel.potentialFESpace().dof().localToGlobalMap ( eleIDu, i );
            rhs.sumIntoGlobalValues (ig, (data.conductivityRatio() * elvec_Iapp.vec() [i] +
                                          elvec_Iapp.vec() [i + nbNode]) /
                                     (1 + data.conductivityRatio() ) + data.volumeSurfaceRatio() * elvec_Iion.vec() [i] );
        }
    }
    rhs.globalAssemble();
    Real coeff = data.volumeSurfaceRatio() * data.membraneCapacitance() / data.timeStep();
    vector_Type tmpvec (electricModel.solutionTransmembranePotential() );
    tmpvec *= coeff;
    rhs += electricModel.massMatrix() * tmpvec;
    MPI_Barrier (MPI_COMM_WORLD);
    chrono.stop();
    if (verbose)
    {
        std::cout << "done in " << chrono.diff() << " s." << std::endl;
    }
}
示例#9
0
int
AztecooOperator::doApplyInverse( const vector_Type& X, vector_Type& Y ) const
{
    M_numIterations = 0;

	vector_Type Xcopy( X );
	Y.PutScalar( 0.0 );
	if( M_tolerance > 0 )
	    M_pList->sublist( "Trilinos: AztecOO List" ).set( "tol", M_tolerance );
	M_linSolver->SetParameters( M_pList->sublist( "Trilinos: AztecOO List" ) );
	M_linSolver->SetRHS( &Xcopy );
	M_linSolver->SetLHS( &Y );

    M_linSolver->SetUserOperator( M_oper.get() );

    if( M_prec.get() != 0 )
        M_linSolver->SetPrecOperator( (Epetra_Operator*) M_prec.get() );

	int maxIter( M_pList->sublist( "Trilinos: AztecOO List" ).get<int>( "max_iter" ) );
	double tol(  M_pList->sublist( "Trilinos: AztecOO List" ).get<double>( "tol" ) );

	// Solving the system
	int retValue = M_linSolver->Iterate(maxIter, tol);

    /* try to solve again (reason may be:
      -2 "Aztec status AZ_breakdown: numerical breakdown"
      -3 "Aztec status AZ_loss: loss of precision"
      -4 "Aztec status AZ_ill_cond: GMRES hessenberg ill-conditioned"
      This method was used in the old AztecOO solver.
    */
    if ( retValue <= -2 )
    {
        M_numIterations += M_linSolver->NumIters();
        retValue = M_linSolver->Iterate(maxIter, tol);
    }

	// Update the number of performed iterations
	M_numIterations += M_linSolver->NumIters();

	// Update of the status
	Real status[AZ_STATUS_SIZE];
	M_linSolver->GetAllAztecStatus( status );

	if ( status[AZ_why] == AZ_normal )
	{
		M_converged = yes;
	}
	else
	{
		M_converged = no;
	}

	if ( status[AZ_why] == AZ_loss )
	{
		M_lossOfAccuracy = yes;
	}
	else
	{
		M_lossOfAccuracy = no;
	}

	return retValue;
}
示例#10
0
void FSIExactJacobian::evalResidual (vector_Type&       res,
                                     const vector_Type& disp,
                                     const UInt          iter)
{
    if (this->isSolid() )
    {
        std::cout << "FSI ---      Residual computation g(x_" << iter << " )\n";
    }

    setLambdaSolidOld (disp);


    eval (disp, iter);

    res  = this->lambdaSolid();
    res -=  disp;

    if (this->isSolid() )
    {
        M_solid->updateJacobian (M_solid->displacement() );
    }

    this->displayer().leaderPrint ("FSI ---      NormInf res        =                     " , res.normInf(), "\n" );
    if (this->isSolid() )
    {
        this->displayer().leaderPrint ("FSI ---      NormInf res_d      =                     " , this->solid().residual().normInf(), "\n" );
    }

}
示例#11
0
int FSIExactJacobian::Epetra_ExactJacobian::Apply (const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
{

    LifeChrono chronoFluid, chronoSolid, chronoInterface;

    M_comm->Barrier();

    double xnorm = 0.;
    X.NormInf (&xnorm);

    Epetra_FEVector  dz (Y.Map() );

    if (M_ej->isSolid() )
    {
        std::cout << "\n ***** norm (z)= " << xnorm << std::endl << std::endl;
    }


    if ( xnorm == 0.0 )
    {
        Y.Scale (0.);
        dz.Scale (0.);
    }
    else
    {
        vector_Type const z (X,  M_ej->solidInterfaceMap(), Unique);

        M_ej->displayer().leaderPrint ( "NormInf res   " , z.normInf(), "\n" );

        //M_ej->solid().residual() *= 0.;
        //M_ej->transferInterfaceOnSolid(z, M_ej->solid().residual());

        //std::cout << "NormInf res_d " << M_ej->solid().residual().NormInf() << std::endl;

        //if (M_ej->isSolid())
        //    M_ej->solid().postProcess();

        M_ej->setLambdaFluid (z);

        //M_ej->transferInterfaceOnSolid(z, M_ej->solid().disp());

        chronoInterface.start();
        vector_Type sigmaFluidUnique (M_ej->sigmaFluid(), Unique);
        chronoInterface.stop();

        M_comm->Barrier();
        chronoFluid.start();

        if (M_ej->isFluid() )
        {

            //to be used when we correct the other lines
            if (true || ( !this->M_ej->dataFluid()->isSemiImplicit() /*|| this->M_ej->dataFluid().semiImplicit()==-1*/) )
            {
                M_ej->meshMotion().iterate (*M_ej->BCh_harmonicExtension() );
                //std::cout<<" mesh motion iterated!!!"<<std::endl;
            }

            M_ej->displayer().leaderPrint ( " norm inf dx = " , M_ej->meshMotion().disp().normInf(), "\n" );

            M_ej->solveLinearFluid();

            M_ej->transferFluidOnInterface (M_ej->fluid().residual(), sigmaFluidUnique);

            //M_ej->fluidPostProcess();
        }

        M_comm->Barrier();
        chronoFluid.stop();
        M_ej->displayer().leaderPrintMax ( "Fluid linear solution: total time : ", chronoFluid.diff() );


        chronoInterface.start();
        // M_ej->setSigmaFluid(sigmaFluidUnique);
        M_ej->setSigmaSolid (sigmaFluidUnique);


        vector_Type lambdaSolidUnique (M_ej->lambdaSolid(), Unique);
        chronoInterface.stop();

        M_comm->Barrier();
        chronoFluid.start();

        if (M_ej->isSolid() )
        {
            M_ej->solveLinearSolid();
            M_ej->transferSolidOnInterface (M_ej->solid().displacement(), lambdaSolidUnique);
        }

        M_comm->Barrier();
        chronoSolid.stop();
        M_ej->displayer().leaderPrintMax ( "Solid linear solution: total time : " , chronoSolid.diff() );

        chronoInterface.start();
        M_ej->setLambdaSolid (lambdaSolidUnique);

        chronoInterface.stop();
        M_ej->displayer().leaderPrintMax ( "Interface linear transfer: total time : " , chronoInterface.diffCumul() );

        dz = lambdaSolidUnique.epetraVector();
    }


    Y = X;
    Y.Update (1., dz, -1.);

    double ynorm;
    Y.NormInf (&ynorm);

    if (M_ej->isSolid() )
        std::cout << "\n\n ***** norm (Jz)= " << ynorm
                  << std::endl << std::endl;

    return 0;
}
示例#12
0
void FSIExactJacobian::eval (const vector_Type& _disp,
                             const UInt          iter)
{
    LifeChrono chronoFluid, chronoSolid, chronoInterface;

    bool recomputeMatrices ( iter == 0 || ( !this->M_data->dataFluid()->isSemiImplicit() &&
                                            ( M_data->updateEvery() > 0 &&
                                              (iter % M_data->updateEvery() == 0) ) ) );

    if (iter == 0)
    {
        if (isFluid() )
        {
            this->M_fluid->resetPreconditioner();
        }
        //this->M_solid->resetPrec();
    }


    this->setLambdaFluid (_disp);


    vector_Type sigmaFluidUnique (this->sigmaFluid(), Unique);

    M_epetraWorldComm->Barrier();
    chronoFluid.start();

    if (isFluid() )
    {
        M_meshMotion->iterate (*M_BCh_mesh);
        // M_meshMotion->updateDispDiff();


        // copying displacement to a repeated indeces displacement, otherwise the mesh wont know
        // the value of the displacement for some points


        if ( iter == 0 || !this->M_data->dataFluid()->isSemiImplicit() )
        {
            *M_beta *= 0.;

            if ( iter == 0 )
            {
                M_ALETimeAdvance->updateRHSFirstDerivative (M_data->dataFluid()->dataTime()->timeStep() );
                M_ALETimeAdvance->shiftRight (M_meshMotion->disp() );
                M_ALETimeAdvance->extrapolation (M_meshMotion->disp() ); //closer initial solution
            }
            else
            {
                M_ALETimeAdvance->setSolution (M_meshMotion->disp() );
            }

            vector_Type meshDispRepeated ( M_meshMotion->disp(), Repeated );
            this->moveMesh (meshDispRepeated);
            vector_Type vel ( this->M_ALETimeAdvance->firstDerivative( ) );
            transferMeshMotionOnFluid ( vel, veloFluidMesh() );
            M_fluidTimeAdvance->extrapolation (*M_beta); //explicit
            *M_beta -= veloFluidMesh();//implicit


            //the conservative formulation as it is now is of order 1. To have higher order (TODO) we need to store the mass matrices computed at the previous time steps.
            if (M_data->dataFluid()->conservativeFormulation() )
                //*M_rhs = M_fluid->matrixMass()*M_fluidTimeAdvance->rhsContributionFirstDerivative();
            {
                *M_rhs = M_fluidMassTimeAdvance->rhsContributionFirstDerivative();
            }


            if (recomputeMatrices)
            {
                double alpha = M_fluidTimeAdvance->coefficientFirstDerivative (0) / M_data->dataFluid()->dataTime()->timeStep();
                this->M_fluid->updateSystem ( alpha, *M_beta, *M_rhs );
            }
            else
            {
                this->M_fluid->updateRightHandSide ( *M_rhs );
            }
            if (!M_data->dataFluid()->conservativeFormulation() )
            {
                *M_rhs = M_fluid->matrixMass() * M_fluidTimeAdvance->rhsContributionFirstDerivative();
                this->M_fluid->updateRightHandSide ( *M_rhs );
            }
        }

        this->M_fluid->iterate ( *M_BCh_u );

        this->transferFluidOnInterface (this->M_fluid->residual(), sigmaFluidUnique);
    }

    M_epetraWorldComm->Barrier();
    chronoFluid.stop();
    this->displayer().leaderPrintMax ("      Fluid solution total time:               ", chronoFluid.diff() );

    if ( false && this->isFluid() )
    {
        vector_Type vel  (this->fluid().velocityFESpace().map() );
        vector_Type press (this->fluid().pressureFESpace().map() );

        vel.subset (*this->M_fluid->solution() );
        press.subset (*this->M_fluid->solution(), this->fluid().velocityFESpace().dim() *this->fluid().pressureFESpace().fieldDim() );

        std::cout << "norm_inf( vel ) " << vel.normInf() << std::endl;
        std::cout << "norm_inf( press ) " << press.normInf() << std::endl;

        //this->M_fluid->postProcess();
    }

    chronoInterface.start();

    this->setSigmaFluid ( sigmaFluidUnique );
    this->setSigmaSolid ( sigmaFluidUnique );



    vector_Type lambdaSolidUnique   (this->lambdaSolid(),    Unique);
    vector_Type lambdaDotSolidUnique (this->lambdaDotSolid(), Unique);
    vector_Type sigmaSolidUnique    (this->sigmaSolid(),     Unique);

    chronoInterface.stop();
    M_epetraWorldComm->Barrier();
    chronoSolid.start();

    if (this->isSolid() )
    {
        this->M_solid->iterate ( M_BCh_d );
    }

    M_epetraWorldComm->Barrier();
    chronoSolid.stop();
    this->displayer().leaderPrintMax ("      Solid solution total time:               ", chronoSolid.diff() );

    chronoInterface.start();

    if (this->isSolid() )
    {
        this->transferSolidOnInterface (this->M_solid->displacement(),     lambdaSolidUnique);
        this->transferSolidOnInterface ( this->M_solidTimeAdvance->firstDerivative ( this->M_solid->displacement() ), lambdaDotSolidUnique );
        this->transferSolidOnInterface (this->M_solid->residual(), sigmaSolidUnique);
    }

    this->setLambdaSolid (    lambdaSolidUnique);
    this->setLambdaDotSolid ( lambdaDotSolidUnique);
    this->setSigmaSolid (     sigmaSolidUnique);

    chronoInterface.stop();
    this->displayer().leaderPrintMax ("      Interface transfer total time:           ", chronoInterface.diffCumul() );


    // possibly unsafe when using more cpus, since both has repeated maps

    this->displayer().leaderPrint ("      Norm(disp     )    =                     ", _disp.normInf(), "\n");
    this->displayer().leaderPrint ("      Norm(dispNew  )    =                     " , this->lambdaSolid().normInf(), "\n" );
    this->displayer().leaderPrint ("      Norm(velo     )    =                     " , this->lambdaDotSolid().normInf(), "\n" );
    this->displayer().leaderPrint ("      Max Residual Fluid =                     " , this->sigmaFluid().normInf(), "\n" );
    this->displayer().leaderPrint ("      Max Residual Solid =                     " , this->sigmaSolid().normInf(), "\n" );

    if ( this->isFluid() )
    {
        this->displayer().leaderPrint ("      Max ResidualF      =                     " , M_fluid->residual().normInf(), "\n" );
    }
    if ( this->isSolid() )
    {
        this->displayer().leaderPrint ("      NL2 Diplacement S. =                     " , M_solid->displacement().norm2(), "\n" );
        this->displayer().leaderPrint ("      Max Residual Solid =                     " , M_solid->residual().normInf(), "\n" );
    }
}