8 #include <lifev/core/linear_algebra/BlockOperator.hpp> 26 M_nBlockRows = map->nBlocks();
29 M_rangeMap = M_domainMap;
30 M_oper.resize(M_nBlockRows, M_nBlockCols);
37 const commPtr_Type & comm)
41 M_nBlockRows = rangeMap->nBlocks();
42 M_nBlockCols = domainMap->nBlocks();
44 M_domainMap = domainMap;
45 M_rangeMap = rangeMap;
47 M_oper.resize(M_nBlockRows, M_nBlockCols);
55 M_nBlockRows = blockOper.size1();
56 M_nBlockCols = blockOper.size2();
64 if(blockOper(iblock,jblock) != 0 && rangeBlockMaps[iblock]==0)
66 rangeBlockMaps[iblock].reset(
new Epetra_Map(blockOper(iblock,jblock)->OperatorRangeMap() ));
74 if(blockOper(iblock,jblock) != 0 && domainBlockMaps[jblock]==0)
76 domainBlockMaps[jblock].reset(
new Epetra_Map(blockOper(iblock,jblock)->OperatorDomainMap() ));
81 M_domainMap.reset(
new BlockEpetra_Map(domainBlockMaps));
82 M_rangeMap.reset(
new BlockEpetra_Map(rangeBlockMaps));
92 ASSERT_PRE(M_rangeMap->blockMap(iblock)->PointSameAs(operBlock->OperatorRangeMap()),
"Wrong range map");
93 ASSERT_PRE(M_domainMap->blockMap(jblock)->PointSameAs(operBlock->OperatorDomainMap()),
"Wrong domain map");
95 M_oper(iblock, jblock) = operBlock;
102 bool thereAreUpperDiagonalBlocks(
false);
105 if(M_oper(iblock,jblock).get() != 0 && (M_oper(iblock, jblock)->HasNormInf() ? M_oper(iblock, jblock)->NormInf()!=0 :
true) )
106 thereAreUpperDiagonalBlocks =
true;
108 bool thereAreLowerDiagonalBlocks(
false);
110 for(
UInt jblock = 0; jblock < iblock; ++jblock)
111 if(M_oper(iblock,jblock).get() != 0 && (M_oper(iblock, jblock)->HasNormInf() ? M_oper(iblock, jblock)->NormInf()!=0 :
true) )
112 thereAreLowerDiagonalBlocks =
true;
115 bool thereAreUpperAntiDiagonalBlocks(
false);
117 for(
UInt jblock = 0; jblock < iblock; ++jblock)
118 if(M_oper(iblock,jblock).get() != 0 && (M_oper(iblock, jblock)->HasNormInf() ? M_oper(iblock, jblock)->NormInf()!=0 :
true) )
119 thereAreUpperAntiDiagonalBlocks =
true;
121 bool thereAreLowerAntiDiagonalBlocks(
false);
124 if(M_oper(iblock,jblock).get() != 0 && (M_oper(iblock, jblock)->HasNormInf() ? M_oper(iblock, jblock)->NormInf()!=0 :
true) )
125 thereAreLowerAntiDiagonalBlocks =
true;
131 if(M_oper(iblock,jblock).get() == 0)
134 nullOp->setUp(M_domainMap->blockMap(jblock), M_rangeMap->blockMap(iblock) );
135 M_oper(iblock,jblock).reset(nullOp);
137 ASSERT(M_rangeMap->blockMap(iblock)->PointSameAs(M_oper(iblock,jblock)->OperatorRangeMap()),
"Wrong range map");
138 ASSERT(M_domainMap->blockMap(jblock)->PointSameAs(M_oper(iblock,jblock)->OperatorDomainMap()),
"Wrong domain map");
147 if(!thereAreLowerDiagonalBlocks && !thereAreUpperDiagonalBlocks)
152 if(thereAreLowerDiagonalBlocks && !thereAreUpperDiagonalBlocks)
157 if(!thereAreLowerDiagonalBlocks && thereAreUpperDiagonalBlocks)
162 if(!thereAreLowerAntiDiagonalBlocks && !thereAreUpperAntiDiagonalBlocks)
167 if(thereAreLowerAntiDiagonalBlocks && !thereAreUpperAntiDiagonalBlocks)
172 if(!thereAreLowerAntiDiagonalBlocks && thereAreUpperAntiDiagonalBlocks)
184 #ifdef HAVE_LIFEV_DEBUG 186 for (UInt i(0); i<M_nBlockRows; ++i)
187 for (UInt j(0); j<M_nBlockCols; ++j)
189 EPETRA_CHK_ERR(M_oper(i,j)->SetUseTranspose(
true));
190 EPETRA_CHK_ERR(M_oper(i,j)->SetUseTranspose(
false));
208 ASSERT_PRE(M_nBlockRows == M_nBlockCols,
"The operator must be squared");
209 ASSERT_PRE(M_domainMap->monolithicMap()->SameAs(*M_rangeMap->monolithicMap() ),
"The operator must be squared");
210 ASSERT_PRE(Y.Map().SameAs(*M_domainMap->monolithicMap()),
"The map of Y is not conforming with domain map.");
211 ASSERT_PRE(X.Map().SameAs(*M_rangeMap->monolithicMap()),
"The map of X is not conforming with range map.");
212 ASSERT_PRE(X.NumVectors() == Y.NumVectors(),
"The number of vectors in X and Y is different" );
246 ASSERT (iblock<M_nBlockRows,
"Error! Index out of bounds.\n");
247 ASSERT (jblock<M_nBlockCols,
"Error! Index out of bounds.\n");
248 return M_oper(iblock,jblock);
259 ASSERT_PRE(X.Map().SameAs(*(M_domainMap->monolithicMap())),
"The map of X is not conforming with domain map.");
260 ASSERT_PRE(Y.Map().SameAs(*(M_rangeMap->monolithicMap())),
"The map of Y is not conforming with range map.");
261 ASSERT_PRE(X.NumVectors() == Y.NumVectors(),
"The number of vectors in X and Y is different" );
263 const std::unique_ptr<BlockEpetra_MultiVector> Xview( createBlockView(X, *M_domainMap) );
264 const std::unique_ptr<BlockEpetra_MultiVector> Yview( createBlockView(Y, *M_rangeMap) );
267 Yview->PutScalar(0.0);
274 EPETRA_CHK_ERR(M_oper(iblock, jblock)->Apply(Xview->block(jblock), tmpY.block(iblock) ));
275 EPETRA_CHK_ERR(Yview->block(iblock).Update(1.0, tmpY.block(iblock), 1.0));
283 ASSERT_PRE(X.Map().SameAs(*(M_rangeMap->monolithicMap())),
"The map of X is not conforming with domain map.");
284 ASSERT_PRE(Y.Map().SameAs(*(M_domainMap->monolithicMap())),
"The map of Y is not conforming with range map.");
285 ASSERT_PRE(X.NumVectors() == Y.NumVectors(),
"The number of vectors in X and Y is different" );
287 const std::unique_ptr<BlockEpetra_MultiVector> Xview( createBlockView(X, *M_rangeMap) );
288 const std::unique_ptr<BlockEpetra_MultiVector> Yview( createBlockView(Y, *M_domainMap) );
291 Yview->PutScalar(0.0);
297 EPETRA_CHK_ERR(M_oper(iblock,jblock)->SetUseTranspose(
true));
298 EPETRA_CHK_ERR(M_oper(iblock, jblock)->Apply(Xview->block(jblock), tmpY.block(iblock) ));
299 EPETRA_CHK_ERR(Yview->block(iblock).Update(1.0, tmpY.block(iblock), 1.0));
300 EPETRA_CHK_ERR(M_oper(iblock,jblock)->SetUseTranspose(
false));
308 const std::unique_ptr<BlockEpetra_MultiVector> Xcopy(
new BlockEpetra_MultiVector(Copy, X, *M_rangeMap) );
309 const std::unique_ptr<BlockEpetra_MultiVector> Yview(
new BlockEpetra_MultiVector(View, Y, *M_rangeMap) );
311 Yview->PutScalar(0.0);
316 for (UInt iblock = 0; iblock < M_nBlockRows; ++iblock)
317 EPETRA_CHK_ERR(M_oper(iblock, iblock)->ApplyInverse(Xcopy->block(iblock), Yview->block(iblock) ));
325 EPETRA_CHK_ERR(M_oper(iblock, jblock)->ApplyInverse(Xcopy->block(jblock), Yview->block(iblock) ));
333 const std::unique_ptr<BlockEpetra_MultiVector> Xcopy(
new BlockEpetra_MultiVector(Copy, X, *M_rangeMap) );
334 const std::unique_ptr<BlockEpetra_MultiVector> Yview(
new BlockEpetra_MultiVector(View, Y, *M_rangeMap) );
337 Yview->PutScalar(0.0);
345 EPETRA_CHK_ERR(M_oper(iblock, iblock)->ApplyInverse(Xcopy->block(iblock), Yview->block(iblock) ));
348 EPETRA_CHK_ERR( M_oper(kblock, iblock)->Apply(Yview->block(iblock), Z.block(kblock) ) );
349 EPETRA_CHK_ERR( Xcopy->block(kblock).Update(-1.0, Z.block(kblock), 1.0) );
359 EPETRA_CHK_ERR(M_oper(iblock, jblock)->ApplyInverse(Xcopy->block(iblock), Yview->block(jblock) ));
362 EPETRA_CHK_ERR( M_oper(kblock, jblock)->Apply(Yview->block(jblock), Z.block(kblock) ) );
363 EPETRA_CHK_ERR( Xcopy->block(kblock).Update(-1.0, Z.block(kblock), 1.0) );
373 const std::unique_ptr<BlockEpetra_MultiVector> Xcopy(
new BlockEpetra_MultiVector(Copy, X, *M_rangeMap) );
374 const std::unique_ptr<BlockEpetra_MultiVector> Yview(
new BlockEpetra_MultiVector(View, Y, *M_rangeMap) );
377 Yview->PutScalar(0.0);
383 for(
int iblock =
M_nBlockRows - 1 ; iblock > -1 ; --iblock)
385 EPETRA_CHK_ERR(M_oper(iblock, iblock)->ApplyInverse(Xcopy->block(iblock), Yview->block(iblock) ));
386 for(
int kblock = 0; kblock < iblock; ++kblock)
388 EPETRA_CHK_ERR( M_oper(kblock, iblock)->Apply(Yview->block(iblock), Z.block(kblock) ) );
389 EPETRA_CHK_ERR( Xcopy->block(kblock).Update(-1.0, Z.block(kblock), 1.0) );
396 for(
int iblock =
M_nBlockRows - 1 ; iblock > -1 ; --iblock)
399 EPETRA_CHK_ERR(M_oper(iblock, jblock)->ApplyInverse(Xcopy->block(iblock), Yview->block(jblock) ));
400 for(
int kblock = 0; kblock < iblock; ++kblock)
402 EPETRA_CHK_ERR( M_oper(kblock, jblock)->Apply(Yview->block(jblock), Z.block(kblock) ) );
403 EPETRA_CHK_ERR( Xcopy->block(kblock).Update(-1.0, Z.block(kblock), 1.0) );
void setUp(const operatorPtrContainer_Type &blockOper, const commPtr_Type &comm)
SetUp when the operator is given like a boost::matrix.
This class handles block access to parallel monolithic Vectors with an underling block structure...
int applyTranspose(const vector_Type &X, vector_Type &Y) const
Compute Y = Op'*X;.
void setUp(const boost::shared_ptr< BlockEpetra_Map > &domainMap, const boost::shared_ptr< BlockEpetra_Map > &rangeMap, const commPtr_Type &comm)
SetUp for a "rectangular operator".
int SetUseTranspose(bool useTranspose)
If true the transpose of the operator will be computed.
UInt M_nBlockCols
Number of blocks in each column.
void setBlock(UInt iblock, UInt jblock, const operatorPtr_Type &operBlock)
set a component of the block operator
Structure M_structure
structure of the block operator
operatorPtrContainer_Type M_oper
block operator represented like a dense matrix of pointers to Operators
const operatorPtr_Type & block(UInt iblock, UInt jblock) const
Returns a const pointer to the (i,j) block.
void updateInverseJacobian(const UInt &iQuadPt)
int blockUpperTriangularSolve(const vector_Type &X, vector_Type &Y) const
Y = backwardsubstitution(X)
void fillComplete()
Complete the block matrix with null operators.
int blockJacobi(const vector_Type &X, vector_Type &Y) const
Y = diag(block(i,i)^-1)*X.
std::vector< mapPtr_Type > mapPtrContainer_Type
A abstract class for handling n-by-m block operators This class inherits from LifeV::LinearOperatorAl...
commPtr_Type M_comm
Communicator.
boost::numeric::ublas::matrix< operatorPtr_Type > operatorPtrContainer_Type
UInt M_nBlockRows
Number of blocks in each row.
A derived class from Epetra_MultiVector specialized to handle parallel block structured Vectors...
int applyNoTranspose(const vector_Type &X, vector_Type &Y) const
Compute Y = Op*X;.
int blockLowerTriangularSolve(const vector_Type &X, vector_Type &Y) const
Y = forwardsubstitution(X)
virtual int ApplyInverse(const vector_Type &X, vector_Type &Y) const
Compute Y = Op;.
virtual int Apply(const vector_Type &X, vector_Type &Y) const
Compute Y = Op*X;.
void setUp(const boost::shared_ptr< BlockEpetra_Map > &map, const commPtr_Type &comm)
SetUp for a "square operator".
uint32_type UInt
generic unsigned integer (used mainly for addressing)
bool M_useTranspose
whenever transpose should be used
BlockOperator()
Empty Constructor.