1#ifndef BLOCKMATRIX_DEF_hpp
2#define BLOCKMATRIX_DEF_hpp
3#include "BlockMatrix_decl.hpp"
15template <
class SC,
class LO,
class GO,
class NO>
16BlockMatrix<SC,LO,GO,NO>::BlockMatrix():
24 blockMap_ = Teuchos::rcp(
new BlockMap_Type( 0 ) );
27template <
class SC,
class LO,
class GO,
class NO>
28BlockMatrix<SC,LO,GO,NO>::BlockMatrix(UN size):
36 blockMap_ = Teuchos::rcp(
new BlockMap_Type( size ) );
40template <
class SC,
class LO,
class GO,
class NO>
41BlockMatrix<SC,LO,GO,NO>::BlockMatrix(BlockMatrixPtr_Type bMatrixIn):
42blockMatrix_(bMatrixIn->size()),
49 blockMap_ = Teuchos::rcp(
new BlockMap_Type( bMatrixIn->size() ) );
51 for(UN i = 0; i < bMatrixIn->size(); i++)
53 for(UN j = 0; j < bMatrixIn->size(); j++)
56 if(bMatrixIn->blockExists(i,j))
58 MatrixPtr_Type matrixTmp = bMatrixIn->getBlock(i,j);
59 MatrixPtr_Type matrixCopy = Teuchos::rcp(
new Matrix_Type( matrixTmp ) );
60 this->addBlock(matrixCopy, i, j);
67template <
class SC,
class LO,
class GO,
class NO>
68BlockMatrix<SC,LO,GO,NO>::~BlockMatrix()
73template <
class SC,
class LO,
class GO,
class NO>
74int BlockMatrix<SC,LO,GO,NO>::size()
const{
75 return blockMatrix_.size();
78template <
class SC,
class LO,
class GO,
class NO>
79void BlockMatrix<SC,LO,GO,NO>::resize(UN size) {
80 blockMatrix_.resize( size );
81 blockMap_->resize( size );
84template <
class SC,
class LO,
class GO,
class NO>
85typename BlockMatrix<SC,LO,GO,NO>::MatrixPtr_Type BlockMatrix<SC,LO,GO,NO>::getBlock(
int i,
int j){
87 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_[i][j].is_null(), std::runtime_error,
"Block in BlockMatrix which you tried to access is null.");
88 return blockMatrix_[i][j];
91template <
class SC,
class LO,
class GO,
class NO>
92typename BlockMatrix<SC,LO,GO,NO>::MatrixConstPtr_Type BlockMatrix<SC,LO,GO,NO>::getBlockConst(
int i,
int j)
const{
94 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_[i][j].is_null(), std::runtime_error,
"Block in BlockMatrix which you tried to access is null.");
95 return blockMatrix_[i][j];
98template <
class SC,
class LO,
class GO,
class NO>
99bool BlockMatrix<SC,LO,GO,NO>::blockExists(
int i,
int j)
const{
100 return ( !blockMatrix_[i][j].is_null() );
103template <
class SC,
class LO,
class GO,
class NO>
104void BlockMatrix<SC,LO,GO,NO>::addBlock(
const MatrixPtr_Type& matrix,
int i,
int j){
105 UN size = blockMatrix_.size();
106 if (i>size-1 || j>size-1)
107 blockMatrix_.resize( std::max(i,j)+1 );
109 if ( blockExists(i,j) )
110 blockMatrix_[i][j].reset();
112 blockMatrix_[i][j] = matrix;
115 blockMap_->addBlock( matrix->getMap(), i);
118template <
class SC,
class LO,
class GO,
class NO>
119void BlockMatrix<SC,LO,GO,NO>::merge(){
120 if ( mergedMap_.is_null() ) {
122 mergedMap_ = Teuchos::rcp_const_cast<Map_Type>(blockMap_->getMergedMap());
124 LO maxNumEntries = 0;
126 for (UN i=0; i<blockMatrix_.size(); i++) {
127 LO maxNumEntriesBlockRow = 0;
128 for (UN j=0; j<blockMatrix_.size(); j++) {
129 if ( !blockMatrix_[i][j].is_null() )
130 maxNumEntriesBlockRow += blockMatrix_[i][j]->getGlobalMaxNumRowEntries();
132 if (maxNumEntriesBlockRow > maxNumEntries)
133 maxNumEntries = maxNumEntriesBlockRow;
137 mergedMatrix_ = Teuchos::rcp(
new Matrix_Type( mergedMap_, maxNumEntries ) );
138 this->determineLocalOffsets();
139 this->determineGlobalOffsets();
141 for (UN i=0; i<blockMatrix_.size(); i++) {
142 for (UN j=0; j<blockMatrix_.size(); j++) {
143 if ( !blockMatrix_[i][j].is_null() ){
144 mergeBlockNew( i, j );
148 mergedMatrix_->fillComplete( mergedMap_, mergedMap_ );
165template <
class SC,
class LO,
class GO,
class NO>
166void BlockMatrix<SC,LO,GO,NO>::determineLocalOffsets(){
169 typedef Teuchos::ScalarTraits<LO> LOST;
171 Teuchos::Array<LO> offsetRows( blockMatrix_.size() - 1, LOST::zero() );
172 Teuchos::Array<LO> offsetCols( blockMatrix_.size() - 1, LOST::zero() );
173 for (UN row=0; row<blockMatrix_.size() - 1; row++) {
174 bool foundOffset =
false;
175 for (UN col=0; col<blockMatrix_.size() && !foundOffset; col++) {
176 if ( !blockMatrix_[row][col].is_null() ){
177 LO mli = blockMatrix_[row][col]->getMap(
"row")->getMaxLocalIndex();
179 offsetRows[row] = mli + 1;
183 for (UN col=0; col<blockMatrix_.size() - 1; col++) {
184 bool foundOffset =
false;
185 for (UN row=0; row<blockMatrix_.size() && !foundOffset; row++) {
186 if ( !blockMatrix_[row][col].is_null() ){
187 LO mli = blockMatrix_[row][col]->getMap(
"col")->getMaxLocalIndex();
189 offsetCols[col] = mli + 1;
195 Teuchos::rcp(
new SmallMatrix< LOTuple_Type >( blockMatrix_.size() ) );
197 LO offsetRow = LOST::zero();
198 for (UN row=0; row<blockMatrix_.size(); row++) {
199 LO offsetCol = LOST::zero();
200 for (UN col=0; col<blockMatrix_.size(); col++) {
201 LOTuple_Type tuple = Teuchos::tuple( offsetRow, offsetCol );
202 (*localBlockOffsets_)[row][col] = tuple;
203 if (offsetCols.size() > col)
204 offsetCol += offsetCols[col];
206 if (offsetRows.size() > row)
207 offsetRow += offsetRows[row];
211template <
class SC,
class LO,
class GO,
class NO>
212void BlockMatrix<SC,LO,GO,NO>::determineGlobalOffsets(){
214 typedef Teuchos::ScalarTraits<GO> GOST;
216 Teuchos::Array<GO> offsetRows( blockMatrix_.size() - 1, GOST::zero() );
217 Teuchos::Array<GO> offsetCols( blockMatrix_.size() - 1, GOST::zero() );
218 for (UN row=0; row<blockMatrix_.size() - 1; row++) {
219 bool foundOffset =
false;
220 for (UN col=0; col<blockMatrix_.size() && !foundOffset; col++) {
221 if ( !blockMatrix_[row][col].is_null() )
223 offsetRows[row] = blockMatrix_[row][col]->getMap(
"row")->getMaxAllGlobalIndex() + 1;
228 for (UN col=0; col<blockMatrix_.size() - 1; col++) {
229 bool foundOffset =
false;
230 for (UN row=0; row<blockMatrix_.size() && !foundOffset; row++) {
231 if ( !blockMatrix_[row][col].is_null() )
233 offsetCols[col] = blockMatrix_[row][col]->getMap(
"col")->getMaxAllGlobalIndex() + 1;
239 globalBlockOffsets_ =
240 Teuchos::rcp(
new SmallMatrix< GOTuple_Type >( blockMatrix_.size() ) );
242 GO offsetRow = GOST::zero();
243 for (UN row=0; row<blockMatrix_.size(); row++) {
244 GO offsetCol = GOST::zero();
245 for (UN col=0; col<blockMatrix_.size(); col++) {
246 GOTuple_Type tuple = Teuchos::tuple( offsetRow, offsetCol );
247 (*globalBlockOffsets_)[row][col] = tuple;
248 if (offsetCols.size() > col)
249 offsetCol += offsetCols[col];
251 if (offsetRows.size() > row)
252 offsetRow += offsetRows[row];
256template <
class SC,
class LO,
class GO,
class NO>
257void BlockMatrix<SC,LO,GO,NO>::mergeBlockNew(UN blockRow, UN blockCol){
259 MatrixPtr_Type matrix = blockMatrix_[blockRow][blockCol];
260 if ( matrix->isLocallyIndexed() ) {
262 Teuchos::ArrayView<const SC> values;
263 Teuchos::ArrayView<const LO> indices;
264 MapConstPtr_Type colMap = matrix->getMap(
"col");
265 MapConstPtr_Type rowMap = matrix->getMap(
"row");
267 for (UN i=0; i<matrix->getNodeNumRows(); i++) {
268 matrix->getLocalRowView( i, indices, values );
269 Teuchos::Array<GO> indicesGlobal( indices.size() );
270 for (UN j=0; j<indices.size(); j++) {
271 indicesGlobal[j] = colMap->getGlobalElement( indices[j] ) + (*globalBlockOffsets_)[blockRow][blockCol][1];
276 GO offset = (*globalBlockOffsets_)[blockRow][blockCol][0];
277 mergedMatrix_->insertGlobalValues( rowMap->getGlobalElement( i ) + offset, indicesGlobal(), values );
285 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Call fillComplete() before you merge the matrix blocks.");
290template <
class SC,
class LO,
class GO,
class NO>
291void BlockMatrix<SC,LO,GO,NO>::print(Teuchos::EVerbosityLevel verbLevel){
293 for (UN i=0; i<blockMatrix_.size(); i++) {
294 for (UN j=0; j<blockMatrix_.size(); j++) {
295 if ( !blockMatrix_[i][j].is_null() ) {
296 blockMatrix_[i][j]->print( verbLevel );
302template <
class SC,
class LO,
class GO,
class NO>
303void BlockMatrix<SC,LO,GO,NO>::printMerge(Teuchos::EVerbosityLevel verbLevel){
305 if ( !mergedMatrix_.is_null() )
306 mergedMatrix_->print( verbLevel );
310template <
class SC,
class LO,
class GO,
class NO>
311Teuchos::RCP<const Thyra::LinearOpBase<SC> > BlockMatrix<SC,LO,GO,NO>::getThyraLinOp(){
313 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() == 0, std::logic_error,
"BlockMatrix size is 0.");
314 Teuchos::RCP<const Thyra::LinearOpBase<SC> > thyraLinOp;
315 if (blockMatrix_.size() == 1){
316 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_[0][0].is_null(), std::runtime_error,
"Block in BlockMatrix is null.");
317 thyraLinOp = blockMatrix_[0][0]->getThyraLinOp( );
321 thyraLinOp = mergedMatrix_->getThyraLinOp( );
326template <
class SC,
class LO,
class GO,
class NO>
327Teuchos::RCP< const Thyra::BlockedLinearOpBase<SC> > BlockMatrix<SC,LO,GO,NO>::getThyraLinBlockOp()
const{
329 Teuchos::RCP< Thyra::DefaultBlockedLinearOp< SC > > dblOp = Thyra::defaultBlockedLinearOp<SC> ();
330 dblOp->beginBlockFill( this->size(), this->size() );
332 for (
int i=0; i<this->size(); i++) {
333 for (
int j=0; j<this->size(); j++) {
334 if ( this->blockExists(i,j) ) {
335 dblOp->setBlock( i, j, blockMatrix_[i][j]->getThyraLinOp( ) );
340 dblOp->endBlockFill();
341 Teuchos::RCP< const Thyra::BlockedLinearOpBase< SC > > blOpConst = Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase< SC > > (dblOp);
346template <
class SC,
class LO,
class GO,
class NO>
347void BlockMatrix<SC,LO,GO,NO>::apply(
const BlockMultiVector_Type& X,
348 BlockMultiVector_Type& Y )
const{
350 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() == 0, std::logic_error,
"BlockMatrix size is 0.");
351 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() != X.size(), std::logic_error,
"BlockMatrix and BlockMultiVector have different sizes.");
352 TEUCHOS_TEST_FOR_EXCEPTION( Y.size() != X.size(), std::logic_error,
"BlockMultiVectors have different sizes.");
354 for (
int i=0; i<Y.size(); i++)
355 Y[i]->putScalar( Teuchos::ScalarTraits<SC>::zero() );
357 typedef Teuchos::ScalarTraits<SC> ST;
359 for (
int i=0; i<blockMatrix_.size(); i++) {
360 for (
int j=0; j<blockMatrix_.size(); j++){
361 MultiVectorConstPtr_Type tmpX = X[j];
362 if (!blockMatrix_[i][j].is_null())
364 blockMatrix_[i][j]->apply( *tmpX, *Y[i], Teuchos::NO_TRANS, ST::one(), ST::one() );
370template <
class SC,
class LO,
class GO,
class NO>
371void BlockMatrix<SC,LO,GO,NO>::apply(
const BlockMultiVector_Type& X,
372 BlockMultiVector_Type& Y,
373 const SmallMatrix<SC>& coeff)
const{
375 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() != coeff.size(), std::logic_error,
"BlockMatrix size and coefficient size are different.");
376 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() == 0, std::logic_error,
"BlockMatrix size is 0.");
377 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() != X.size(), std::logic_error,
"BlockMatrix and BlockMultiVector have different sizes.");
378 TEUCHOS_TEST_FOR_EXCEPTION( Y.size() != X.size(), std::logic_error,
"BlockMultiVectors have different sizes.");
380 for (
int i=0; i<Y.size(); i++)
381 Y[i]->putScalar( Teuchos::ScalarTraits<SC>::zero() );
383 typedef Teuchos::ScalarTraits<SC> ST;
385 for (
int i=0; i<blockMatrix_.size(); i++) {
386 for (
int j=0; j<blockMatrix_.size(); j++){
387 MultiVectorConstPtr_Type tmpX = X[j];
388 if (!blockMatrix_[i][j].is_null())
389 blockMatrix_[i][j]->apply( *tmpX, *Y[i], Teuchos::NO_TRANS, coeff[i][j], ST::one() );
394template <
class SC,
class LO,
class GO,
class NO>
395void BlockMatrix<SC,LO,GO,NO>::addMatrix(
const SmallMatrix<SC>& coeffAlpha,
const BlockMatrixPtr_Type &B,
const SmallMatrix<SC>& coeffBeta){
397 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() != coeffAlpha.size(), std::logic_error,
"BlockMatrix size and coefficient size are different.");
398 TEUCHOS_TEST_FOR_EXCEPTION( coeffAlpha.size() != coeffBeta.size(), std::logic_error,
"Coefficients have different sizes.");
399 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() == 0, std::logic_error,
"BlockMatrix size is 0.");
400 TEUCHOS_TEST_FOR_EXCEPTION( blockMatrix_.size() != B->size(), std::logic_error,
"BlockMatrices have different sizes.");
404 for (
int i=0; i<blockMatrix_.size(); i++) {
405 for (
int j=0; j<blockMatrix_.size(); j++){
406 if (blockMatrix_[i][j].is_null()){
407 if ( coeffBeta[i][j] != Teuchos::ScalarTraits<SC>::one() && B->blockExists(i,j) )
409 B->getBlock(i,j)->scale( coeffBeta[i][j] );
413 blockMatrix_[i][j]->addMatrix( coeffAlpha[i][j], B->getBlock(i,j), coeffBeta[i][j] );
418template <
class SC,
class LO,
class GO,
class NO>
419void BlockMatrix<SC,LO,GO,NO>::writeMM(std::string fN)
const{
420 for (
int i=0; i<blockMatrix_.size(); i++) {
421 for (
int j=0; j<blockMatrix_.size(); j++){
422 if (!blockMatrix_[i][j].is_null() ){
423 std::string fileName = fN + std::to_string(i) + std::to_string(j) +
".mm" ;
424 blockMatrix_[i][j]->writeMM(fileName);
430template <
class SC,
class LO,
class GO,
class NO>
431typename BlockMatrix<SC,LO,GO,NO>::MatrixPtr_Type BlockMatrix<SC,LO,GO,NO>::getMergedMatrix() {
432 if (this->size()>1) {
434 return mergedMatrix_;
437 return this->getBlock(0,0);
440template <
class SC,
class LO,
class GO,
class NO>
441typename BlockMatrix<SC,LO,GO,NO>::BlockMapPtr_Type BlockMatrix<SC,LO,GO,NO>::getMap() {
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement.cpp:5