Esempio n. 1
0
int main(int argc, char** argv)
{

    // +-----------------------------------------------+
    // |            Initialization of MPI              |
    // +-----------------------------------------------+
#ifdef HAVE_MPI
    MPI_Init(&argc, &argv);
#endif

    boost::shared_ptr<Epetra_Comm>   comm;
#ifdef EPETRA_MPI
    comm.reset( new Epetra_MpiComm( MPI_COMM_WORLD ) );
    int nproc;
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
#else
    comm.reset( new Epetra_SerialComm() );
#endif

    bool verbose(false);
    if (comm->MyPID() == 0)
    {
        verbose = true;
        std::cout
                << " +-----------------------------------------------+" << std::endl
                << " |           Cavity example for LifeV            |" << std::endl
                << " +-----------------------------------------------+" << std::endl
                << std::endl
                << " +-----------------------------------------------+" << std::endl
                << " |           Author: Gwenol Grandperrin          |" << std::endl
                << " |             Date: October 25, 2010            |" << std::endl
                << " +-----------------------------------------------+" << std::endl
                << std::endl;

        std::cout << "[Initilization of MPI]" << std::endl;
#ifdef HAVE_MPI
        std::cout << "Using MPI (" << nproc << " proc.)" << std::endl;
#else
        std::cout << "Using serial version" << std::endl;
#endif
    }

    // Chronometer
    LifeV::LifeChrono globalChrono;
    LifeV::LifeChrono initChrono;
    LifeV::LifeChrono iterChrono;
    globalChrono.start();
    initChrono.start();

    // +-----------------------------------------------+
    // |               Loading the data                |
    // +-----------------------------------------------+
    if (verbose) std::cout << std::endl << "[Loading the data]" << std::endl;
    GetPot command_line(argc,argv);
    const std::string dataFileName = command_line.follow("data", 2, "-f","--file");
    GetPot dataFile(dataFileName);

    // +-----------------------------------------------+
    // |               Loading the mesh                |
    // +-----------------------------------------------+
    if (verbose) std::cout << std::endl << "[Loading the mesh]" << std::endl;
    LifeV::MeshData meshData;
    meshData.setup(dataFile, "fluid/space_discretization");
    if (verbose) std::cout << "Mesh file: " << meshData.meshDir() << meshData.meshFile() << std::endl;
    boost::shared_ptr< mesh_Type > fullMeshPtr(new mesh_Type);
    LifeV::readMesh(*fullMeshPtr, meshData);
    // Split the mesh between processors
    boost::shared_ptr< mesh_Type > localMeshPtr;
    {
        LifeV::MeshPartitioner< mesh_Type >   meshPart(fullMeshPtr, comm);
        localMeshPtr = meshPart.meshPartition();
    }

    // +-----------------------------------------------+
    // |            Creating the FE spaces             |
    // +-----------------------------------------------+
    if (verbose) std::cout << std::endl << "[Creating the FE spaces]" << std::endl;
    std::string uOrder =  dataFile( "fluid/space_discretization/vel_order",   "P2");
    std::string pOrder =  dataFile( "fluid/space_discretization/press_order", "P1");
    if (verbose) std::cout << "FE for the velocity: " << uOrder << std::endl
                               << "FE for the pressure: " << pOrder << std::endl;

    if (verbose) std::cout << "Building the velocity FE space... " << std::flush;
    feSpacePtr_Type uFESpacePtr( new feSpace_Type(localMeshPtr, uOrder, 3, comm) );
    if (verbose)
        std::cout << "ok." << std::endl;

    if (verbose) std::cout << "Building the pressure FE space... " << std::flush;
    feSpacePtr_Type pFESpacePtr( new feSpace_Type(localMeshPtr,pOrder,1,comm) );
    if (verbose) std::cout << "ok." << std::endl;

    // Total degrees of freedom (elements of matrix)
    LifeV::UInt totalVelDof   = uFESpacePtr->map().map(LifeV::Unique)->NumGlobalElements();
    LifeV::UInt totalPressDof = pFESpacePtr->map().map(LifeV::Unique)->NumGlobalElements();

    if (verbose) std::cout << "Total Velocity Dof: " << totalVelDof << std::endl;
    if (verbose) std::cout << "Total Pressure Dof: " << totalPressDof << std::endl;

    // +-----------------------------------------------+
    // |             Boundary conditions               |
    // +-----------------------------------------------+
    if (verbose) std::cout<< std::endl << "[Boundary conditions]" << std::endl;

    LifeV::BCFunctionBase uZero(fZero);
    LifeV::BCFunctionBase uLid(lidBC);

    std::vector<LifeV::ID> xComp(1);
    xComp[0] = 1;

    LifeV::BCHandler bcH;
    // A boundary condition in every face
    bcH.addBC( "Top"   , TOP   , LifeV::Essential, LifeV::Full     , uLid , 3     );
    bcH.addBC( "Left"  , LEFT  , LifeV::Essential, LifeV::Full     , uZero, 3     );
    bcH.addBC( "Front" , FRONT , LifeV::Essential, LifeV::Component, uZero, xComp );
    bcH.addBC( "Right" , RIGHT , LifeV::Essential, LifeV::Full     , uZero, 3     );
    bcH.addBC( "Back"  , BACK  , LifeV::Essential, LifeV::Component, uZero, xComp );
    bcH.addBC( "Bottom", BOTTOM, LifeV::Essential, LifeV::Full     , uZero, 3     );

    // Get the number of Lagrange Multiplyers (LM) and set the offsets
    std::vector<LifeV::bcName_Type> fluxVector = bcH.findAllBCWithType( LifeV::Flux );
    LifeV::UInt numLM = static_cast<LifeV::UInt>( fluxVector.size() );

    LifeV::UInt offset = uFESpacePtr->map().map(LifeV::Unique)->NumGlobalElements()
                         + pFESpacePtr->map().map(LifeV::Unique)->NumGlobalElements();

    for ( LifeV::UInt i = 0; i < numLM; ++i )
        bcH.setOffset( fluxVector[i], offset + i );

    // +-----------------------------------------------+
    // |             Creating the problem              |
    // +-----------------------------------------------+
    if (verbose) std::cout<< std::endl << "[Creating the problem]" << std::endl;
    boost::shared_ptr<LifeV::OseenData> oseenData(new LifeV::OseenData());
    oseenData->setup( dataFile );

    if (verbose) std::cout << "Time discretization order " << oseenData->dataTime()->orderBDF() << std::endl;

    // The problem (matrix and rhs) is packed in an object called fluid
    LifeV::OseenSolver< mesh_Type > fluid (oseenData,
                                           *uFESpacePtr,
                                           *pFESpacePtr,
                                           comm,
                                           numLM);
    // Gets inputs from the data file
    fluid.setUp(dataFile);

    // Assemble the matrices
    fluid.buildSystem();

    // Communication map
    LifeV::MapEpetra fullMap(fluid.getMap());

    // Synchronization
    MPI_Barrier(MPI_COMM_WORLD);

    // +-----------------------------------------------+
    // |       Initialization of the simulation        |
    // +-----------------------------------------------+
    if (verbose) std::cout<< std::endl << "[Initialization of the simulation]" << std::endl;
    LifeV::Real dt     = oseenData->dataTime()->timeStep();
    LifeV::Real t0     = oseenData->dataTime()->initialTime();
    LifeV::Real tFinal = oseenData->dataTime()->endTime ();

    // bdf object to store the previous solutions
    LifeV::TimeAdvanceBDFNavierStokes<vector_Type> bdf;
    bdf.setup(oseenData->dataTime()->orderBDF());

    // Initialization with exact solution: either interpolation or "L2-NS"-projection
    t0 -= dt * bdf.bdfVelocity().order();

    vector_Type beta( fullMap );
    vector_Type rhs ( fullMap );

    MPI_Barrier(MPI_COMM_WORLD);

    // We get the initial solution using a steady Stokes problem
    oseenData->dataTime()->setTime(t0);

    beta *= 0.;
    rhs  *= 0.;
    fluid.updateSystem(0.0,beta,rhs);
    fluid.iterate(bcH);
    bdf.bdfVelocity().setInitialCondition( *fluid.solution() );

    LifeV::Real time = t0 + dt;
    for (  ; time <=  oseenData->dataTime()->initialTime() + dt/2.; time += dt)
    {
        oseenData->dataTime()->setTime(time);

        fluid.updateSystem(0.0,beta,rhs);
        fluid.iterate(bcH);
        bdf.bdfVelocity().shiftRight( *fluid.solution() );
    }

    // We erase the preconditioner build for Stokes
    // (A new one should be built for Navier-Stokes)
    fluid.resetPreconditioner();

    boost::shared_ptr< LifeV::ExporterHDF5<mesh_Type> > exporter;

    vectorPtr_Type velAndPressure;

    std::string const exporterType =  dataFile( "exporter/type", "ensight");

    exporter.reset( new LifeV::ExporterHDF5<mesh_Type> ( dataFile, "cavity_example" ) );
    exporter->setPostDir( "./" ); // This is a test to see if M_post_dir is working
    exporter->setMeshProcId( localMeshPtr, comm->MyPID() );

    velAndPressure.reset( new vector_Type(*fluid.solution(), exporter->mapType() ) );

    exporter->addVariable( LifeV::ExporterData<mesh_Type>::VectorField, "velocity", uFESpacePtr,
                           velAndPressure, LifeV::UInt(0) );

    exporter->addVariable( LifeV::ExporterData<mesh_Type>::ScalarField, "pressure", pFESpacePtr,
                           velAndPressure, LifeV::UInt(3*uFESpacePtr->dof().numTotalDof()) );
    exporter->postProcess( 0 );

    initChrono.stop();
    if (verbose) std::cout << "Initialization time:  " << initChrono.diff() << " s." << std::endl;

    // +-----------------------------------------------+
    // |             Solving the problem               |
    // +-----------------------------------------------+
    if (verbose) std::cout<< std::endl << "[Solving the problem]" << std::endl;
    int iter = 1;

    for ( ; time <= tFinal + dt/2.; time += dt, iter++)
    {

        oseenData->dataTime()->setTime(time);

        if (verbose) std::cout << "[t = "<< oseenData->dataTime()->time() << " s.]" << std::endl;

        iterChrono.start();

        double alpha = bdf.bdfVelocity().coefficientFirstDerivative( 0 ) / oseenData->dataTime()->timeStep();
        //Matteo
        //	beta =bdf.bdfVelocity().extrapolation();
        bdf.bdfVelocity().extrapolation( beta ); // Extrapolation for the convective term
        bdf.bdfVelocity().updateRHSContribution(oseenData->dataTime()->timeStep() );
        rhs  = fluid.matrixMass()*bdf.bdfVelocity().rhsContributionFirstDerivative();

        fluid.getDisplayer().leaderPrint("alpha ", alpha);
        fluid.getDisplayer().leaderPrint("\n");
        fluid.getDisplayer().leaderPrint("norm beta ", beta.norm2());
        fluid.getDisplayer().leaderPrint("\n");
        fluid.getDisplayer().leaderPrint("norm rhs  ", rhs.norm2());
        fluid.getDisplayer().leaderPrint("\n");

        fluid.updateSystem( alpha, beta, rhs );
        fluid.iterate( bcH );

        bdf.bdfVelocity().shiftRight( *fluid.solution() );

        // Computation of the error
        vector_Type vel  (uFESpacePtr->map(), LifeV::Repeated);
        vector_Type press(pFESpacePtr->map(), LifeV::Repeated);
        vector_Type velpressure ( *fluid.solution(), LifeV::Repeated );

        velpressure = *fluid.solution();
        vel.subset(velpressure);
        press.subset(velpressure, uFESpacePtr->dim()*uFESpacePtr->fieldDim());


        bool verbose = (comm->MyPID() == 0);


        // Exporting the solution
        *velAndPressure = *fluid.solution();
        exporter->postProcess( time );


        MPI_Barrier(MPI_COMM_WORLD);

        iterChrono.stop();
        if (verbose) std::cout << "Iteration time: " << iterChrono.diff() << " s." << std::endl << std::endl;
    }

    globalChrono.stop();
    if (verbose) std::cout << "Total simulation time:  " << globalChrono.diff() << " s." << std::endl;

    exporter->closeFile();

#ifdef HAVE_MPI
    MPI_Finalize();
#endif

    return 0;
}
Esempio n. 2
0
void SolveHilbert( El::Int n, El::Int maxRefineIts, bool refineProgress )
{
    El::Output("Attempting to solve Hilbert system with ",El::TypeName<Real>());

    // Form an n x n Hilbert matrix
    El::Matrix<Real> A;
    El::Hilbert( A, n );

    // Form a uniform random vector
    El::Matrix<Real> x;
    El::Uniform( x, n, 1 );
    const Real xFrob = El::FrobeniusNorm( x );

    // Form b := A x
    El::Matrix<Real> b;
    El::Gemv( El::NORMAL, Real(1), A, x, b );
    const Real bFrob = El::FrobeniusNorm( b );

    // Form xComp := inv(A) b. Rather than calling El::HPDSolve, we will instead
    // call El::hpd_solve::Overwrite so that we can reuse the Cholesky factor.
    El::Matrix<Real> xComp(b);
    El::Matrix<Real> L(A);
    El::hpd_solve::Overwrite( El::LOWER, El::NORMAL, L, xComp );

    // Form r := b - A x
    El::Matrix<Real> r(b);
    El::Gemv( El::NORMAL, Real(-1), A, xComp, Real(1), r );
    const Real rFrob = El::FrobeniusNorm( r );
    El::Output("|| r ||_2 / || b ||_2 = ",rFrob/bFrob);

    // Form e := x - xComp
    El::Matrix<Real> e(x);
    e -= xComp;
    const Real eFrob = El::FrobeniusNorm( e );
    El::Output("|| e ||_2 / || x ||_2 = ",eFrob/xFrob);

    // Run iterative refinement to try to increase the solution accuracy
    // (unfortunately, for Hilbert matrices the residual is already small)
    auto applyA = [&]( const El::Matrix<Real>& y, El::Matrix<Real>& Ay ) {
        El::Gemv( El::NORMAL, Real(1), A, y, Ay );
    };
    auto applyAInv = [&]( El::Matrix<Real>& y ) {
        El::cholesky::SolveAfter( El::LOWER, El::NORMAL, L, y );
    };
    const Real relTol = El::Pow( El::limits::Epsilon<Real>(), Real(0.9) );
    xComp = b;
    El::RefinedSolve
    ( applyA, applyAInv, xComp, relTol, maxRefineIts, refineProgress );

    // Form r := b - A x
    r = b;
    El::Gemv( El::NORMAL, Real(-1), A, xComp, Real(1), r );
    const Real rRefinedFrob = El::FrobeniusNorm( r );
    El::Output("|| rRefined ||_2 / || b ||_2 = ",rRefinedFrob/bFrob);

    // Form e := x - xComp
    e = x;
    e -= xComp;
    const Real eRefinedFrob = El::FrobeniusNorm( e );
    El::Output("|| eRefined ||_2 / || x ||_2 = ",eRefinedFrob/xFrob);

    // Run iterative refinement in increased precision to try to increase the
    // solution accuracy.
    typedef El::Promote<Real> RealProm;
    El::Matrix<RealProm> AProm;
    El::Copy( A, AProm );
    auto applyAProm = [&]( const El::Matrix<RealProm>& y,
                                 El::Matrix<RealProm>& Ay ) {
        El::Gemv( El::NORMAL, RealProm(1), AProm, y, Ay );
    };
    const Real relTolProm =
      Real(El::Pow( El::limits::Epsilon<RealProm>(), RealProm(0.9) ));
    El::Output
    ("Promoting from ",El::TypeName<Real>()," to ",El::TypeName<RealProm>(),
     " and setting relative tolerance to ",relTolProm);
    xComp = b;
    El::PromotedRefinedSolve
    ( applyAProm, applyAInv, xComp, relTolProm, maxRefineIts, refineProgress );

    // Form r := b - A x
    r = b;
    El::Gemv( El::NORMAL, Real(-1), A, xComp, Real(1), r );
    const Real rPromRefinedFrob = El::FrobeniusNorm( r );
    El::Output("|| rPromRefined ||_2 / || b ||_2 = ",rPromRefinedFrob/bFrob);

    // Form e := x - xComp
    e = x;
    e -= xComp;
    const Real ePromRefinedFrob = El::FrobeniusNorm( e );
    El::Output("|| ePromRefined ||_2 / || x ||_2 = ",ePromRefinedFrob/xFrob);

    El::Output("");
}