Thyra_DefaultBlockedLinearOp_def.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 
00030 #ifndef THYRA_DEFAULT_BLOCKED_LINEAR_OP_DEF_HPP
00031 #define THYRA_DEFAULT_BLOCKED_LINEAR_OP_DEF_HPP
00032 
00033 
00034 #include "Thyra_DefaultBlockedLinearOp_decl.hpp"
00035 #include "Thyra_DefaultProductVectorSpace.hpp"
00036 #include "Thyra_DefaultProductVector.hpp"
00037 #include "Thyra_DefaultProductMultiVector.hpp"
00038 #include "Thyra_MultiVectorStdOps.hpp"
00039 #include "Thyra_AssertOp.hpp"
00040 #include "Teuchos_Utils.hpp"
00041 
00042 
00043 namespace Thyra {
00044 
00045 
00046 // Constructors
00047 
00048 
00049 template<class Scalar>
00050 DefaultBlockedLinearOp<Scalar>::DefaultBlockedLinearOp()
00051   :numRowBlocks_(0), numColBlocks_(0), blockFillIsActive_(false)
00052 {}
00053 
00054 
00055 // Overridden from PhysicallyBlockedLinearOpBase
00056 
00057 
00058 template<class Scalar>
00059 void DefaultBlockedLinearOp<Scalar>::beginBlockFill()
00060 {
00061   assertBlockFillIsActive(false);
00062   uninitialize();
00063   resetStorage(0,0);
00064 }
00065 
00066 
00067 template<class Scalar>
00068 void DefaultBlockedLinearOp<Scalar>::beginBlockFill(
00069   const int numRowBlocks, const int numColBlocks
00070   )
00071 {
00072   assertBlockFillIsActive(false);
00073   uninitialize();
00074   resetStorage(numRowBlocks,numColBlocks);
00075 }
00076 
00077 
00078 template<class Scalar>
00079 void DefaultBlockedLinearOp<Scalar>::beginBlockFill(
00080   const RCP<const ProductVectorSpaceBase<Scalar> > &productRange
00081   ,const RCP<const ProductVectorSpaceBase<Scalar> > &productDomain
00082   )
00083 {
00084   using Teuchos::rcp_dynamic_cast;
00085   assertBlockFillIsActive(false);
00086   uninitialize();
00087   productRange_ = productRange.assert_not_null();
00088   productDomain_ = productDomain.assert_not_null();
00089   defaultProductRange_ =
00090     rcp_dynamic_cast<const DefaultProductVectorSpace<Scalar> >(productRange_);
00091   defaultProductDomain_ =
00092     rcp_dynamic_cast<const DefaultProductVectorSpace<Scalar> >(productDomain_);
00093   // Note: the above spaces must be set before calling the next function!
00094   resetStorage(productRange_->numBlocks(), productDomain_->numBlocks());
00095 }
00096 
00097 
00098 template<class Scalar>
00099 bool DefaultBlockedLinearOp<Scalar>::blockFillIsActive() const
00100 {
00101   return blockFillIsActive_;
00102 }
00103 
00104 
00105 template<class Scalar>
00106 bool DefaultBlockedLinearOp<Scalar>::acceptsBlock(
00107   const int i, const int j
00108   ) const
00109 {
00110   assertBlockFillIsActive(true);
00111   assertBlockRowCol(i,j);
00112   return true;
00113 }
00114 
00115 
00116 template<class Scalar>
00117 void DefaultBlockedLinearOp<Scalar>::setNonconstBlock(
00118   const int i, const int j
00119   ,const RCP<LinearOpBase<Scalar> > &block
00120   )
00121 {
00122   setBlockImpl(i, j, block);
00123 }
00124 
00125 
00126 template<class Scalar>
00127 void DefaultBlockedLinearOp<Scalar>::setBlock(
00128   const int i, const int j
00129   ,const RCP<const LinearOpBase<Scalar> > &block
00130   )
00131 {
00132   setBlockImpl(i, j, block);
00133 }
00134 
00135 
00136 template<class Scalar>
00137 void DefaultBlockedLinearOp<Scalar>::endBlockFill()
00138 {
00139 
00140   using Teuchos::as;
00141 
00142   assertBlockFillIsActive(true);
00143 
00144   // 2009/05/06: rabartl: ToDo: When doing a flexible block fill
00145   // (Ops_stack_.size() > 0), we need to assert that all of the block rows and
00146   // columns have been filled in.  I don't think we do that here.
00147 
00148   // Get the number of block rows and columns
00149   if (nonnull(productRange_)) {
00150     numRowBlocks_ = productRange_->numBlocks();
00151     numColBlocks_ = productDomain_->numBlocks();
00152   }
00153   else {
00154     numRowBlocks_ = rangeBlocks_.size();
00155     numColBlocks_ = domainBlocks_.size();
00156     // NOTE: Above, whether doing a flexible fill or not, all of the blocks
00157     // must be set in order to have a valid filled operator so this
00158     // calculation should be correct.
00159   }
00160 
00161   // Assert that all of the block rows and columns have at least one entry if
00162   // the spaces were not given up front.
00163 #ifdef TEUCHOS_DEBUG
00164   if (is_null(productRange_)) {
00165     for (int i = 0; i < numRowBlocks_; ++i) {
00166       TEST_FOR_EXCEPTION(
00167         !rangeBlocks_[i].get(), std::logic_error
00168         ,"DefaultBlockedLinearOp<Scalar>::endBlockFill():"
00169         " Error, no linear operator block for the i="<<i<<" block row was added"
00170         " and we can not complete the block fill!"
00171         );
00172     }
00173     for(int j = 0; j < numColBlocks_; ++j) {
00174       TEST_FOR_EXCEPTION(
00175         !domainBlocks_[j].get(), std::logic_error
00176         ,"DefaultBlockedLinearOp<Scalar>::endBlockFill():"
00177         " Error, no linear operator block for the j="
00178         <<j<<" block column was added"
00179         " and we can not complete the block fill!"
00180         );
00181     }
00182   }
00183 #endif
00184   
00185   // Insert the block LOB objects if doing a flexible fill.
00186   if (Ops_stack_.size()) {
00187     Ops_.resize(numRowBlocks_*numColBlocks_);
00188     for ( int k = 0; k < as<int>(Ops_stack_.size()); ++k ) {
00189       const BlockEntry<Scalar> &block_i_j = Ops_stack_[k];
00190       Ops_[numRowBlocks_*block_i_j.j + block_i_j.i] = block_i_j.block;
00191     }
00192     Ops_stack_.resize(0);
00193   }
00194 
00195   // Set the product range and domain spaces if not already set
00196   if (is_null(productRange_)) {
00197     adjustBlockSpaces();
00198     defaultProductRange_ = productVectorSpace<Scalar>(rangeBlocks_());
00199     defaultProductDomain_ = productVectorSpace<Scalar>(domainBlocks_());
00200     productRange_ = defaultProductRange_;
00201     productDomain_ = defaultProductDomain_;
00202   }
00203 
00204   rangeBlocks_.resize(0);
00205   domainBlocks_.resize(0);
00206 
00207   blockFillIsActive_ = false;
00208 
00209 }
00210 
00211 
00212 template<class Scalar>
00213 void DefaultBlockedLinearOp<Scalar>::uninitialize()
00214 {
00215   productRange_ = Teuchos::null;
00216   productDomain_ = Teuchos::null;
00217   numRowBlocks_ = 0;
00218   numColBlocks_ = 0;
00219   Ops_.resize(0);
00220   Ops_stack_.resize(0);
00221   rangeBlocks_.resize(0);
00222   domainBlocks_.resize(0);
00223   blockFillIsActive_ = false;
00224 }
00225 
00226 
00227 // Overridden from BlockedLinearOpBase
00228 
00229 
00230 template<class Scalar>
00231 RCP<const ProductVectorSpaceBase<Scalar> >
00232 DefaultBlockedLinearOp<Scalar>::productRange() const
00233 {
00234   return productRange_;
00235 }
00236 
00237 
00238 template<class Scalar>
00239 RCP<const ProductVectorSpaceBase<Scalar> >
00240 DefaultBlockedLinearOp<Scalar>::productDomain() const
00241 {
00242   return productDomain_;
00243 }
00244 
00245 
00246 template<class Scalar>
00247 bool DefaultBlockedLinearOp<Scalar>::blockExists(
00248   const int i, const int j
00249   ) const
00250 {
00251   assertBlockFillIsActive(false);
00252   assertBlockRowCol(i,j);
00253   return true;
00254 } 
00255 
00256 
00257 template<class Scalar>
00258 bool DefaultBlockedLinearOp<Scalar>::blockIsConst(
00259   const int i, const int j
00260   ) const
00261 {
00262 #ifdef TEUCHOS_DEBUG
00263   TEST_FOR_EXCEPT(!blockExists(i,j));
00264 #endif
00265   assertBlockFillIsActive(false);
00266   assertBlockRowCol(i,j);
00267   return Ops_[numRowBlocks_*j+i].isConst();
00268 }
00269 
00270 
00271 template<class Scalar>
00272 RCP<LinearOpBase<Scalar> >
00273 DefaultBlockedLinearOp<Scalar>::getNonconstBlock(const int i, const int j)
00274 {
00275 #ifdef TEUCHOS_DEBUG
00276   TEST_FOR_EXCEPT(!blockExists(i,j));
00277 #endif
00278   assertBlockFillIsActive(false);
00279   assertBlockRowCol(i,j);
00280   return Ops_[numRowBlocks_*j+i].getNonconstObj();
00281 } 
00282 
00283 
00284 template<class Scalar>
00285 RCP<const LinearOpBase<Scalar> >
00286 DefaultBlockedLinearOp<Scalar>::getBlock(const int i, const int j) const
00287 {
00288 #ifdef TEUCHOS_DEBUG
00289   TEST_FOR_EXCEPT(!blockExists(i,j));
00290 #endif
00291   assertBlockFillIsActive(false);
00292   assertBlockRowCol(i,j);
00293   return Ops_[numRowBlocks_*j+i];
00294 } 
00295 
00296 
00297 // Overridden from LinearOpBase
00298 
00299 
00300 template<class Scalar>
00301 RCP< const VectorSpaceBase<Scalar> >
00302 DefaultBlockedLinearOp<Scalar>::range() const
00303 {
00304   return productRange_;
00305 }
00306 
00307 
00308 template<class Scalar>
00309 RCP< const VectorSpaceBase<Scalar> >
00310 DefaultBlockedLinearOp<Scalar>::domain() const
00311 {
00312   return productDomain_;
00313 }
00314 
00315 
00316 template<class Scalar>
00317 RCP<const LinearOpBase<Scalar> >
00318 DefaultBlockedLinearOp<Scalar>::clone() const
00319 {
00320   return Teuchos::null; // ToDo: Implement this when needed!
00321 }
00322 
00323 
00324 // Overridden from Teuchos::Describable
00325 
00326 
00327 template<class Scalar>
00328 std::string DefaultBlockedLinearOp<Scalar>::description() const
00329 {
00330   assertBlockFillIsActive(false);
00331   std::ostringstream oss;
00332   oss
00333     << Teuchos::Describable::description() << "{"
00334     << "numRowBlocks="<<numRowBlocks_
00335     << ",numColBlocks="<<numColBlocks_
00336     << "}";
00337   return oss.str();
00338 }
00339 
00340 
00341 template<class Scalar>
00342 void DefaultBlockedLinearOp<Scalar>::describe(
00343   Teuchos::FancyOStream &out_arg
00344   ,const Teuchos::EVerbosityLevel verbLevel
00345   ) const
00346 {
00347   typedef Teuchos::ScalarTraits<Scalar> ST;
00348   using Teuchos::rcpFromRef;
00349   using Teuchos::FancyOStream;
00350   using Teuchos::OSTab;
00351   assertBlockFillIsActive(false);
00352   RCP<FancyOStream> out = rcpFromRef(out_arg);
00353   OSTab tab(out);
00354   switch(verbLevel) {
00355     case Teuchos::VERB_DEFAULT:
00356     case Teuchos::VERB_LOW:
00357       *out << this->description() << std::endl;
00358       break;
00359     case Teuchos::VERB_MEDIUM:
00360     case Teuchos::VERB_HIGH:
00361     case Teuchos::VERB_EXTREME:
00362     {
00363       *out
00364         << Teuchos::Describable::description() << "{"
00365         << "rangeDim=" << this->range()->dim()
00366         << ",domainDim=" << this->domain()->dim()
00367         << ",numRowBlocks=" << numRowBlocks_
00368         << ",numColBlocks=" << numColBlocks_
00369         << "}\n";
00370       OSTab tab(out);
00371       *out
00372         << "Constituent LinearOpBase objects for M = [ Op[0,0] ..."
00373         << " ; ... ; ... Op[numRowBlocks-1,numColBlocks-1] ]:\n";
00374       tab.incrTab();
00375       for( int i = 0; i < numRowBlocks_; ++i ) {
00376         for( int j = 0; j < numColBlocks_; ++j ) {
00377           *out << "Op["<<i<<","<<j<<"] = ";
00378           RCP<const LinearOpBase<Scalar> >
00379             block_i_j = getBlock(i,j);
00380           if(block_i_j.get())
00381             *out << Teuchos::describe(*getBlock(i,j),verbLevel);
00382           else
00383             *out << "NULL\n";
00384         }
00385       }
00386       break;
00387     }
00388     default:
00389       TEST_FOR_EXCEPT(true); // Should never get here!
00390   }
00391 }
00392 
00393 
00394 // protected
00395 
00396 
00397 // Overridden from SingleScalarLinearOpBase
00398 
00399 
00400 template<class Scalar>
00401 bool DefaultBlockedLinearOp<Scalar>::opSupported(
00402   EOpTransp M_trans
00403   ) const
00404 {
00405   bool opSupported = true;
00406   for( int i = 0; i < numRowBlocks_; ++i ) {
00407     for( int j = 0; j < numColBlocks_; ++j ) {
00408       RCP<const LinearOpBase<Scalar> >
00409         block_i_j = getBlock(i,j);
00410       if( block_i_j.get() && !Thyra::opSupported(*block_i_j,M_trans) )
00411         opSupported = false;
00412     }
00413   }
00414   return opSupported;
00415 }
00416 
00417 
00418 template<class Scalar>
00419 void DefaultBlockedLinearOp<Scalar>::apply(
00420   const EOpTransp M_trans
00421   ,const MultiVectorBase<Scalar> &X_in
00422   ,MultiVectorBase<Scalar> *Y_inout
00423   ,const Scalar alpha
00424   ,const Scalar beta
00425   ) const
00426 {
00427 
00428   using Teuchos::rcpFromRef;
00429   typedef Teuchos::ScalarTraits<Scalar> ST;
00430   typedef RCP<MultiVectorBase<Scalar> > MultiVectorPtr;
00431   typedef RCP<const MultiVectorBase<Scalar> > ConstMultiVectorPtr;
00432   typedef RCP<const LinearOpBase<Scalar> > ConstLinearOpPtr;
00433 
00434 #ifdef TEUCHOS_DEBUG
00435   THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(
00436     "DefaultBlockedLinearOp<Scalar>::apply(...)",*this,M_trans,X_in,Y_inout
00437     );
00438 #endif // TEUCHOS_DEBUG 
00439   
00440   const bool
00441     struct_transp = (real_trans(M_trans)!=NOTRANS); // Structural transpose?
00442   const int
00443     opNumRowBlocks = ( !struct_transp ? numRowBlocks_ : numColBlocks_ ), 
00444     opNumColBlocks = ( !struct_transp ? numColBlocks_ : numRowBlocks_ ); 
00445   
00446   //
00447   // Y = alpha * op(M) * X + beta*Y
00448   //
00449   // =>
00450   //
00451   // Y[i] = beta+Y[i] + sum(alpha*op(Op)[i,j]*X[j],j=0...opNumColBlocks-1)
00452   //
00453   // , for i=0...opNumRowBlocks-1
00454   //
00455 
00456   const RCP<const DefaultProductVectorSpace<Scalar> >
00457     defaultProductRange_op = ( real_trans(M_trans)==NOTRANS
00458       ? defaultProductRange_ : defaultProductDomain_ ),
00459     defaultProductDomain_op = ( real_trans(M_trans)==NOTRANS
00460       ? defaultProductDomain_ : defaultProductRange_ );
00461 
00462   const RCP<const ProductMultiVectorBase<Scalar> >
00463     X = castOrCreateSingleBlockProductMultiVector<Scalar>(
00464       defaultProductDomain_op, rcpFromRef(X_in));
00465   const RCP<ProductMultiVectorBase<Scalar> >
00466     Y = nonconstCastOrCreateSingleBlockProductMultiVector<Scalar>(
00467       defaultProductRange_op, rcpFromRef(*Y_inout));
00468 
00469   for( int i = 0; i < opNumRowBlocks; ++i ) {
00470     MultiVectorPtr Y_i = Y->getNonconstMultiVectorBlock(i);
00471     for( int j = 0; j < opNumColBlocks; ++j ) {
00472       ConstLinearOpPtr
00473         Op_i_j = ( !struct_transp ? getBlock(i,j) : getBlock(j,i) );
00474       ConstMultiVectorPtr
00475         X_j = X->getMultiVectorBlock(j);
00476       if(j==0) {
00477         if (nonnull(Op_i_j))
00478           Thyra::apply(*Op_i_j, M_trans,* X_j, Y_i.ptr(), alpha, beta);
00479         else
00480           scale(beta, Y_i.ptr());
00481       }
00482       else {
00483         if (nonnull(Op_i_j))
00484           Thyra::apply(*Op_i_j, M_trans, *X_j, Y_i.ptr(), alpha, ST::one());
00485       }
00486     }
00487   }
00488 }
00489 
00490 
00491 // private
00492 
00493 
00494 template<class Scalar>
00495 void DefaultBlockedLinearOp<Scalar>::resetStorage(
00496   const int numRowBlocks, const int numColBlocks
00497   )
00498 {
00499   numRowBlocks_ = numRowBlocks;
00500   numColBlocks_ = numColBlocks;
00501   Ops_.resize(numRowBlocks_*numColBlocks_);
00502   if (is_null(productRange_)) {
00503     rangeBlocks_.resize(numRowBlocks);
00504     domainBlocks_.resize(numColBlocks);
00505   }
00506   blockFillIsActive_ = true;
00507 }
00508 
00509 
00510 template<class Scalar>
00511 void DefaultBlockedLinearOp<Scalar>::assertBlockFillIsActive(
00512   bool blockFillIsActive
00513   ) const
00514 {
00515 #ifdef TEUCHOS_DEBUG
00516   TEST_FOR_EXCEPT(!(blockFillIsActive_==blockFillIsActive));
00517 #endif
00518 }
00519 
00520 
00521 template<class Scalar>
00522 void DefaultBlockedLinearOp<Scalar>::assertBlockRowCol(
00523   const int i, const int j
00524   ) const
00525 {
00526 #ifdef TEUCHOS_DEBUG
00527   TEST_FOR_EXCEPTION(
00528     !( 0 <= i ), std::logic_error
00529     ,"Error, i="<<i<<" is invalid!"
00530     );
00531   TEST_FOR_EXCEPTION(
00532     !( 0 <= j ), std::logic_error
00533     ,"Error, j="<<j<<" is invalid!"
00534     );
00535   // Only validate upper range if the number of row and column blocks is
00536   // fixed!
00537   if(Ops_.size()) {
00538     TEST_FOR_EXCEPTION(
00539       !( 0 <= i && i < numRowBlocks_ ), std::logic_error
00540       ,"Error, i="<<i<<" does not fall in the range [0,"<<numRowBlocks_-1<<"]!"
00541       );
00542     TEST_FOR_EXCEPTION(
00543       !( 0 <= j && j < numColBlocks_ ), std::logic_error
00544       ,"Error, j="<<j<<" does not fall in the range [0,"<<numColBlocks_-1<<"]!"
00545       );
00546   }
00547 #endif
00548 }
00549 
00550 
00551 template<class Scalar>
00552 void DefaultBlockedLinearOp<Scalar>::setBlockSpaces(
00553   const int i, const int j, const LinearOpBase<Scalar> &block
00554   )
00555 {
00556 
00557   typedef std::string s;
00558   using Teuchos::toString;
00559   assertBlockFillIsActive(true);
00560   assertBlockRowCol(i,j);
00561 
00562   // Validate that if the vector space block is already set that it is
00563   // compatible with the block that is being set.
00564   if( i < numRowBlocks_ && j < numColBlocks_ ) {
00565 #ifdef TEUCHOS_DEBUG
00566     RCP<const VectorSpaceBase<Scalar> >
00567       rangeBlock = (
00568         productRange_.get()
00569         ? productRange_->getBlock(i)
00570         : rangeBlocks_[i]
00571         ),
00572       domainBlock = (
00573         productDomain_.get()
00574         ? productDomain_->getBlock(j)
00575         : domainBlocks_[j]
00576         );
00577     if(rangeBlock.get()) {
00578       THYRA_ASSERT_VEC_SPACES_NAMES(
00579         "DefaultBlockedLinearOp<Scalar>::setBlockSpaces(i,j,block):\n\n"
00580         "Adding block: " + block.description(),
00581         *rangeBlock,("(*productRange->getBlock("+toString(i)+"))"),
00582         *block.range(),("(*block["+toString(i)+","+toString(j)+"].range())")
00583         );
00584     }
00585     if(domainBlock.get()) {
00586       THYRA_ASSERT_VEC_SPACES_NAMES(
00587         "DefaultBlockedLinearOp<Scalar>::setBlockSpaces(i,j,block):\n\n"
00588         "Adding block: " + block.description(),
00589         *domainBlock,("(*productDomain->getBlock("+toString(j)+"))"),
00590         *block.domain(),("(*block["+toString(i)+","+toString(j)+"].domain())")
00591         );
00592     }
00593 #endif // TEUCHOS_DEBUG
00594   }
00595 
00596   // Add spaces missing range and domain space blocks if we are doing a
00597   // flexible fill (otherwise these loops will not be executed)
00598   for( int k = numRowBlocks_; k <= i; ++k )
00599     rangeBlocks_.push_back(Teuchos::null);
00600   for( int k = numColBlocks_; k <= j; ++k )
00601     domainBlocks_.push_back(Teuchos::null);
00602 
00603   // Set the incoming range and domain blocks if not already set
00604   if(!productRange_.get()) {
00605     if(!rangeBlocks_[i].get())
00606       rangeBlocks_[i] = block.range().assert_not_null();
00607     if(!domainBlocks_[j].get()) {
00608       domainBlocks_[j] = block.domain().assert_not_null();
00609     }
00610   }
00611 
00612   // Update the current number of row and columns blocks if doing a flexible
00613   // fill.
00614   if(!Ops_.size()) {
00615     numRowBlocks_ = rangeBlocks_.size();
00616     numColBlocks_ = domainBlocks_.size();
00617   }
00618 
00619 }
00620 
00621 
00622 template<class Scalar>
00623 template<class LinearOpType>
00624 void DefaultBlockedLinearOp<Scalar>::setBlockImpl(
00625   const int i, const int j,
00626   const RCP<LinearOpType> &block
00627   )
00628 {
00629   setBlockSpaces(i, j, *block);
00630   if (Ops_.size()) {
00631     // We are doing a fill with a fixed number of row and column blocks so we
00632     // can just set this.
00633     Ops_[numRowBlocks_*j+i] = block;
00634   }
00635   else {
00636     // We are doing a flexible fill so add the block to the stack of blocks or
00637     // replace a block that already exists.
00638     bool foundBlock = false;
00639     for( unsigned int k = 0; k < Ops_stack_.size(); ++k ) {
00640       BlockEntry<Scalar> &block_i_j = Ops_stack_[k];
00641       if( block_i_j.i == i && block_i_j.j == j ) {
00642         block_i_j.block = block;
00643         foundBlock = true;
00644         break;
00645       }
00646     }
00647     if(!foundBlock)
00648       Ops_stack_.push_back(BlockEntry<Scalar>(i,j,block));
00649   }
00650 }
00651 
00652 
00653 template<class Scalar>
00654 void DefaultBlockedLinearOp<Scalar>::adjustBlockSpaces()
00655 {
00656 
00657 #ifdef TEUCHOS_DEBUG
00658   TEUCHOS_ASSERT_INEQUALITY(Ops_.size(), !=, 0);
00659 #endif
00660 
00661   //
00662   // Loop through the rows and columns looking for rows with mixed
00663   // single-space range and/or domain spaces on operators and set the single
00664   // spaces as the block space if it exists.
00665   //
00666   // NOTE: Once we get here, we can safely assume that all of the operators
00667   // are compatible w.r.t. their spaces so if there are rows and/or columns
00668   // with mixed product and single vector spaces that we can just pick the
00669   // single vector space for the whole row and/or column.
00670   //
00671 
00672   // Adjust blocks in the range space
00673   for (int i = 0; i < numRowBlocks_; ++i) {
00674     for (int j = 0; j < numColBlocks_; ++j) {
00675       const RCP<const LinearOpBase<Scalar> >
00676         op_i_j = Ops_[numRowBlocks_*j+i];
00677       if (is_null(op_i_j))
00678         continue;
00679       const RCP<const VectorSpaceBase<Scalar> > range_i_j = op_i_j->range();
00680       if (is_null(productVectorSpaceBase<Scalar>(range_i_j, false))) {
00681         rangeBlocks_[i] = range_i_j;
00682         break;
00683       }
00684     }
00685   }
00686 
00687   // Adjust blocks in the domain space
00688   for (int j = 0; j < numColBlocks_; ++j) {
00689     for (int i = 0; i < numRowBlocks_; ++i) {
00690       const RCP<const LinearOpBase<Scalar> >
00691         op_i_j = Ops_[numRowBlocks_*j+i];
00692       if (is_null(op_i_j))
00693         continue;
00694       const RCP<const VectorSpaceBase<Scalar> >
00695         domain_i_j = op_i_j->domain();
00696       if (is_null(productVectorSpaceBase<Scalar>(domain_i_j, false))) {
00697         domainBlocks_[j] = domain_i_j;
00698         break;
00699       }
00700     }
00701   }
00702 
00703 }
00704 
00705 
00706 } // namespace Thyra
00707 
00708 
00709 template<class Scalar>
00710 Teuchos::RCP<Thyra::DefaultBlockedLinearOp<Scalar> >
00711 Thyra::defaultBlockedLinearOp()
00712 {
00713   return Teuchos::rcp(new DefaultBlockedLinearOp<Scalar>());
00714 }
00715 
00716 
00717 template<class Scalar>
00718 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00719 Thyra::block1x1(
00720   const RCP<const LinearOpBase<Scalar> > &A00,
00721   const std::string &label
00722   )
00723 {
00724   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00725     M = defaultBlockedLinearOp<Scalar>();
00726   M->beginBlockFill(1,1);
00727   M->setBlock(0, 0, A00);
00728   M->endBlockFill();
00729   if (label.length())
00730     M->setObjectLabel(label);
00731   return M;
00732 }
00733 
00734 
00735 template<class Scalar>
00736 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00737 Thyra::block1x2(
00738   const RCP<const LinearOpBase<Scalar> > &A00,
00739   const RCP<const LinearOpBase<Scalar> > &A01,
00740   const std::string &label
00741   )
00742 {
00743   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00744     M = defaultBlockedLinearOp<Scalar>();
00745   M->beginBlockFill(1,2);
00746   if(A00.get()) M->setBlock(0,0,A00);
00747   if(A01.get()) M->setBlock(0,1,A01);
00748   M->endBlockFill();
00749   if (label.length())
00750     M->setObjectLabel(label);
00751   return M;
00752 }
00753 
00754 
00755 template<class Scalar>
00756 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00757 Thyra::block2x1(
00758   const RCP<const LinearOpBase<Scalar> > &A00,
00759   const RCP<const LinearOpBase<Scalar> > &A10,
00760   const std::string &label
00761   )
00762 {
00763   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00764     M = defaultBlockedLinearOp<Scalar>();
00765   M->beginBlockFill(2,1);
00766   if(A00.get()) M->setBlock(0,0,A00);
00767   if(A10.get()) M->setBlock(1,0,A10);
00768   M->endBlockFill();
00769   if (label.length())
00770     M->setObjectLabel(label);
00771   return M;
00772 }
00773 
00774 
00775 template<class Scalar>
00776 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> >
00777 Thyra::block2x2(
00778   const RCP<const LinearOpBase<Scalar> > &A00,
00779   const RCP<const LinearOpBase<Scalar> > &A01,
00780   const RCP<const LinearOpBase<Scalar> > &A10,
00781   const RCP<const LinearOpBase<Scalar> > &A11,
00782   const std::string &label
00783   )
00784 {
00785   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00786     M = defaultBlockedLinearOp<Scalar>();
00787   M->beginBlockFill(2,2);
00788   if(A00.get()) M->setBlock(0,0,A00);
00789   if(A01.get()) M->setBlock(0,1,A01);
00790   if(A10.get()) M->setBlock(1,0,A10);
00791   if(A11.get()) M->setBlock(1,1,A11);
00792   M->endBlockFill();
00793   if (label.length())
00794     M->setObjectLabel(label);
00795   return M;
00796 }
00797 
00798 
00799 template<class Scalar>
00800 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00801 Thyra::nonconstBlock1x1(
00802   const RCP<LinearOpBase<Scalar> > &A00,
00803   const std::string &label
00804   )
00805 {
00806   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00807     M = defaultBlockedLinearOp<Scalar>();
00808   M->beginBlockFill(1, 1);
00809   M->setNonconstBlock(0, 0, A00);
00810   M->endBlockFill();
00811   if (label.length())
00812     M->setObjectLabel(label);
00813   return M;
00814 }
00815 
00816 
00817 template<class Scalar>
00818 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00819 Thyra::nonconstBlock1x2(
00820   const RCP<LinearOpBase<Scalar> > &A00,
00821   const RCP<LinearOpBase<Scalar> > &A01,
00822   const std::string &label
00823   )
00824 {
00825   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00826     M = defaultBlockedLinearOp<Scalar>();
00827   M->beginBlockFill(1,2);
00828   if(A00.get()) M->setNonconstBlock(0,0,A00);
00829   if(A01.get()) M->setNonconstBlock(0,1,A01);
00830   M->endBlockFill();
00831   if (label.length())
00832     M->setObjectLabel(label);
00833   return M;
00834 }
00835 
00836 
00837 template<class Scalar>
00838 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00839 Thyra::nonconstBlock2x1(
00840   const RCP<LinearOpBase<Scalar> > &A00,
00841   const RCP<LinearOpBase<Scalar> > &A10,
00842   const std::string &label
00843   )
00844 {
00845   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00846     M = defaultBlockedLinearOp<Scalar>();
00847   M->beginBlockFill(2,1);
00848   if(A00.get()) M->setNonconstBlock(0,0,A00);
00849   if(A10.get()) M->setNonconstBlock(1,0,A10);
00850   M->endBlockFill();
00851   if (label.length())
00852     M->setObjectLabel(label);
00853   return M;
00854 }
00855 
00856 
00857 template<class Scalar>
00858 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00859 Thyra::nonconstBlock2x2(
00860   const RCP<LinearOpBase<Scalar> > &A00,
00861   const RCP<LinearOpBase<Scalar> > &A01,
00862   const RCP<LinearOpBase<Scalar> > &A10,
00863   const RCP<LinearOpBase<Scalar> > &A11,
00864   const std::string &label
00865   )
00866 {
00867   RCP<PhysicallyBlockedLinearOpBase<Scalar> >
00868     M = defaultBlockedLinearOp<Scalar>();
00869   M->beginBlockFill(2,2);
00870   if(A00.get()) M->setNonconstBlock(0,0,A00);
00871   if(A01.get()) M->setNonconstBlock(0,1,A01);
00872   if(A10.get()) M->setNonconstBlock(1,0,A10);
00873   if(A11.get()) M->setNonconstBlock(1,1,A11);
00874   M->endBlockFill();
00875   if (label.length())
00876     M->setObjectLabel(label);
00877   return M;
00878 }
00879 
00880 
00881 //
00882 // Explicit instantiation macro
00883 //
00884 // Must be expanded from within the Thyra namespace!
00885 //
00886 
00887 
00888 #define THYRA_DEFAULT_BLOCKED_LINEAR_OP_INSTANT(SCALAR) \
00889   \
00890   template class DefaultBlockedLinearOp<SCALAR >; \
00891    \
00892   template RCP<DefaultBlockedLinearOp<SCALAR > > \
00893   defaultBlockedLinearOp(); \
00894    \
00895   template RCP<const LinearOpBase<SCALAR > > \
00896   block1x1( \
00897     const RCP<const LinearOpBase<SCALAR > > &A00, \
00898     const std::string &label \
00899     ); \
00900    \
00901   template RCP<const LinearOpBase<SCALAR > > \
00902   block1x2( \
00903     const RCP<const LinearOpBase<SCALAR > > &A00, \
00904     const RCP<const LinearOpBase<SCALAR > > &A01, \
00905     const std::string &label \
00906     ); \
00907    \
00908   template RCP<const LinearOpBase<SCALAR > > \
00909   block2x1( \
00910     const RCP<const LinearOpBase<SCALAR > > &A00, \
00911     const RCP<const LinearOpBase<SCALAR > > &A10, \
00912     const std::string &label \
00913     ); \
00914    \
00915   template RCP<const LinearOpBase<SCALAR > > \
00916   block2x2( \
00917     const RCP<const LinearOpBase<SCALAR > > &A00, \
00918     const RCP<const LinearOpBase<SCALAR > > &A01, \
00919     const RCP<const LinearOpBase<SCALAR > > &A10, \
00920     const RCP<const LinearOpBase<SCALAR > > &A11, \
00921     const std::string &label \
00922     ); \
00923    \
00924   template RCP<LinearOpBase<SCALAR > > \
00925   nonconstBlock1x1( \
00926     const RCP<LinearOpBase<SCALAR > > &A00, \
00927     const std::string &label \
00928     ); \
00929    \
00930   template RCP<LinearOpBase<SCALAR > > \
00931   nonconstBlock1x2( \
00932     const RCP<LinearOpBase<SCALAR > > &A00, \
00933     const RCP<LinearOpBase<SCALAR > > &A01, \
00934     const std::string &label \
00935     ); \
00936    \
00937   template RCP<LinearOpBase<SCALAR > > \
00938   nonconstBlock2x1( \
00939     const RCP<LinearOpBase<SCALAR > > &A00, \
00940     const RCP<LinearOpBase<SCALAR > > &A10, \
00941     const std::string &label \
00942     ); \
00943    \
00944   template RCP<LinearOpBase<SCALAR > > \
00945   nonconstBlock2x2( \
00946     const RCP<LinearOpBase<SCALAR > > &A00, \
00947     const RCP<LinearOpBase<SCALAR > > &A01, \
00948     const RCP<LinearOpBase<SCALAR > > &A10, \
00949     const RCP<LinearOpBase<SCALAR > > &A11, \
00950     const std::string &label \
00951     );
00952 
00953 
00954 #endif  // THYRA_DEFAULT_BLOCKED_LINEAR_OP_DEF_HPP

Generated on Wed May 12 21:26:53 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7