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