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; }
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(""); }