LifeV
lifev/eta/examples/vortex_shedding/main.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3  *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23  *******************************************************************************
24  */
25 //@HEADER
26 
27 /*!
28  @file
29  @brief
30 
31  @author Toni Lassila <toni.lassila@epfl.ch>
32  @author Samuel Quinodoz <samuel.quinodoz@epfl.ch>
33  @date 23-11-2012
34  */
35 
36 // Tell the compiler to ignore specific kind of warnings:
37 #pragma GCC diagnostic ignored "-Wunused-variable"
38 #pragma GCC diagnostic ignored "-Wunused-parameter"
39 
40 #include <Epetra_ConfigDefs.h>
41 #ifdef EPETRA_MPI
42 #include <mpi.h>
43 #include <Epetra_MpiComm.h>
44 #else
45 #include <Epetra_SerialComm.h>
46 #endif
47 
48 //Tell the compiler to restore the warning previously silented
49 #pragma GCC diagnostic warning "-Wunused-variable"
50 #pragma GCC diagnostic warning "-Wunused-parameter"
51 
52 #include <lifev/core/LifeV.hpp>
53 #include <lifev/core/mesh/RegionMesh3DStructured.hpp>
54 #include <lifev/core/mesh/MeshData.hpp>
55 #include <lifev/core/mesh/RegionMesh.hpp>
56 #include <lifev/core/mesh/MeshPartitioner.hpp>
57 
58 #include <lifev/eta/expression/Integrate.hpp>
59 #include <lifev/core/fem/FESpace.hpp>
60 #include <lifev/eta/fem/ETFESpace.hpp>
61 
62 #include <lifev/core/fem/BCManage.hpp>
63 
64 #include <lifev/core/array/MatrixEpetra.hpp>
65 #include <lifev/core/array/VectorEpetra.hpp>
66 #include <lifev/core/array/MatrixEpetraStructured.hpp>
67 #include <lifev/core/array/VectorBlockMonolithicEpetra.hpp>
68 
69 
70 #include <lifev/core/algorithm/PreconditionerIfpack.hpp>
71 #include <lifev/core/algorithm/PreconditionerML.hpp>
72 #include <lifev/core/algorithm/SolverAztecOO.hpp>
73 #include <lifev/core/filter/ExporterHDF5.hpp>
74 #include <lifev/core/fem/TimeAdvanceBDF.hpp>
75 
76 #include <lifev/navier_stokes/solver/StabilizationIP.hpp>
77 #include <lifev/core/fem/Assembly.hpp>
78 #include <lifev/core/fem/AssemblyElemental.hpp>
79 
80 using namespace LifeV;
81 
82 namespace
83 {
84 
88 enum ConvectionType {Explicit, SemiImplicit};
90 
92 typedef MatrixEpetra<Real> matrix_Type;
93 typedef VectorEpetra vector_Type;
95 
96 typedef MatrixEpetraStructured<Real> matrix_block_type;
97 typedef VectorBlockMonolithicEpetra vector_block_type;
99 
100 typedef FESpace< mesh_Type, MapEpetra > fespace_Type;
102 
103 typedef FESpace< mesh_Type, MapEpetra > fespace_Type;
105 
106 typedef ETFESpace< mesh_Type, MapEpetra, 3, 3 > etaUspace_Type;
108 
109 typedef ETFESpace< mesh_Type, MapEpetra, 3, 1 > etaPspace_Type;
111 
112 }
113 
114 Real fluxFunction (const Real& t, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& /*i*/)
115 {
116  return (1 * t / 0.5 * (t < 0.5) + 1 * (t > 0.5) ); // Ramp function
117 }
118 
119 Real zeroFunction (const Real& /*t*/, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& /*i*/)
120 {
121  return 0;
122 }
123 
124 Real inflowFunction (const Real& t, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& i)
125 {
126  if (i == 0)
127  {
128  Real ux = 1; // flat velocity profile
129  return (1 * ux * t / 0.5 * (t < 0.5) + 1 * ux * (t > 0.5) );
130  }
131  else
132  {
133  return 0;
134  }
135 
136 }
137 
138 /* NormalizeFct */
139 class NormalizeFct
140 {
141 public:
143 
144  return_Type operator() (const VectorSmall<3>& value)
145  {
146  Real norm (sqrt ( value[0]*value[0] + value[1]*value[1] + value[2]*value[2]) );
147 
148  if (norm > 0)
149  {
150  return value * (1.0 / norm);
151  }
152  return value;
153  }
154 
156  NormalizeFct (const NormalizeFct&) {}
158 };
159 
160 
161 /* NormalizeFct */
162 class NormFct
163 {
164 public:
165  typedef Real return_Type;
166 
167  return_Type operator() (const VectorSmall<3> value)
168  {
169  Real norm (sqrt ( value[0]*value[0] + value[1]*value[1] + value[2]*value[2]) );
170 
171  return norm;
172  }
173 
174  NormFct() {}
175  NormFct (const NormFct&) {}
176  ~NormFct() {}
177 };
178 
179 int
180 main ( int argc, char** argv )
181 {
182  // +-----------------------------------------------+
183  // | Initialization of MPI |
184  // +-----------------------------------------------+
185 
186 #ifdef HAVE_MPI
187  MPI_Init (&argc, &argv);
188  std::shared_ptr<Epetra_Comm> Comm (new Epetra_MpiComm (MPI_COMM_WORLD) );
189  int nproc;
190  MPI_Comm_size (MPI_COMM_WORLD, &nproc);
191 #else
192  std::shared_ptr<Epetra_Comm> Comm (new Epetra_SerialComm);
193 #endif
194 
195  const bool verbose (Comm->MyPID() == 0);
196  if (verbose)
197  {
198  std::cout
199  << " +-----------------------------------------------+" << std::endl
200  << " | Vortex shedding example w/ETA assembly |" << std::endl
201  << " +-----------------------------------------------+" << std::endl
202  << std::endl
203  << " +-----------------------------------------------+" << std::endl
204  << " | Author: Toni Lassila |" << std::endl
205  << " | Date: 2012-11-13 |" << std::endl
206  << " +-----------------------------------------------+" << std::endl
207  << std::endl;
208 
209  std::cout << "[Initilization of MPI]" << std::endl;
210 #ifdef HAVE_MPI
211  std::cout << "Using MPI (" << nproc << " proc.)" << std::endl;
212 #else
213  std::cout << "Using serial version" << std::endl;
214 #endif
215  }
216 
217  // +-----------------------------------------------+
218  // | Loading the data |
219  // +-----------------------------------------------+
220  if (verbose)
221  {
222  std::cout << std::endl << "[Loading the data]" << std::endl;
223  }
224  LifeChrono globalChrono;
225  LifeChrono initChrono;
226  LifeChrono iterChrono;
227 
228  globalChrono.start();
229  initChrono.start();
230 
231  // **** Stupid GetPot stuff ****
232  GetPot command_line (argc, argv);
233  const std::string dataFileName = command_line.follow ("data", 2, "-f", "--file");
234  GetPot dataFile (dataFileName);
235  // *****************************
236 
237  // Physical quantity (corresponds to Re = 100)
238  const Real viscosity = 0.01 / 5;
239  const Real density = 1.0;
240 
241  // Time discretization
242  const Real initialTime = 0.0;
243  const Real endTime = 100.0;
244  const Real timestep = 1e-1;
245 
246  // Space discretization
247  const UInt numDimensions = 3;
248 
249  // Time discretization
250  UInt BDFOrder = 2;
251 
252  // Stabilization method
253  const StabilizationType stabilizationMethod = VMS;
254 
255  // Numerical scheme
256  const InitType initializationMethod = Interpolation;
257  const ConvectionType convectionTerm = SemiImplicit;
258 
259  // +-----------------------------------------------+
260  // | Loading the mesh |
261  // +-----------------------------------------------+
262  if (verbose)
263  {
264  std::cout << std::endl << "[Loading the mesh]" << std::endl;
265  }
266 
267  std::shared_ptr<RegionMesh<LinearTetra> > fullMeshPtr (new RegionMesh<LinearTetra>);
268 
269 
270  MeshData meshData;
271  meshData.setup (dataFile, "fluid/space_discretization");
272  readMesh (*fullMeshPtr, meshData);
273 
274  if (verbose) std::cout << "Mesh source: file("
275  << meshData.meshDir() << meshData.meshFile() << ")" << std::endl;
276 
277  if (verbose)
278  {
279  std::cout << "Mesh size : " <<
280  MeshUtility::MeshStatistics::computeSize (*fullMeshPtr).maxH << std::endl;
281  }
282  if (verbose)
283  {
284  std::cout << "Partitioning the mesh ... " << std::endl;
285  }
286  MeshPartitioner< RegionMesh<LinearTetra> > meshPart (fullMeshPtr, Comm);
287  fullMeshPtr.reset(); //Freeing the global mesh to save memory
288 
289  // +-----------------------------------------------+
290  // | Creating the FE spaces |
291  // +-----------------------------------------------+
292  if (verbose)
293  {
294  std::cout << std::endl << "[Creating the FE spaces]" << std::endl;
295  }
296  std::string uOrder ("P1");
297  std::string pOrder ("P1");
298 
299  if (verbose) std::cout << "FE for the velocity: " << uOrder << std::endl
300  << "FE for the pressure: " << pOrder << std::endl;
301 
302  if (verbose)
303  {
304  std::cout << "Building the velocity FE space ... " << std::flush;
305  }
306  fespacePtr_Type uFESpace ( new FESpace< mesh_Type, MapEpetra > (meshPart, uOrder, numDimensions, Comm) );
307  if (verbose)
308  {
309  std::cout << "ok." << std::endl;
310  }
311 
312  if (verbose)
313  {
314  std::cout << "Building the pressure FE space ... " << std::flush;
315  }
316  fespacePtr_Type pFESpace ( new FESpace< mesh_Type, MapEpetra > (meshPart, pOrder, 1, Comm) );
317  if (verbose)
318  {
319  std::cout << "ok." << std::endl;
320  }
321 
322  // Define the ETA spaces for velocity and pressure
323  etaUspacePtr_Type ETuFESpace ( new etaUspace_Type (meshPart, & (uFESpace->refFE() ), Comm) );
324  etaPspacePtr_Type ETpFESpace ( new etaPspace_Type (meshPart, & (pFESpace->refFE() ), Comm) );
325 
326  // Creation of the total map
327  MapEpetra solutionMap (uFESpace->map() + pFESpace->map() );
328 
329  // Pressure offset in the vector
330  UInt pressureOffset = numDimensions * uFESpace->dof().numTotalDof();
331 
332  if (verbose)
333  {
334  std::cout << "Total Velocity Dof: " << pressureOffset << std::endl;
335  }
336  if (verbose)
337  {
338  std::cout << "Total Pressure Dof: " << pFESpace->dof().numTotalDof() << std::endl;
339  }
340 
341  // +-----------------------------------------------+
342  // | Boundary conditions |
343  // +-----------------------------------------------+
344  if (verbose)
345  {
346  std::cout << std::endl << "[Boundary conditions]" << std::endl;
347  }
348  BCHandler bcHandler;
349  BCFunctionBase uZero ( zeroFunction );
350  BCFunctionBase uInflow ( inflowFunction );
351 
352 
353  std::vector<LifeV::ID> zComp (1);
354  zComp[0] = 2;
355 
356  if (verbose)
357  {
358  std::cout << "Setting Neumann BC... " << std::flush;
359  }
360  bcHandler.addBC ( "Outflow", 3, Natural, Full, uZero, 3 );
361  if (verbose)
362  {
363  std::cout << "ok." << std::endl;
364  }
365 
366  if (verbose)
367  {
368  std::cout << "Setting Dirichlet BC... " << std::flush;
369  }
370  bcHandler.addBC ( "Inflow", 1, Essential, Full, uInflow, 3 );
371  bcHandler.addBC ( "Wall", 2, Essential, Full, uInflow, 3 );
372  bcHandler.addBC ( "Cube", 4, Essential, Full, uZero, 3 );
373  bcHandler.addBC ( "Symmetry", 5, Essential, Component, uZero, zComp );
374 
375  if (verbose)
376  {
377  std::cout << "ok." << std::endl;
378  }
379 
380  // Update the BCHandler (internal data related to FE)
381  bcHandler.bcUpdate ( *meshPart.meshPartition(), uFESpace->feBd(), uFESpace->dof() );
382 
383  // +-----------------------------------------------+
384  // | Matrices Assembly |
385  // +-----------------------------------------------+
386  if (verbose)
387  {
388  std::cout << std::endl << "[Matrices Assembly]" << std::endl;
389  }
390 
391  if (verbose)
392  {
393  std::cout << "Defining the matrices... " << std::flush;
394  }
395 
396  // Initialize the full matrix, the nonconvective part, and the mass matrix (for time advancing)
397  std::shared_ptr<matrix_block_type> systemMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
398  std::shared_ptr<matrix_block_type> baseMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
399  std::shared_ptr<matrix_block_type> convMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
400  std::shared_ptr<matrix_block_type> massMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
401 
402  *systemMatrix *= 0.0;
403  *baseMatrix *= 0.0;
404  *convMatrix *= 0.0;
405  *massMatrix *= 0.0;
406 
407  if (verbose)
408  {
409  std::cout << "done" << std::endl;
410  }
411 
412  // Perform the assembly of the base matrix with ETA
413 
414  {
415  std::shared_ptr<NormalizeFct> normalize (new NormalizeFct);
416 
417  using namespace ExpressionAssembly;
418 
419  // Use of stiff-strain formulation due to stabilization is mandatory
420  integrate (
421  elements (ETuFESpace->mesh() ), // Mesh
422  uFESpace->qr(), // QR
423  ETuFESpace,
424  ETuFESpace,
425  0.5 * viscosity * dot (grad (phi_i) + transpose (grad (phi_i) ), grad (phi_j) + transpose (grad (phi_j) ) )
426  )
427  >> baseMatrix->block (0, 0);
428 
429  integrate (
430  elements (ETuFESpace->mesh() ), // Mesh
431  uFESpace->qr(), // QR
432  ETuFESpace,
433  ETpFESpace,
434  value (-1.0) * phi_j * div (phi_i)
435  )
436  >> baseMatrix->block (0, 1);
437 
438 
439  integrate (
440  elements (ETuFESpace->mesh() ), // Mesh
441  uFESpace->qr(), // QR
442  ETpFESpace,
443  ETuFESpace,
444  phi_i * div (phi_j)
445  )
446  >> baseMatrix->block (1, 0);
447 
448  integrate (
449  elements (ETuFESpace->mesh() ), // Mesh
450  uFESpace->qr(), // QR
451  ETuFESpace,
452  ETuFESpace,
453  // NS
454  dot (phi_i, phi_j)
455  )
456  >> massMatrix->block (0, 0);
457  }
458 
459  if (verbose)
460  {
461  std::cout << "done" << std::endl;
462  }
463 
464  if (verbose)
465  {
466  std::cout << "Closing the matrices... " << std::flush;
467  }
468  baseMatrix->globalAssemble();
469  massMatrix->globalAssemble();
470  convMatrix->globalAssemble();
471 
472  if (verbose)
473  {
474  std::cout << "done" << std::endl;
475  }
476 
477  // +-----------------------------------------------+
478  // | Solver initialization |
479  // +-----------------------------------------------+
480  if (verbose)
481  {
482  std::cout << std::endl << "[Solver initialization]" << std::endl;
483  }
484  SolverAztecOO linearSolver;
485 
486  if (verbose)
487  {
488  std::cout << "Setting up the solver... " << std::flush;
489  }
490  linearSolver.setDataFromGetPot (dataFile, "solver");
491  linearSolver.setupPreconditioner (dataFile, "prec");
492  if (verbose)
493  {
494  std::cout << "done" << std::endl;
495  }
496 
497  linearSolver.setCommunicator (Comm);
498 
499  // +-----------------------------------------------+
500  // | Initialization of the simulation |
501  // +-----------------------------------------------+
502  if (verbose)
503  {
504  std::cout << std::endl << "[Initialization of the simulation]" << std::endl;
505  }
506  if (verbose)
507  {
508  std::cout << "Creation of vectors... " << std::flush;
509  }
510  vectorPtr_Type rhs;
511  vectorPtr_Type prevRhs;
512 
513  rhs.reset (new vector_Type (solutionMap, Unique) );
514  prevRhs.reset (new vector_Type (solutionMap, Unique) );
515 
516  vectorPtr_Type velocityExtrapolated;
517  velocityExtrapolated.reset (new vector_Type (solutionMap, Repeated) );
518 
519  vector_Type convect (rhs->map() );
520 
521  vectorPtr_Type velocity;
522  velocity.reset (new vector_Type (uFESpace->map(), Unique) );
523 
524  vectorPtr_Type pressure;
525  vectorPtr_Type prevPressure;
526  pressure.reset (new vector_Type (pFESpace->map(), Unique) );
527  prevPressure.reset (new vector_Type (pFESpace->map(), Unique) );
528 
529  vectorPtr_Type solution;
530  vectorPtr_Type prevSolution;
531  vectorPtr_Type prevSolutionTimeDerivative;
532 
533  solution.reset (new vector_Type (solutionMap, Unique) );
534  prevSolution.reset (new vector_Type (solutionMap, Unique) );
535  prevSolutionTimeDerivative.reset (new vector_Type (solutionMap, Unique) );
536  if (verbose)
537  {
538  std::cout << "done" << std::endl;
539  }
540 
541  if (verbose)
542  {
543  std::cout << "Computing the initial solution ... " << std::endl;
544  }
545 
546  // TimeAdvanceBDF object to store the previous solutions
547  TimeAdvanceBDF<vector_Type> bdf;
548  bdf.setup (BDFOrder);
549 
550  TimeAdvanceBDF<vector_Type> bdfConvection;
551  bdfConvection.setup (BDFOrder);
552 
553  Real currentTime = initialTime - timestep * BDFOrder;
554 
555  // Start from zero velocity and ramp up
556  *velocity *= 0;
557  *pressure *= 0;
558 
559  *solution *= 0;
560  *prevRhs *= 0.;
561  *prevSolutionTimeDerivative *= 0.;
562  *prevSolution *= 0;
563 
564  bdf.setInitialCondition ( *solution );
565 
566  // Initial solution (interpolation or projection)
567  currentTime += timestep;
568  for ( ; currentTime <= initialTime + timestep / 2.; currentTime += timestep)
569  {
570  *rhs *= 0.;
571  *velocityExtrapolated *= 0.;
572  *solution *= 0;
573 
574  if (initializationMethod == Projection)
575  {
576  *rhs *= -1.;
577 
578  if (verbose)
579  {
580  std::cout << "Updating the system... " << std::flush;
581  }
582  systemMatrix.reset (new matrix_block_type ( solutionMap ) );
583  *systemMatrix += *baseMatrix;
584 
585  // Assemble the convective term
586 
587  if (convectionTerm == SemiImplicit)
588  {
589  convMatrix.reset (new matrix_block_type ( solutionMap ) );
590 
591  // Perform the assembly of the convection matrix with ETA
592 
593  {
594  using namespace ExpressionAssembly;
595 
596  integrate (
597  elements (ETuFESpace->mesh() ), // Mesh
598  uFESpace->qr(), // QR
599  ETuFESpace,
600  ETuFESpace,
601  dot (grad (phi_j) * value (ETuFESpace, *velocityExtrapolated), phi_i)
602  )
603  >> convMatrix->block (0, 0);
604  }
605  *systemMatrix += *convMatrix;
606  }
607  else if (convectionTerm == Explicit)
608  {
609  //oseenAssembler.addConvectionRhs(*rhs,1.,*solution);
610  /*{
611  using namespace ExpressionAssembly;
612 
613  integrate(
614  elements(ETuFESpace->mesh()), // Mesh
615  uFESpace->qr(), // QR
616  ETuFESpace,
617  ETuFESpace,
618  dot( value(ETuFESpace,*solution), phi_i)
619  )
620  >> rhs->block(0);
621  }*/
622  }
623 
624  std::shared_ptr<matrix_block_type> stabMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
625  *stabMatrix *= 0;
626  stabMatrix->globalAssemble();
627  *systemMatrix += *stabMatrix;
628 
629  if (verbose)
630  {
631  std::cout << "done" << std::endl;
632  }
633 
634  if (verbose)
635  {
636  std::cout << "Applying BC... " << std::flush;
637  }
638  bcManage (*systemMatrix, *rhs, *uFESpace->mesh(), uFESpace->dof(), bcHandler, uFESpace->feBd(), 1.0, currentTime);
639  systemMatrix->globalAssemble();
640  if (verbose)
641  {
642  std::cout << "done" << std::endl;
643  }
644 
645  if (verbose)
646  {
647  std::cout << "Solving the system... " << std::endl;
648  }
649  *solution *= 0;
650 
651  // LinearSolver needs the monolithic matrix
652  std::shared_ptr<matrix_Type> systemMatrixNoBlock (new matrix_Type ( systemMatrix->matrixPtr() ) );
653  linearSolver.setMatrix (*systemMatrix);
654  linearSolver.solveSystem (*rhs, *solution, systemMatrixNoBlock);
655  }
656 
657  // Updating bdf
658  bdf.shiftRight ( *solution );
659 
660  }
661 
662  linearSolver.resetPreconditioner();
663 
664  // +-----------------------------------------------+
665  // | Setting the exporter |
666  // +-----------------------------------------------+
667  if (verbose)
668  {
669  std::cout << "Defining the exporter... " << std::flush;
670  }
671  ExporterHDF5<mesh_Type> exporter ( dataFile, "OseenAssembler");
672  exporter.setPostDir ( "./" ); // This is a test to see if M_post_dir is working
673  exporter.setMeshProcId ( meshPart.meshPartition(), Comm->MyPID() );
674  if (verbose)
675  {
676  std::cout << "done" << std::endl;
677  }
678 
679  if (verbose)
680  {
681  std::cout << "Updating the exporter... " << std::flush;
682  }
683  exporter.addVariable ( ExporterData<mesh_Type>::VectorField, "velocity", uFESpace, solution, UInt (0) );
684  exporter.addVariable ( ExporterData<mesh_Type>::ScalarField, "pressure", pFESpace, solution, pressureOffset );
685  if (verbose)
686  {
687  std::cout << "done" << std::endl;
688  }
689 
690  if (verbose)
691  {
692  std::cout << "Exporting solution at time t=" << initialTime << "... " << std::endl;
693  }
694  exporter.postProcess (initialTime);
695 
696  initChrono.stop();
697  if (verbose)
698  {
699  std::cout << "Initialization time: " << initChrono.diff() << " s." << std::endl;
700  }
701 
702  // +-----------------------------------------------+
703  // | Solving the problem |
704  // +-----------------------------------------------+
705  if (verbose)
706  {
707  std::cout << std::endl << "[Solving the problem]" << std::endl;
708  }
709  int iter = 1;
710 
711  for ( ; currentTime <= endTime + timestep / 2.; currentTime += timestep, iter++)
712  {
713  iterChrono.reset();
714  iterChrono.start();
715 
716  if (verbose)
717  {
718  std::cout << std::endl << "[t = " << currentTime << " s.]" << std::endl;
719  }
720 
721  if (verbose)
722  {
723  std::cout << "Updating the system... " << std::flush;
724  }
725  bdf.updateRHSContribution ( timestep );
726  *rhs = *massMatrix * bdf.rhsContributionFirstDerivative();
727 
728  systemMatrix.reset (new matrix_block_type ( solutionMap ) );
729  double alpha = bdf.coefficientFirstDerivative ( 0 ) / timestep;
730  *systemMatrix += *massMatrix * alpha;
731  *systemMatrix += *baseMatrix;
732 
733  if (convectionTerm == SemiImplicit)
734  {
735  bdf.extrapolation ( *velocityExtrapolated ); // Extrapolation for the convective term
736 
737  convMatrix.reset (new matrix_block_type ( solutionMap ) );
738 
739  // Perform the assembly of the convection matrix with ETA
740 
741  {
742  using namespace ExpressionAssembly;
743 
744  integrate (
745  elements (ETuFESpace->mesh() ), // Mesh
746  uFESpace->qr(), // QR
747  ETuFESpace,
748  ETuFESpace,
749  dot (grad (phi_j) * value (ETuFESpace, *velocityExtrapolated), phi_i)
750  )
751  >> convMatrix->block (0, 0);
752  }
753  convMatrix->globalAssemble();
754  *systemMatrix += *convMatrix;
755  }
756  else if (convectionTerm == Explicit)
757  {
758  //oseenAssembler.addConvectionRhs(*rhs,1.,*solution);
759  /*{
760  using namespace ExpressionAssembly;
761 
762  integrate(
763  elements(ETuFESpace->mesh()), // Mesh
764  uFESpace->qr(), // QR
765  ETuFESpace,
766  ETuFESpace,
767  dot( value(ETuFESpace,*solution), phi_i)
768  )
769  >> rhs->block(0);
770  }*/
771  }
772 
773  // Assemble the stabilization terms
774 
775  // Stabilization parameters for SUPG/PSPG/LSIC/VMS/LES
776  Real TauM (1e-3); // 1e-3
777  Real TauC (5e-2); // 5e-2
778 
779  /* Stabilization Macros for the stabilization terms (later add the ones coming from VMS) */
780 
781 #define SUPG_TEST value(TauM) * h_K * (grad(phi_i) * value(ETuFESpace, *velocityExtrapolated))
782 #define VMS_TEST value(TauM) * h_K * (transpose(grad(phi_i)) * value(ETuFESpace, *velocityExtrapolated))
783 #define PSPG_TEST value(TauM) * h_K * grad(phi_i)
784 #define DIVDIV_TEST value(TauC) * h_K * div(phi_i)
785 
786 #define RES_MOMENTUM grad(phi_j) * value(ETuFESpace, *velocityExtrapolated) * density + value(alpha) * density * phi_j
787 #define RES_MASS div(phi_j)
788 #define RES_PRESSURE grad(phi_j)
789 
790 #define RESIDUAL_EXPLICIT value(TauM) * h_K * value(ETuFESpace, *residualVector)
791 
792  std::shared_ptr<matrix_block_type> stabMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
793  std::shared_ptr<matrix_block_type> residualMatrix (new matrix_block_type ( ETuFESpace->map() | ETpFESpace->map() ) );
794  vector_block_type NSRhs ( ETuFESpace->map() | ETpFESpace->map(), Repeated );
795  vectorPtr_Type residualVector;
796  residualVector.reset (new vector_Type (solutionMap, Unique) );
797 
798  *stabMatrix *= 0;
799  *residualMatrix *= 0;
800  *residualVector *= 0;
801  NSRhs *= 0.0;
802 
803  if (stabilizationMethod == VMS)
804  {
805 
806  std::shared_ptr<NormalizeFct> normalize (new NormalizeFct);
807 
808  using namespace ExpressionAssembly;
809 
810  // Residual computation
811  integrate (
812  elements (ETuFESpace->mesh() ),
813  uFESpace->qr(),
814  ETuFESpace,
815  ETuFESpace,
816  dot (RES_MOMENTUM, phi_i)
817  )
818  >> residualMatrix->block (0, 0);
819 
820  integrate (
821  elements (ETuFESpace->mesh() ),
822  uFESpace->qr(),
823  ETuFESpace,
824  ETpFESpace,
825  dot (RES_PRESSURE, phi_i)
826  )
827  >> residualMatrix->block (0, 1);
828 
829  // Assemble the system matrix used for the residual computation
830  residualMatrix->globalAssemble();
831  bcManage (*residualMatrix, *prevRhs, *uFESpace->mesh(), uFESpace->dof(), bcHandler, uFESpace->feBd(), 1.0, currentTime);
832 
833  // Compute the residual from the previous time step for the turbulence terms
834  *residualVector = *prevRhs - (*residualMatrix * (*prevSolution) );
835 
836  // Stabilization, SUPG and DIV/DIV (1) and (2), VMS
837  integrate (
838  elements (ETuFESpace->mesh() ),
839  uFESpace->qr(),
840  ETuFESpace,
841  ETuFESpace,
842  RES_MASS * DIVDIV_TEST // OK
843  + dot (RES_MOMENTUM, SUPG_TEST) // OK
844  + dot (RES_MOMENTUM, VMS_TEST) // OK
845  )
846  >> stabMatrix->block (0, 0);
847 
848  // Stabilization, SUPG (3), VMS
849  integrate (
850  elements (ETuFESpace->mesh() ),
851  uFESpace->qr(),
852  ETuFESpace,
853  ETpFESpace,
854  dot (RES_PRESSURE, SUPG_TEST) // OK
855  + dot (RES_PRESSURE, VMS_TEST)
856  )
857  >> stabMatrix->block (0, 1);
858 
859 
860  // Stabilization, PSPG (4)
861  integrate (
862  elements (ETuFESpace->mesh() ),
863  uFESpace->qr(),
864  ETpFESpace,
865  ETuFESpace,
866  dot (RES_MOMENTUM, PSPG_TEST) // OK
867  )
868  >> stabMatrix->block (1, 0);
869 
870  // Stabilization, PSPG (5)
871  integrate (
872  elements (ETuFESpace->mesh() ),
873  uFESpace->qr(),
874  ETpFESpace,
875  ETpFESpace,
876  dot (RES_PRESSURE, PSPG_TEST) // OK
877  )
878  >> stabMatrix->block (1, 1);
879 
880 
881  stabMatrix->globalAssemble();
882  *systemMatrix += *stabMatrix;
883  }
884  else if (stabilizationMethod == IP)
885  {
886  details::StabilizationIP<mesh_Type, DOF> M_ipStabilization;
887  M_ipStabilization.setFeSpaceVelocity ( *uFESpace );
888  M_ipStabilization.setViscosity ( viscosity );
889 
890  // Parameters from J. Michalik
891  M_ipStabilization.setGammaBeta ( 0.1 );
892  M_ipStabilization.setGammaDiv ( 0.1 );
893  M_ipStabilization.setGammaPress ( 0.1 );
894 
895  M_ipStabilization.apply ( *stabMatrix, *velocityExtrapolated, false );
896  stabMatrix->globalAssemble();
897  *systemMatrix += *stabMatrix;
898  }
899 
900  // Now we can assemble the consistency terms on the RHS
901 
902  if (verbose)
903  {
904  std::cout << "done" << std::endl;
905  }
906 
907  if (stabilizationMethod == VMS)
908  {
909  std::shared_ptr<NormalizeFct> normalize (new NormalizeFct);
910 
911  using namespace ExpressionAssembly;
912  // RHS, consistency term for SUPG (6) and turbulence model (8)
913  integrate (
914  elements (ETuFESpace->mesh() ),
915  uFESpace->qr(),
916  ETuFESpace,
917  dot (value (ETuFESpace, *rhs), SUPG_TEST)
918  + dot (value (ETuFESpace, *rhs), VMS_TEST)
919  + dot (grad (phi_i), outerProduct ( RESIDUAL_EXPLICIT, RESIDUAL_EXPLICIT ) ) // Explicit turbulence model
920  )
921  >> NSRhs.block (0);
922 
923  // RHS, consistency term for PSPG (7)
924  integrate (
925  elements (ETuFESpace->mesh() ),
926  pFESpace->qr(),
927  ETpFESpace,
928  dot (value (ETuFESpace, *rhs), PSPG_TEST)
929  )
930  >> NSRhs.block (1);
931 
932 
933  vector_block_type NSRhsUnique ( NSRhs, Unique );
934  *rhs += NSRhsUnique;
935  }
936  if (verbose)
937  {
938  std::cout << "done" << std::endl;
939  }
940 
941  // RHS has to assembled next
942 
943  if (verbose)
944  {
945  std::cout << "Applying BC... " << std::flush;
946  }
947  bcManage (*systemMatrix, *rhs, *uFESpace->mesh(), uFESpace->dof(), bcHandler, uFESpace->feBd(), 1.0, currentTime);
948 
949 
950  if (verbose)
951  {
952  std::cout << "Solving the system... " << std::endl;
953  }
954  *solution *= 0;
955 
956  // LinearSolver needs the monolithic matrix
957  std::shared_ptr<matrix_Type> systemMatrixNoBlock (new matrix_Type ( systemMatrix->matrixPtr() ) );
958  linearSolver.setMatrix (*systemMatrix);
959  linearSolver.solveSystem (*rhs, *solution, systemMatrixNoBlock);
960 
961  // Updating the BDF scheme
962  bdf.shiftRight ( *solution );
963 
964  // Exporting the solution
965  exporter.postProcess ( currentTime );
966 
967  // Store previous solution, its time derivative and the RHS for the explicit turbulence model
968  *prevSolution = *solution;
969  *prevRhs = *rhs;
970 
971  iterChrono.stop();
972  if (verbose)
973  {
974  std::cout << "Iteration time: " << iterChrono.diff() << " s." << std::endl;
975  }
976 
977  MPI_Barrier (MPI_COMM_WORLD);
978  }
979 
980  // +-----------------------------------------------+
981  // | Ending the simulation |
982  // +-----------------------------------------------+
983  exporter.closeFile();
984 
985  globalChrono.stop();
986  if (verbose)
987  {
988  std::cout << std::endl << "Total simulation time: " << globalChrono.diff() << " s." << std::endl;
989  }
990  if (verbose)
991  {
992  std::cout << std::endl << "[[END_SIMULATION]]" << std::endl;
993  }
994 
995 #ifdef HAVE_MPI
996  MPI_Finalize();
997 #endif
998  return ( EXIT_SUCCESS );
999 }
ETFESpace< mesh_Type, MapEpetra, 3, 1 > etaPspace_Type
Real fluxFunction(const Real &, const Real &, const Real &, const Real &, const ID &)
FESpace - Short description here please!
Definition: FESpace.hpp:78
#define DIVDIV_TEST
Real const & operator[](UInt const &i) const
Operator [].
std::shared_ptr< ETFESpace< mesh_Type, MapEpetra, 3, 1 > > etaPspacePtr_Type
return_Type operator()(const VectorSmall< 3 > &value)
#define RESIDUAL_EXPLICIT
#define SUPG_TEST
Real inflowFunction(const Real &t, const Real &, const Real &, const Real &, const ID &i)
VectorSmall< 3 > operator*(Real const &factor) const
Operator * (multiplication by scalar on the right)
uint32_type ID
IDs.
Definition: LifeV.hpp:194
std::shared_ptr< VectorBlockMonolithicEpetra > vector_blockPtr_type
Real zeroFunction(const Real &, const Real &, const Real &, const Real &, const ID &)
#define PSPG_TEST
ETFESpace< mesh_Type, MapEpetra, 3, 3 > etaUspace_Type
double Real
Generic real data.
Definition: LifeV.hpp:175
#define RES_MOMENTUM
std::shared_ptr< ETFESpace< mesh_Type, MapEpetra, 3, 3 > > etaUspacePtr_Type
#define VMS_TEST
return_Type operator()(const VectorSmall< 3 > value)
#define RES_PRESSURE
class ETFESpace A light, templated version of the FESpace
Definition: ETFESpace.hpp:93
int main(int argc, char **argv)
#define RES_MASS