LifeV
NavierStokesOperator.cpp
Go to the documentation of this file.
1 #include <lifev/navier_stokes_blocks/solver/NavierStokesOperator.hpp>
2 
3 namespace LifeV
4 {
5 namespace Operators
6 {
7 NavierStokesOperator::NavierStokesOperator():
8 M_name("NavierStokesOperator"),
9 M_useTranspose(false)
10 {
11 
12 }
13 
14 void NavierStokesOperator::setUp(const std::shared_ptr<BlockEpetra_Map> & map, const commPtr_Type & comm)
15 {
16  M_comm = comm;
17 
18  M_nBlockRows = map->nBlocks();
19  M_nBlockCols = M_nBlockRows;
20  M_domainMap = map;
21  M_rangeMap = M_domainMap;
22  M_oper.resize(M_nBlockRows, M_nBlockCols);
23 }
24 
25 
26 //! SetUp for a "rectangular operator"
27 void NavierStokesOperator::setUp(const std::shared_ptr<BlockEpetra_Map> & domainMap,
28  const std::shared_ptr<BlockEpetra_Map> & rangeMap,
29  const commPtr_Type & comm)
30 {
31  M_comm = comm;
32 
33  M_nBlockRows = rangeMap->nBlocks();
34  M_nBlockCols = domainMap->nBlocks();
35 
36  M_domainMap = domainMap;
37  M_rangeMap = rangeMap;
38 
39  M_oper.resize(M_nBlockRows, M_nBlockCols);
40 
41 }
42 
43 //! SetUp when the operator is given like a std::matrix
44 void NavierStokesOperator::setUp(const operatorPtrContainer_Type & blockOper, const commPtr_Type & comm)
45 {
46  M_comm = comm;
47  M_nBlockRows = blockOper.size1();
48  M_nBlockCols = blockOper.size2();
49 
50  BlockEpetra_Map::mapPtrContainer_Type rangeBlockMaps(M_nBlockRows);
51  BlockEpetra_Map::mapPtrContainer_Type domainBlockMaps(M_nBlockCols);
52 
53  for(UInt iblock=0; iblock < M_nBlockRows; ++iblock)
54  for(UInt jblock=0; jblock < M_nBlockCols; ++jblock)
55  {
56  if(blockOper(iblock,jblock) != 0 && rangeBlockMaps[iblock]==0)
57  {
58  rangeBlockMaps[iblock].reset(new Epetra_Map(blockOper(iblock,jblock)->OperatorRangeMap() ));
59  jblock = M_nBlockCols;
60  }
61  }
62 
63  for(UInt jblock=0; jblock < M_nBlockCols; ++jblock)
64  for(UInt iblock=0; iblock < M_nBlockRows; ++iblock)
65  {
66  if(blockOper(iblock,jblock) != 0 && domainBlockMaps[jblock]==0)
67  {
68  domainBlockMaps[jblock].reset(new Epetra_Map(blockOper(iblock,jblock)->OperatorDomainMap() ));
69  iblock = M_nBlockRows;
70  }
71  }
72 
73  M_domainMap.reset(new BlockEpetra_Map(domainBlockMaps));
74  M_rangeMap.reset(new BlockEpetra_Map(rangeBlockMaps));
75 
76  M_oper = blockOper;
77  fillComplete();
78 
79 }
80 
81 //! set a component of the block operator
82 void NavierStokesOperator::setBlock(UInt iblock, UInt jblock, const operatorPtr_Type & operBlock)
83 {
84  ASSERT_PRE(M_rangeMap->blockMap(iblock)->PointSameAs(operBlock->OperatorRangeMap()), "Wrong range map");
85  ASSERT_PRE(M_domainMap->blockMap(jblock)->PointSameAs(operBlock->OperatorDomainMap()), "Wrong domain map");
86 
87  M_oper(iblock, jblock) = operBlock;
88 }
89 
90 
91 void NavierStokesOperator::fillComplete()
92 {
93  // Filling the empty blocks with null operators
94  for(UInt iblock = 0; iblock < M_nBlockRows; ++iblock)
95  for(UInt jblock = 0; jblock < M_nBlockCols; ++jblock)
96  {
97  if(M_oper(iblock,jblock).get() == 0)
98  {
99  NullOperator * nullOp(new NullOperator);
100  nullOp->setUp(M_domainMap->blockMap(jblock), M_rangeMap->blockMap(iblock) );
101  M_oper(iblock,jblock).reset(nullOp);
102  }
103  ASSERT(M_rangeMap->blockMap(iblock)->PointSameAs(M_oper(iblock,jblock)->OperatorRangeMap()), "Wrong range map");
104  ASSERT(M_domainMap->blockMap(jblock)->PointSameAs(M_oper(iblock,jblock)->OperatorDomainMap()), "Wrong domain map");
105  }
106 }
107 
108 int NavierStokesOperator::SetUseTranspose(bool useTranspose)
109 {
110  M_useTranspose = useTranspose;
111 #ifdef HAVE_LIFEV_DEBUG
112  // Checking that all the blocks support the transpose option
113  for (UInt i(0); i<M_nBlockRows; ++i)
114  for (UInt j(0); j<M_nBlockCols; ++j)
115  {
116  EPETRA_CHK_ERR(M_oper(i,j)->SetUseTranspose(true));
117  EPETRA_CHK_ERR(M_oper(i,j)->SetUseTranspose(false));
118  }
119 #endif
120  return 0;
121 }
122 
123 int NavierStokesOperator::Apply(const vector_Type & X, vector_Type & Y) const
124 {
125  int error(-1);
126  if (M_useTranspose)
127  error = applyTranspose(X,Y);
128  else
129  error = applyNoTranspose(X,Y);
130  return error;
131 }
132 
133 int NavierStokesOperator::ApplyInverse(const vector_Type & X, vector_Type & Y) const
134 {
135  // We just have to code the Apply method.
136  return -1;
137 }
138 
139 const NavierStokesOperator::operatorPtr_Type& NavierStokesOperator::block(UInt iblock, UInt jblock) const
140 {
141  ASSERT (iblock<M_nBlockRows,"Error! Index out of bounds.\n");
142  ASSERT (jblock<M_nBlockCols,"Error! Index out of bounds.\n");
143  return M_oper(iblock,jblock);
144 }
145 
146 //===========================================================================//
147 //===========================================================================//
148 // Private Methods //
149 //===========================================================================//
150 //===========================================================================//
151 
152 int NavierStokesOperator::applyNoTranspose(const vector_Type & X, vector_Type & Y) const
153 {
154  ASSERT_PRE(X.Map().SameAs(*(M_domainMap->monolithicMap())),"The map of X is not conforming with domain map.");
155  ASSERT_PRE(Y.Map().SameAs(*(M_rangeMap->monolithicMap())), "The map of Y is not conforming with range map.");
156  ASSERT_PRE(X.NumVectors() == Y.NumVectors(), "The number of vectors in X and Y is different" );
157 
158  const std::unique_ptr<BlockEpetra_MultiVector> Xview( createBlockView(X, *M_domainMap) );
159  const std::unique_ptr<BlockEpetra_MultiVector> Yview( createBlockView(Y, *M_rangeMap) );
160  BlockEpetra_MultiVector tmpY(*M_rangeMap, X.NumVectors(), true);
161 
162  Yview->PutScalar(0.0);
163 
164 
165  // Perform the mat-vec multiplications
166  for(UInt iblock=0; iblock < M_nBlockRows; ++iblock)
167  for(UInt jblock=0; jblock < M_nBlockCols; ++jblock)
168  {
169  EPETRA_CHK_ERR(M_oper(iblock, jblock)->Apply(Xview->block(jblock), tmpY.block(iblock) ));
170  EPETRA_CHK_ERR(Yview->block(iblock).Update(1.0, tmpY.block(iblock), 1.0));
171  }
172 
173  return 0;
174 }
175 
176 int NavierStokesOperator::applyTranspose(const vector_Type & X, vector_Type & Y) const
177 {
178  ASSERT_PRE(X.Map().SameAs(*(M_rangeMap->monolithicMap())),"The map of X is not conforming with domain map.");
179  ASSERT_PRE(Y.Map().SameAs(*(M_domainMap->monolithicMap())), "The map of Y is not conforming with range map.");
180  ASSERT_PRE(X.NumVectors() == Y.NumVectors(), "The number of vectors in X and Y is different" );
181 
182  const std::unique_ptr<BlockEpetra_MultiVector> Xview( createBlockView(X, *M_rangeMap) );
183  const std::unique_ptr<BlockEpetra_MultiVector> Yview( createBlockView(Y, *M_domainMap) );
184  BlockEpetra_MultiVector tmpY(*M_domainMap, X.NumVectors(), true);
185 
186  Yview->PutScalar(0.0);
187 
188  // Perform the mat-vec multiplications
189  for(UInt iblock=0; iblock < M_nBlockCols; ++iblock)
190  for(UInt jblock=0; jblock < M_nBlockRows; ++jblock)
191  {
192  EPETRA_CHK_ERR(M_oper(iblock,jblock)->SetUseTranspose(true));
193  EPETRA_CHK_ERR(M_oper(iblock, jblock)->Apply(Xview->block(jblock), tmpY.block(iblock) ));
194  EPETRA_CHK_ERR(Yview->block(iblock).Update(1.0, tmpY.block(iblock), 1.0));
195  EPETRA_CHK_ERR(M_oper(iblock,jblock)->SetUseTranspose(false));
196  }
197 
198  return 0;
199 }
200 
201 } /* end namespace Operators */
202 
203 } /*end namespace */
This class handles block access to parallel monolithic Vectors with an underling block structure...
void updateInverseJacobian(const UInt &iQuadPt)
#define ASSERT_PRE(X, A)
Definition: LifeAssert.hpp:96
std::vector< mapPtr_Type > mapPtrContainer_Type
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
A derived class from Epetra_MultiVector specialized to handle parallel block structured Vectors...
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191