33 #ifndef NAVIERSTOKES_H 34 #define NAVIERSTOKES_H 1
36 #include <lifev/navier_stokes/solver/OseenSolver.hpp> 37 #include <lifev/core/mesh/ElementShapes.hpp> 38 #include <lifev/core/mesh/MeshData.hpp> 39 #include <lifev/core/array/MatrixEpetra.hpp> 40 #include <lifev/core/array/MapEpetra.hpp> 41 #include <lifev/core/mesh/MeshPartitioner.hpp> 42 #include <lifev/core/mesh/MeshData.hpp> 43 #include <lifev/navier_stokes/solver/OseenData.hpp> 44 #include <lifev/core/fem/FESpace.hpp> 45 #include <lifev/navier_stokes/fem/TimeAdvanceBDFNavierStokes.hpp> 46 #include <lifev/core/filter/ExporterEnsight.hpp> 47 #include <lifev/core/filter/ExporterHDF5.hpp> 48 #include <lifev/core/filter/ExporterEmpty.hpp> 99 template<
typename MeshType,
typename Problem>
123 const std::string defaultDataName =
"data",
124 const std::string outputName =
"navierStokes");
165 std::cout <<
"Some modifications led to changes in the l2 norm of the solution" << std::endl;
181 LifeV::Real& uL2Error, LifeV::Real& uRelError,
feSpacePtr_Type& uFESpace,
182 LifeV::Real& pL2Error, LifeV::Real& pRelError,
feSpacePtr_Type& pFESpace,
199 const std::vector<std::vector<LifeV::Real> >& uL2Error,
200 const std::vector<LifeV::UInt>& uConvergenceOrder,
201 const std::vector<std::string>& pFELabels,
202 const std::vector<std::vector<LifeV::Real> > pL2Error,
203 const std::vector<LifeV::UInt>& pConvergenceOrder,
204 const std::vector<LifeV::UInt>& meshDiscretizations,
205 LifeV::Real convTolerance);
244 using namespace LifeV;
270 std::string stringList = list;
271 std::set<UInt> setList;
276 std::string::size_type commaPos = 0;
277 while ( commaPos != std::string::npos )
279 commaPos = stringList.find (
"," );
280 setList.insert ( atoi ( stringList.substr ( 0, commaPos ).c_str() ) );
281 stringList = stringList.substr ( commaPos + 1 );
283 setList.insert ( atoi ( stringList.c_str() ) );
288 template<
typename MeshType,
typename Problem>
309 template<
typename MeshType,
typename Problem>
312 const std::string defaultDataName,
313 const std::string outputName)
319 std::string data_file_name = command_line.follow (defaultDataName.c_str(), 2,
"-f",
"--file");
322 M_data->data_file_name = data_file_name;
324 M_data->Re = dataFile (
"fluid/problem/Re", 1. );
325 M_data->nu = dataFile (
"fluid/physics/viscosity", 1. ) /
326 dataFile (
"fluid/physics/density", 1. );
329 std::string testType = dataFile
("NavierStokes/test", "none");
330 if (testType ==
"none")
334 else if (testType ==
"accuracy")
338 else if (testType ==
"space_convergence")
344 std::cout <<
"[Error] Unknown test method" << std::endl;
348 M_convTol = dataFile (
"NavierStokes/space_convergence_tolerance", 1.0);
349 M_accuracyTol = dataFile (
"NavierStokes/accuracy_tolerance", 1.0);
352 std::string initType = dataFile
("NavierStokes/initialization", "projection");
353 if (initType ==
"projection")
357 else if (initType ==
"interpolation")
363 std::cout <<
"[Error] Unknown initialization method" << std::endl;
370 std::string meshSource = dataFile
( "NavierStokes/mesh_source", "regular_mesh");
371 if (meshSource ==
"regular_mesh")
375 else if (meshSource ==
"file")
381 std::cout <<
"[Error] Unknown mesh source" << std::endl;
388 std::cout <<
"[Error] You cannot use mesh files to test the space convergence." << std::endl;
397 M_data->comm.reset (
new Epetra_MpiComm ( MPI_COMM_WORLD ) );
399 MPI_Comm_size (MPI_COMM_WORLD, &ntasks);
401 M_data->comm.reset (
new Epetra_SerialComm() );
406 template<
typename MeshType,
typename Problem>
409 LifeV::Real& uL2Error, LifeV::Real& uRelError,
feSpacePtr_Type& uFESpace,
410 LifeV::Real& pL2Error, LifeV::Real& pRelError,
feSpacePtr_Type& pFESpace,
416 vector_Type velpressure ( velocityAndPressureSolution, Repeated );
418 velpressure = velocityAndPressureSolution;
419 vel.subset (velpressure);
420 press.subset (velpressure, uFESpace->dim() *uFESpace->fieldDim() );
422 uL2Error = uFESpace->l2Error (problem_Type::uexact, vel , time, &uRelError );
423 pL2Error = pFESpace->l20Error (problem_Type::pexact, press, time, &pRelError );
426 template<
typename MeshType,
typename Problem>
429 const std::vector<std::vector<LifeV::Real> >& uL2Error,
430 const std::vector<UInt>& uConvergenceOrder,
431 const std::vector<std::string>& pFELabels,
432 const std::vector<std::vector<LifeV::Real> > pL2Error,
433 const std::vector<UInt>& pConvergenceOrder,
434 const std::vector<UInt>& meshDiscretizations,
435 LifeV::Real convTolerance)
439 std::cout <<
"Checking the convergence:" << std::endl;
443 Real h1 (0.0), h2 (0.0);
444 Real uBound (0.0), pBound (0.0);
445 Real uErrRatio (0.0), pErrRatio (0.0);
446 std::string status (
"");
448 UInt numFELabels (uFELabels.size() );
449 UInt numDiscretizations (meshDiscretizations.size() );
451 for (
UInt iFELabel (0); iFELabel < numFELabels; ++iFELabel)
453 std::cout <<
" - " << uFELabels[iFELabel] <<
"-" << pFELabels[iFELabel] <<
" ... " << std::endl;
458 for (
UInt jDiscretization (0); jDiscretization < numDiscretizations - 1; ++jDiscretization)
460 h1 = 1.0 / meshDiscretizations[jDiscretization];
461 h2 = 1.0 / meshDiscretizations[jDiscretization + 1];
463 uBound = convTolerance * pow (h1 / h2,
int (uConvergenceOrder[iFELabel]) );
464 pBound = convTolerance * pow (h1 / h2,
int (pConvergenceOrder[iFELabel]) );
466 uErrRatio = uL2Error[iFELabel][jDiscretization] / uL2Error[iFELabel][jDiscretization + 1];
467 pErrRatio = pL2Error[iFELabel][jDiscretization] / pL2Error[iFELabel][jDiscretization + 1];
469 if (uErrRatio < uBound)
474 if (pErrRatio < pBound)
479 std::cout <<
" " <<
" (velocity: " << uErrRatio <<
">=?" << uBound
480 <<
", pressure: " << pErrRatio <<
">=?" << pBound << std::endl;
482 std::cout <<
" Status: " << status << std::endl;
489 template<
typename MeshType,
typename Problem>
493 bool verbose = (M_data->comm->MyPID() == 0);
495 MPI_Comm_size (MPI_COMM_WORLD, &nproc);
498 std::cout <<
"[[BEGIN_SIMULATION]]" << std::endl << std::endl;
500 std::cout <<
"[Initilization of MPI]" << std::endl;
502 std::cout <<
"Using MPI (" << nproc <<
" proc.)" << std::endl;
504 std::cout <<
"Using serial version" << std::endl;
524 std::cout << std::endl <<
"[Loading the data]" << std::endl;
526 GetPot dataFile ( M_data->data_file_name.c_str() );
532 std::cout <<
"Test : checks the accuracy of the solution" << std::endl;
534 case SpaceConvergence:
535 std::cout <<
"Test : checks the convergence in space of the solution" << std::endl;
543 UInt numDiscretizations;
547 numDiscretizations = dataFile
( "fluid/space_discretization/mesh_number", 1
);
548 for (
UInt i ( 0 ); i < numDiscretizations; ++i )
550 M_meshDiscretization.push_back (dataFile (
"fluid/space_discretization/mesh_size", 8, i ) );
555 M_meshDiscretization.push_back (0);
556 numDiscretizations = 1;
559 UInt numFELabels = dataFile
( "fluid/space_discretization/FE_number", 1
);
563 for (
UInt i ( 0 ); i < numFELabels; ++i )
565 M_uConvergenceOrder.push_back (dataFile (
"fluid/space_discretization/vel_conv_order", 2, i ) );
567 for (
UInt i ( 0 ); i < numFELabels; ++i )
569 M_pConvergenceOrder.push_back (dataFile (
"fluid/space_discretization/press_conv_order", 2, i ) );
574 for (
UInt i ( 0 ); i < numFELabels; ++i )
576 M_uFELabels.push_back (dataFile (
"fluid/space_discretization/vel_order",
"P1", i ) );
578 for (
UInt i ( 0 ); i < numFELabels; ++i )
580 M_pFELabels.push_back (dataFile (
"fluid/space_discretization/press_order",
"P1", i ) );
584 std::vector<std::vector<LifeV::Real> > uL2Error;
585 std::vector<std::vector<LifeV::Real> > pL2Error;
588 std::vector<LifeV::Real> tmpVec (numDiscretizations, 0.0);
589 for (
UInt iFELabel (0); iFELabel < numFELabels; ++iFELabel)
591 uL2Error.push_back (tmpVec);
592 pL2Error.push_back (tmpVec);
598 std::cout <<
"Initialization time (pre-run): " << initChrono.diff() <<
" s." << std::endl;
602 for (
UInt jDiscretization (0); jDiscretization < numDiscretizations; ++jDiscretization)
604 UInt mElem = M_meshDiscretization[jDiscretization];
607 for (
UInt iFELabel (0); iFELabel < numFELabels; ++iFELabel)
611 std::cout << std::endl <<
"[[BEGIN_RUN_" << jDiscretization* numFELabels + iFELabel <<
"]]" << std::endl;
620 std::string fileName (
"norm_");
621 std::ostringstream oss;
623 fileName.append (oss.str() );
624 fileName.append (
"_");
625 fileName.append (M_uFELabels[iFELabel]);
626 fileName.append (M_pFELabels[iFELabel]);
627 fileName.append (
".txt");
628 M_outNorm.open (fileName.c_str() );
629 M_outNorm <<
"% time / u L2 error / L2 rel error p L2 error / L2 rel error \n" << std::flush;
637 std::cout <<
"[Loading the mesh]" << std::endl;
640 std::shared_ptr<mesh_Type > fullMeshPtr (
new mesh_Type ( M_data->comm ) );
660 meshData.setup (dataFile,
"fluid/space_discretization");
661 readMesh (*fullMeshPtr, meshData);
663 if (verbose) std::cout <<
"Mesh source: file(" 664 << meshData.meshDir() << meshData.meshFile() <<
")" << std::endl;
670 std::cout << std::endl <<
"Error: Unknown source type for the mesh" << std::endl;
677 std::cout <<
"Partitioning the mesh ... " << std::flush;
679 std::shared_ptr<mesh_Type > localMeshPtr;
681 MeshPartitioner<
mesh_Type > meshPart (fullMeshPtr, M_data->comm);
682 localMeshPtr = meshPart.meshPartition();
691 std::cout << std::endl <<
"[Creating the FE spaces]" << std::endl;
693 std::string uOrder = M_uFELabels[iFELabel];
694 std::string pOrder = M_pFELabels[iFELabel];
696 if (verbose) std::cout <<
"FE for the velocity: " << uOrder << std::endl
697 <<
"FE for the pressure: " << pOrder << std::endl;
701 std::cout <<
"Building the velocity FE space ... " << std::flush;
704 uFESpace.reset (
new feSpace_Type (localMeshPtr, uOrder, geoDimensions, M_data->comm) );
707 std::cout <<
"ok." << std::endl;
712 std::cout <<
"Building the pressure FE space ... " << std::flush;
715 pFESpace.reset (
new feSpace_Type (localMeshPtr, pOrder, 1, M_data->comm) );
718 std::cout <<
"ok." << std::endl;
721 UInt totalVelDof = uFESpace->dof().numTotalDof();
722 UInt totalPressDof = pFESpace->dof().numTotalDof();
725 UInt pressureOffset = uFESpace->fieldDim() * uFESpace->dof().numTotalDof();
729 std::cout <<
"Total Velocity Dof = " << totalVelDof << std::endl;
733 std::cout <<
"Total Pressure Dof = " << totalPressDof << std::endl;
741 std::cout << std::endl <<
"[Boundary conditions]" << std::endl;
743 std::string dirichletList = dataFile
( "fluid/problem/dirichletList", "" );
744 std::set<UInt> dirichletMarkers = parseList ( dirichletList );
745 std::string neumannList = dataFile
( "fluid/problem/neumannList", "" );
746 std::set<UInt> neumannMarkers = parseList ( neumannList );
752 for (std::set<UInt>::const_iterator it = dirichletMarkers.begin();
753 it != dirichletMarkers.end(); ++it)
755 bcH.addBC (
"Wall", *it, Essential, Full, uWall, geoDimensions );
757 for (std::set<UInt>::const_iterator it = neumannMarkers.begin();
758 it != neumannMarkers.end(); ++it)
760 bcH.addBC (
"Flux", *it, Natural, Full, uNeumann, geoDimensions );
764 bcH.bcUpdate ( *localMeshPtr, uFESpace->feBd(), uFESpace->dof() );
771 std::cout << std::endl <<
"[Creating the problem]" << std::endl;
773 std::shared_ptr<OseenData> oseenData (
new OseenData() );
774 oseenData->setup ( dataFile );
778 std::cout <<
"Time discretization order " << oseenData->dataTimeAdvance()->orderBDF() << std::endl;
781 OseenSolver< mesh_Type > fluid (oseenData,
788 fluid.setUp (dataFile);
791 MPI_Barrier (MPI_COMM_WORLD);
798 std::cout << std::endl <<
"[Initialization of the simulation]" << std::endl;
800 Real dt = oseenData->dataTime()->timeStep();
801 Real t0 = oseenData->dataTime()->initialTime();
802 Real tFinal = oseenData->dataTime()->endTime();
807 bdf.setup (oseenData->dataTimeAdvance()->orderBDF() );
815 t0 -= dt * bdf.bdfVelocity().order();
819 std::cout <<
"Computing the initial solution ... " << std::endl;
825 MPI_Barrier (MPI_COMM_WORLD);
827 oseenData->dataTime()->setTime (t0);
828 fluid.initialize ( problem_Type::uexact, problem_Type::pexact );
830 bdf.bdfVelocity().setInitialCondition ( *fluid.solution() );
853 for ( ; time <= oseenData->dataTime()->initialTime() + dt / 2.; time += dt)
856 oseenData->dataTime()->setTime (time);
861 fluid.initialize ( problem_Type::uexact, problem_Type::pexact );
863 beta = *fluid.solution();
865 if (M_initMethod == Projection)
867 uFESpace->interpolate (
static_cast<
typename feSpace_Type::function_Type> ( problem_Type::uderexact ), rhs, time);
869 rhs = fluid.matrixMass() * rhs;
870 fluid.updateSystem ( 0., beta, rhs );
875 LifeV::Real urelerr, prelerr, ul2error, pl2error;
877 computeErrors (*fluid.solution(),
878 ul2error, urelerr, uFESpace,
879 pl2error, prelerr, pFESpace,
882 if (verbose && M_exportNorms)
884 M_outNorm << time <<
" " 888 << prelerr <<
"\n" << std::flush;
893 bdf.bdfVelocity().shiftRight ( *fluid.solution() );
897 fluid.resetPreconditioner();
899 std::shared_ptr< Exporter<mesh_Type > > exporter;
904 vector_Type exactPress (pFESpace->map(), Repeated);
909 std::string
const exporterType = dataFile
( "exporter/type", "ensight");
912 if (exporterType.compare (
"hdf5") == 0)
914 exporter.reset (
new ExporterHDF5<mesh_Type > ( dataFile, M_outputName ) );
915 exporter->setPostDir (
"./" );
916 exporter->setMeshProcId ( localMeshPtr, M_data->comm->MyPID() );
921 if (exporterType.compare (
"none") == 0)
923 exporter.reset (
new ExporterEmpty<mesh_Type > ( dataFile, localMeshPtr, M_outputName, M_data->comm->MyPID() ) );
927 exporter.reset (
new ExporterEnsight<mesh_Type > ( dataFile, localMeshPtr, M_outputName, M_data->comm->MyPID() ) );
931 velAndPressure.reset (
new vector_Type (*fluid.solution(), exporter->mapType() ) );
934 exactPressPtr.reset (
new vector_Type (exactPress, exporter->mapType() ) );
935 pFESpace->interpolate (
static_cast<
typename feSpace_Type::function_Type> ( problem_Type::pexact ), *exactPressPtr, 0 );
936 exactVelPtr.reset (
new vector_Type (exactVel, exporter->mapType() ) );
937 uFESpace->interpolate (
static_cast<
typename feSpace_Type::function_Type> ( problem_Type::uexact ), *exactVelPtr, 0 );
940 exporter->addVariable ( ExporterData<mesh_Type>::VectorField,
"velocity", uFESpace,
941 velAndPressure, UInt (0) );
942 exporter->addVariable ( ExporterData<mesh_Type>::ScalarField,
"pressure", pFESpace,
943 velAndPressure, pressureOffset );
946 exporter->addVariable ( ExporterData<mesh_Type>::VectorField,
"exactVelocity", uFESpace,
947 exactVelPtr, UInt (0) );
948 exporter->addVariable ( ExporterData<mesh_Type>::ScalarField,
"exactPressure", pFESpace,
949 exactPressPtr, UInt (0) );
951 exporter->postProcess ( 0 );
956 std::cout <<
"Initialization time: " << initChrono.diff() <<
" s." << std::endl;
964 std::cout << std::endl <<
"[Solving the problem]" << std::endl;
968 for ( ; time <= tFinal + dt / 2.; time += dt, iter++)
973 oseenData->dataTime()->setTime (time);
977 std::cout <<
"[t = " << oseenData->dataTime()->time() <<
" s.]" << std::endl;
980 double alpha = bdf.bdfVelocity().coefficientFirstDerivative ( 0 ) / oseenData->dataTime()->timeStep();
982 bdf.bdfVelocity().extrapolation (beta);
983 bdf.bdfVelocity().updateRHSContribution ( oseenData->dataTime()->timeStep() );
985 fluid.getDisplayer().leaderPrint (
"alpha ", alpha);
986 fluid.getDisplayer().leaderPrint (
"\n");
987 fluid.getDisplayer().leaderPrint (
"norm beta ", beta.norm2() );
988 fluid.getDisplayer().leaderPrint (
"\n");
989 fluid.getDisplayer().leaderPrint (
"norm rhs ", rhs.norm2() );
990 fluid.getDisplayer().leaderPrint (
"\n");
992 if (oseenData->conservativeFormulation() )
994 rhs = fluid.matrixMass() * bdf.bdfVelocity().rhsContributionFirstDerivative();
997 fluid.updateSystem ( alpha, beta, rhs );
999 if (!oseenData->conservativeFormulation() )
1001 rhs = fluid.matrixMass() * bdf.bdfVelocity().rhsContributionFirstDerivative();
1004 fluid.iterate ( bcH );
1006 bdf.bdfVelocity().shiftRight ( *fluid.solution() );
1009 LifeV::Real urelerr, prelerr, ul2error, pl2error;
1011 computeErrors (*fluid.solution(),
1012 ul2error, urelerr, uFESpace,
1013 pl2error, prelerr, pFESpace,
1018 M_outNorm << time <<
" " 1022 << prelerr <<
"\n" << std::flush;
1026 uL2Error[iFELabel][jDiscretization] = ul2error;
1027 pL2Error[iFELabel][jDiscretization] = pl2error;
1030 *velAndPressure = *fluid.solution();
1033 pFESpace->interpolate (
static_cast<
typename feSpace_Type::function_Type> ( problem_Type::pexact ), *exactPressPtr, time );
1034 uFESpace->interpolate (
static_cast<
typename feSpace_Type::function_Type> ( problem_Type::uexact ), *exactVelPtr, time );
1036 exporter->postProcess ( time );
1039 MPI_Barrier (MPI_COMM_WORLD);
1044 std::cout <<
"Iteration time: " << initChrono.diff() <<
" s." << std::endl << std::endl;
1057 LifeV::Real urelerr, prelerr, ul2error, pl2error;
1059 computeErrors (*fluid.solution(),
1060 ul2error, urelerr, uFESpace,
1061 pl2error, prelerr, pFESpace,
1064 if (verbose) std::cout <<
"Relative error: E(u)=" << urelerr <<
", E(p)=" << prelerr << std::endl
1065 <<
"Tolerance=" << M_accuracyTol << std::endl;
1067 if (urelerr > M_accuracyTol || prelerr > M_accuracyTol)
1071 std::cout <<
"TEST_NAVIERSTOKES STATUS: ECHEC" << std::endl;
1081 std::cout <<
"Total run time: " << runChrono.diff() <<
" s." << std::endl;
1085 std::cout <<
"[[END_RUN_" << jDiscretization* numFELabels + iFELabel <<
"]]" << std::endl;
1095 success = checkConvergenceRate (M_uFELabels, uL2Error, M_uConvergenceOrder,
1096 M_pFELabels, pL2Error, M_pConvergenceOrder,
1097 M_meshDiscretization,
1104 std::cout <<
"TEST_NAVIERSTOKES STATUS: ECHEC" << std::endl;
1113 std::cout << std::endl <<
"Total simulation time:" << globalChrono.diff() <<
" s." << std::endl;
1117 std::cout <<
"TEST_NAVIERSTOKES_STATUS: SUCCESS" << std::endl;
1121 std::cout << std::endl <<
"[[END_SIMULATION]]" << std::endl;
fluid_Type::matrix_Type matrix_Type
Real zero_scalar(const Real &, const Real &, const Real &, const Real &, const ID &)
Null function used to define the boundary conditions.
void start()
Start the timer.
~NavierStokes()
Destructor.
std::function< Real(Real const &, Real const &, Real const &, Real const &, ID const &) > fct_Type
LifeV::OseenSolver< mesh_Type > fluid_Type
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
BCHandler - class for handling boundary conditions.
void run()
Launches the simulation.
MeshSourceType M_meshSource
int32_type Int
Generic integer data.
std::vector< std::string > M_uFELabels
LifeV::Real M_accuracyTol
std::set< UInt > parseList(const std::string &list)
BCFunctionBase - class that holds the function used for prescribing boundary conditions.
Epetra_Import const & importer()
Getter for the Epetra_Import.
std::shared_ptr< feSpace_Type > feSpacePtr_Type
std::shared_ptr< vector_Type > vectorPtr_Type
NavierStokes(int argc, char **argv, const std::string defaultDataName="data", const std::string outputName="navierStokes")
Constructor.
NavierStokes Simulation class.
void computeErrors(const vector_Type &velocityAndPressureSolution, LifeV::Real &uL2Error, LifeV::Real &uRelError, feSpacePtr_Type &uFESpace, LifeV::Real &pL2Error, LifeV::Real &pRelError, feSpacePtr_Type &pFESpace, LifeV::Real time)
Computes the L2 error and the relative L2 error with the exact solution.
RESULT_CHANGED_EXCEPTION()
std::vector< LifeV::UInt > M_pConvergenceOrder
MeshData - class for handling spatial discretization.
InitializationType M_initMethod
double Real
Generic real data.
int operator()(const char *VarName, int Default) const
std::vector< LifeV::UInt > M_meshDiscretization
std::vector< std::string > M_pFELabels
bool M_exportExactSolutions
const std::string operator()(const char *VarName, const char *Default) const
void stop()
Stop the timer.
GetPot(const STRING_VECTOR &FileNameList)
bool operator()(const char *VarName, bool Default) const
bool checkConvergenceRate(const std::vector< std::string > &uFELabels, const std::vector< std::vector< LifeV::Real > > &uL2Error, const std::vector< LifeV::UInt > &uConvergenceOrder, const std::vector< std::string > &pFELabels, const std::vector< std::vector< LifeV::Real > > pL2Error, const std::vector< LifeV::UInt > &pConvergenceOrder, const std::vector< LifeV::UInt > &meshDiscretizations, LifeV::Real convTolerance)
Method to check the convergence rate of the solution.
std::shared_ptr< Epetra_Comm > comm
LifeV::FESpace< mesh_Type, LifeV::MapEpetra > feSpace_Type
std::string data_file_name
fluid_Type::vector_Type vector_Type
uint32_type UInt
generic unsigned integer (used mainly for addressing)
std::shared_ptr< Private > M_data
std::vector< LifeV::UInt > M_uConvergenceOrder