Teko Version of the Day
Teko_EpetraOperatorWrapper.cpp
00001 // @HEADER
00002 // 
00003 // ***********************************************************************
00004 // 
00005 //      Teko: A package for block and physics based preconditioning
00006 //                  Copyright 2010 Sandia Corporation 
00007 //  
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //  
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //  
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //  
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //  
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission. 
00025 //  
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //  
00038 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
00039 // 
00040 // ***********************************************************************
00041 // 
00042 // @HEADER
00043 
00044 
00045 #include "Teko_EpetraOperatorWrapper.hpp"
00046 #include "Thyra_SpmdVectorBase.hpp"
00047 #include "Thyra_MultiVectorStdOps.hpp"
00048 #ifdef HAVE_MPI
00049 #include "Teuchos_DefaultMpiComm.hpp"
00050 #endif
00051 #include "Teuchos_DefaultSerialComm.hpp"
00052 #include "Thyra_EpetraLinearOp.hpp"
00053 #include "Epetra_SerialComm.h"
00054 #include "Epetra_Vector.h"
00055 #ifdef HAVE_MPI
00056 #include "Epetra_MpiComm.h"
00057 #endif
00058 #include "Thyra_EpetraThyraWrappers.hpp"
00059 
00060 // #include "Thyra_LinearOperator.hpp"
00061 #include "Thyra_BlockedLinearOpBase.hpp"
00062 #include "Thyra_ProductVectorSpaceBase.hpp"
00063 
00064 #include "Teko_EpetraThyraConverter.hpp"
00065 #include "Teuchos_Ptr.hpp"
00066 
00067 
00068 namespace Teko { 
00069 namespace Epetra { 
00070 
00071 
00072 using namespace Teuchos;
00073 using namespace Thyra;
00074 
00075 DefaultMappingStrategy::DefaultMappingStrategy(const RCP<const Thyra::LinearOpBase<double> > & thyraOp,const Epetra_Comm & comm)
00076 {
00077    RCP<Epetra_Comm> newComm = rcp(comm.Clone());
00078 
00079    // extract vector spaces from linear operator
00080    domainSpace_ = thyraOp->domain();
00081    rangeSpace_ = thyraOp->range();
00082 
00083    domainMap_ = Teko::Epetra::thyraVSToEpetraMap(*domainSpace_,newComm);
00084    rangeMap_ = Teko::Epetra::thyraVSToEpetraMap(*rangeSpace_,newComm);
00085 }
00086 
00087 void DefaultMappingStrategy::copyEpetraIntoThyra(const Epetra_MultiVector& x, const Ptr<Thyra::MultiVectorBase<double> > & thyraVec,
00088                                       const EpetraOperatorWrapper & eow) const
00089 {
00090    Teko::Epetra::blockEpetraToThyra(x,thyraVec);
00091 }
00092 
00093 void DefaultMappingStrategy::copyThyraIntoEpetra(const RCP<const Thyra::MultiVectorBase<double> > & thyraVec, Epetra_MultiVector& v,
00094                                       const EpetraOperatorWrapper & eow) const
00095 {
00096    Teko::Epetra::blockThyraToEpetra(thyraVec,v);
00097 }
00098 
00099 EpetraOperatorWrapper::EpetraOperatorWrapper()
00100 {
00101    useTranspose_ = false;
00102    mapStrategy_ = Teuchos::null;
00103    thyraOp_ = Teuchos::null;
00104    comm_ = Teuchos::null;
00105    label_ = Teuchos::null;
00106 }
00107 
00108 EpetraOperatorWrapper::EpetraOperatorWrapper(const RCP<const Thyra::LinearOpBase<double> > & thyraOp)
00109 { 
00110    SetOperator(thyraOp); 
00111 }
00112 
00113 EpetraOperatorWrapper::EpetraOperatorWrapper(const RCP<const Thyra::LinearOpBase<double> > & thyraOp,const RCP<const MappingStrategy> & mapStrategy)
00114    : mapStrategy_(mapStrategy)
00115 {
00116    SetOperator(thyraOp);
00117 }
00118 
00119 EpetraOperatorWrapper::EpetraOperatorWrapper(const RCP<const MappingStrategy> & mapStrategy)
00120    : mapStrategy_(mapStrategy)
00121 {
00122    useTranspose_ = false;
00123    thyraOp_ = Teuchos::null;
00124    comm_ = Teuchos::null;
00125    label_ = Teuchos::null;
00126 }
00127 
00128 void EpetraOperatorWrapper::SetOperator(const RCP<const LinearOpBase<double> > & thyraOp,bool buildMap)
00129 {
00130    useTranspose_ = false;
00131    thyraOp_ = thyraOp;
00132    comm_ = getEpetraComm(*thyraOp);
00133    label_ = thyraOp_->description();
00134    if(mapStrategy_==Teuchos::null && buildMap)
00135       mapStrategy_ = Teuchos::rcp(new DefaultMappingStrategy(thyraOp,*comm_));
00136 }
00137 
00138 double EpetraOperatorWrapper::NormInf() const 
00139 {
00140   TEST_FOR_EXCEPTION(true, std::runtime_error,
00141                      "EpetraOperatorWrapper::NormInf not implemated");
00142   return 1.0;
00143 }
00144 
00145 int EpetraOperatorWrapper::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const
00146 {
00147    if (!useTranspose_)
00148    {
00149        // allocate space for each vector
00150        RCP<Thyra::MultiVectorBase<double> > tX;
00151        RCP<Thyra::MultiVectorBase<double> > tY; 
00152 
00153        tX = Thyra::createMembers(thyraOp_->domain(),X.NumVectors()); 
00154        tY = Thyra::createMembers(thyraOp_->range(),X.NumVectors());
00155 
00156        Thyra::assign(tX.ptr(),0.0);
00157        Thyra::assign(tY.ptr(),0.0);
00158 
00159        // copy epetra X into thyra X
00160        mapStrategy_->copyEpetraIntoThyra(X, tX.ptr(),*this);
00161        mapStrategy_->copyEpetraIntoThyra(Y, tY.ptr(),*this); // if this matrix isn't block square, this probably won't work!
00162 
00163        // perform matrix vector multiplication
00164        thyraOp_->apply(Thyra::NOTRANS,*tX,tY.ptr(),1.0,0.0);
00165 
00166        // copy thyra Y into epetra Y
00167        mapStrategy_->copyThyraIntoEpetra(tY, Y,*this);
00168    }
00169    else
00170    {
00171        TEUCHOS_ASSERT(false);
00172    }
00173  
00174    return 0;
00175 }
00176 
00177 
00178 int EpetraOperatorWrapper::ApplyInverse(const Epetra_MultiVector& X, 
00179                                       Epetra_MultiVector& Y) const
00180 {
00181   TEST_FOR_EXCEPTION(true, std::runtime_error,
00182                      "EpetraOperatorWrapper::ApplyInverse not implemented");
00183   return 1;
00184 }
00185 
00186 
00187 RCP<const Epetra_Comm> 
00188 EpetraOperatorWrapper::getEpetraComm(const Thyra::LinearOpBase<double>& inOp) const
00189 {
00190   RCP<const VectorSpaceBase<double> > vs = inOp.domain();
00191 
00192   RCP<const SpmdVectorSpaceBase<double> > spmd;
00193   RCP<const VectorSpaceBase<double> > current = vs;
00194   while(current!=Teuchos::null) {
00195      // try to cast to a product vector space first
00196      RCP<const ProductVectorSpaceBase<double> > prod
00197            = rcp_dynamic_cast<const ProductVectorSpaceBase<double> >(current);
00198 
00199      // figure out what type it is
00200      if(prod==Teuchos::null) {
00201         // hopfully this is a SPMD vector space
00202         spmd = rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(current);
00203 
00204         break;
00205      }
00206      else // get first convenient vector space
00207         current = prod->getBlock(0);
00208   }
00209 
00210   TEST_FOR_EXCEPTION(spmd==Teuchos::null, std::runtime_error, 
00211                      "EpetraOperatorWrapper requires std::vector space "
00212                      "blocks to be SPMD std::vector spaces");
00213 
00214   return Thyra::get_Epetra_Comm(*spmd->getComm());
00215 /*
00216   const Thyra::ConstLinearOperator<double> thyraOp = rcpFromRef(inOp); 
00217 
00218   RCP<Epetra_Comm> rtn;
00219   // VectorSpace<double> vs = thyraOp.domain().getBlock(0);
00220   RCP<const VectorSpaceBase<double> > vs = thyraOp.domain().getBlock(0).constPtr();
00221 
00222   // search for an SpmdVectorSpaceBase object
00223   RCP<const SpmdVectorSpaceBase<double> > spmd;
00224   RCP<const VectorSpaceBase<double> > current = vs;
00225   while(current!=Teuchos::null) {
00226      // try to cast to a product vector space first
00227      RCP<const ProductVectorSpaceBase<double> > prod
00228            = rcp_dynamic_cast<const ProductVectorSpaceBase<double> >(current);
00229 
00230      // figure out what type it is
00231      if(prod==Teuchos::null) {
00232         // hopfully this is a SPMD vector space
00233         spmd = rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(current);
00234 
00235         break;
00236      }
00237      else {
00238         // get first convenient vector space
00239         current = prod->getBlock(0);
00240      }
00241   }
00242 
00243   TEST_FOR_EXCEPTION(spmd==Teuchos::null, std::runtime_error, 
00244                      "EpetraOperatorWrapper requires std::vector space "
00245                      "blocks to be SPMD std::vector spaces");
00246 
00247   const SerialComm<Thyra::Ordinal>* serialComm 
00248     = dynamic_cast<const SerialComm<Thyra::Ordinal>*>(spmd->getComm().get());
00249 
00250 #ifdef HAVE_MPI
00251   const MpiComm<Thyra::Ordinal>* mpiComm 
00252     = dynamic_cast<const MpiComm<Thyra::Ordinal>*>(spmd->getComm().get());
00253 
00254   TEST_FOR_EXCEPTION(mpiComm==0 && serialComm==0, std::runtime_error, 
00255                      "SPMD std::vector space has a communicator that is "
00256                      "neither a serial comm nor an MPI comm");
00257 
00258   if (mpiComm != 0)
00259     {
00260       rtn = rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
00261     }
00262   else
00263     {
00264       rtn = rcp(new Epetra_SerialComm());
00265     }
00266 #else
00267   TEST_FOR_EXCEPTION(serialComm==0, std::runtime_error, 
00268                      "SPMD std::vector space has a communicator that is "
00269                      "neither a serial comm nor an MPI comm");
00270   rtn = rcp(new Epetra_SerialComm());
00271   
00272 #endif
00273 
00274   TEST_FOR_EXCEPTION(rtn.get()==0, std::runtime_error, "null communicator created");
00275   return rtn;
00276 */
00277 }
00278 
00279 int EpetraOperatorWrapper::GetBlockRowCount()
00280 {
00281    const RCP<const Thyra::BlockedLinearOpBase<double> > blkOp 
00282          = Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(getThyraOp());
00283 
00284    return blkOp->productRange()->numBlocks();
00285 }
00286 
00287 int EpetraOperatorWrapper::GetBlockColCount()
00288 {
00289    const RCP<const Thyra::BlockedLinearOpBase<double> > blkOp 
00290          = Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(getThyraOp());
00291 
00292    return blkOp->productDomain()->numBlocks();
00293 }
00294 
00295 
00296 } // namespace Epetra
00297 } // namespace Teko
 All Classes Files Functions Variables