|
Teko Version of the Day
|
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
1.7.4