|
Stratimikos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Stratimikos: Thyra-based strategies for linear solvers 00005 // Copyright (2006) 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 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #ifndef __Thyra_TsqrAdaptor_hpp 00043 #define __Thyra_TsqrAdaptor_hpp 00044 00045 #include <BelosConfigDefs.hpp> 00046 00047 // BelosThyraAdapter.hpp only includes this file if HAVE_BELOS_TSQR is 00048 // defined. Thus, it's OK to include TSQR header files here. 00049 00050 #include <Tsqr_NodeTsqrFactory.hpp> // create intranode TSQR object 00051 #include <Tsqr.hpp> // full (internode + intranode) TSQR 00052 #include <Tsqr_DistTsqr.hpp> // internode TSQR 00053 // Subclass of TSQR::MessengerBase, implemented using Teuchos 00054 // communicator template helper functions 00055 #include <Tsqr_TeuchosMessenger.hpp> 00056 #include <Kokkos_SerialNode.hpp> 00057 00058 //#include <Thyra_DetachedMultiVectorView.hpp> 00059 #include <Thyra_MultiVectorBase.hpp> 00060 //#include <Thyra_MultiVectorStdOps.hpp> 00061 #include <Thyra_SpmdVectorSpaceBase.hpp> 00062 00063 #ifdef HAVE_MPI 00064 # include <Teuchos_DefaultMpiComm.hpp> 00065 #endif // HAVE_MPI 00066 #include <Teuchos_DefaultSerialComm.hpp> 00067 #include <Teuchos_ParameterListAcceptorDefaultBase.hpp> 00068 00069 #include <stdexcept> 00070 00071 00072 namespace Thyra { 00073 00095 template<class Scalar> 00096 class TsqrAdaptor : public Teuchos::ParameterListAcceptorDefaultBase { 00097 public: 00098 typedef Thyra::MultiVectorBase<Scalar> MV; 00099 typedef Scalar scalar_type; 00100 typedef int ordinal_type; // MultiVectorBase really does use int for this 00101 typedef KokkosClassic::SerialNode node_type; // FIXME (mfh 18 Jun 2013) Would be better to defer to the MV subclass 00102 typedef Teuchos::SerialDenseMatrix<ordinal_type, scalar_type> dense_matrix_type; 00103 typedef typename Teuchos::ScalarTraits<scalar_type>::magnitudeType magnitude_type; 00104 00105 private: 00106 typedef TSQR::NodeTsqrFactory<node_type, scalar_type, ordinal_type> node_tsqr_factory_type; 00107 typedef typename node_tsqr_factory_type::node_tsqr_type node_tsqr_type; 00108 typedef TSQR::DistTsqr<ordinal_type, scalar_type> dist_tsqr_type; 00109 typedef TSQR::Tsqr<ordinal_type, scalar_type, node_tsqr_type> tsqr_type; 00110 00111 public: 00118 TsqrAdaptor (const Teuchos::RCP<Teuchos::ParameterList>& plist) : 00119 nodeTsqr_ (new node_tsqr_type), 00120 distTsqr_ (new dist_tsqr_type), 00121 tsqr_ (new tsqr_type (nodeTsqr_, distTsqr_)), 00122 ready_ (false) 00123 { 00124 throw std::logic_error ("Thyra adaptor for TSQR not implemented"); 00125 } 00126 00128 TsqrAdaptor () : 00129 nodeTsqr_ (new node_tsqr_type), 00130 distTsqr_ (new dist_tsqr_type), 00131 tsqr_ (new tsqr_type (nodeTsqr_, distTsqr_)), 00132 ready_ (false) 00133 { 00134 throw std::logic_error ("Thyra adaptor for TSQR not implemented"); 00135 } 00136 00137 Teuchos::RCP<const Teuchos::ParameterList> 00138 getValidParameters () const 00139 { 00140 using Teuchos::RCP; 00141 using Teuchos::rcp; 00142 using Teuchos::ParameterList; 00143 using Teuchos::parameterList; 00144 00145 if (defaultParams_.is_null()) { 00146 RCP<ParameterList> params = parameterList ("TSQR implementation"); 00147 params->set ("NodeTsqr", *(nodeTsqr_->getValidParameters ())); 00148 params->set ("DistTsqr", *(distTsqr_->getValidParameters ())); 00149 defaultParams_ = params; 00150 } 00151 return defaultParams_; 00152 } 00153 00154 void 00155 setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist) 00156 { 00157 using Teuchos::ParameterList; 00158 using Teuchos::parameterList; 00159 using Teuchos::RCP; 00160 using Teuchos::sublist; 00161 00162 RCP<ParameterList> params = plist.is_null() ? 00163 parameterList (*getValidParameters ()) : plist; 00164 nodeTsqr_->setParameterList (sublist (params, "NodeTsqr")); 00165 distTsqr_->setParameterList (sublist (params, "DistTsqr")); 00166 00167 this->setMyParamList (params); 00168 } 00169 00191 void 00192 factorExplicit (MV& A, 00193 MV& Q, 00194 dense_matrix_type& R, 00195 const bool forceNonnegativeDiagonal=false) 00196 { 00197 typedef KokkosClassic::MultiVector<scalar_type, node_type> KMV; 00198 00199 prepareTsqr (Q); // Finish initializing TSQR. 00200 KMV A_view = getNonConstView (A); 00201 KMV Q_view = getNonConstView (Q); 00202 tsqr_->factorExplicit (A_view, Q_view, R, false, 00203 forceNonnegativeDiagonal); 00204 } 00205 00236 int 00237 revealRank (MV& Q, 00238 dense_matrix_type& R, 00239 const magnitude_type& tol) 00240 { 00241 typedef KokkosClassic::MultiVector<scalar_type, node_type> KMV; 00242 00243 prepareTsqr (Q); // Finish initializing TSQR. 00244 00245 // FIXME (mfh 18 Oct 2010) Check Teuchos::Comm<int> object in Q 00246 // to make sure it is the same communicator as the one we are 00247 // using in our dist_tsqr_type implementation. 00248 KMV Q_view = getNonConstView (Q); 00249 return tsqr_->revealRank (Q_view, R, tol, false); 00250 } 00251 00252 private: 00254 Teuchos::RCP<node_type> node_; 00255 00257 Teuchos::RCP<node_tsqr_type> nodeTsqr_; 00258 00260 Teuchos::RCP<dist_tsqr_type> distTsqr_; 00261 00263 Teuchos::RCP<tsqr_type> tsqr_; 00264 00266 mutable Teuchos::RCP<const Teuchos::ParameterList> defaultParams_; 00267 00269 bool ready_; 00270 00281 static Teuchos::RCP<const Teuchos::Comm<int> > 00282 getComm (const MV& X) 00283 { 00284 using Teuchos::RCP; 00285 using Teuchos::rcp; 00286 using Teuchos::rcp_dynamic_cast; 00287 using Teuchos::rcp_implicit_cast; 00288 typedef Thyra::VectorSpaceBase<Scalar> space_base_type; 00289 typedef Thyra::SpmdVectorSpaceBase<Scalar> space_type; 00290 00291 // Thyra stores the communicator in the "vector space," but only 00292 // if that vector space is an SpmdVectorSpaceBase. 00293 RCP<const space_base_type> rangeBase = X.range (); 00294 TEUCHOS_TEST_FOR_EXCEPTION(rangeBase.is_null (), std::runtime_error, "X.range() is null."); 00295 RCP<const space_type> range = rcp_dynamic_cast<const space_type> (rangeBase); 00296 TEUCHOS_TEST_FOR_EXCEPTION(range.is_null (), std::runtime_error, "X.range() is not an SpmdVectorSpaceBase."); 00297 00298 // Thyra annoyingly uses a (possibly) different template 00299 // parameter for its Teuchos::Comm than everybody else. The 00300 // least hackish way to work around this is to convert the Comm 00301 // to one of two subclasses (MpiComm or SerialComm). If it's an 00302 // MpiComm, we can extract the RCP<const OpaqueWrapper<MPI_Comm> 00303 // > and make a new MpiComm<int> from it. If it's a SerialComm, 00304 // just create a new SerialComm<int>. If it's neither of those, 00305 // then I have no idea what to do. Note that MpiComm is only 00306 // defined if HAVE_MPI is defined. 00307 RCP<const Teuchos::Comm<Thyra::Ordinal> > thyraComm = range->getComm (); 00308 #ifdef HAVE_MPI 00309 RCP<const Teuchos::MpiComm<Thyra::Ordinal> > thyraMpiComm = 00310 rcp_dynamic_cast<const Teuchos::MpiComm<Thyra::Ordinal> > (thyraComm); 00311 if (thyraMpiComm.is_null ()) { 00312 RCP<const Teuchos::SerialComm<Thyra::Ordinal> > thyraSerialComm = 00313 rcp_dynamic_cast<const Teuchos::SerialComm<Thyra::Ordinal> > (thyraComm); 00314 TEUCHOS_TEST_FOR_EXCEPTION( 00315 thyraSerialComm.is_null (), std::runtime_error, 00316 "Thyra's communicator is neither an MpiComm nor a SerialComm. " 00317 "Sorry, I have no idea what to do with it in that case."); 00318 // It's a SerialComm. Make a SerialComm of our own. 00319 // SerialComm instances are all the same, so there's no need 00320 // to keep the original one. 00321 return rcp_implicit_cast<const Teuchos::Comm<int> > (rcp (new Teuchos::SerialComm<int>)); 00322 } 00323 else { // Yippie, we have an MpiComm. 00324 RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > rawMpiComm = thyraMpiComm->getRawMpiComm (); 00325 // NOTE (mfh 18 Jun 2013) Since the error handler is attached 00326 // to the MPI_Comm, not to the Teuchos widget, we don't have 00327 // to set the error handler again on the new MpiComm object. 00328 return rcp_implicit_cast<const Teuchos::Comm<int> > (rcp (new Teuchos::MpiComm<int> (rawMpiComm))); 00329 } 00330 #else // NOT HAVE_MPI 00331 // Either it's a SerialComm or I don't know what to do with it. 00332 RCP<const Teuchos::SerialComm<Thyra::Ordinal> > thyraSerialComm = 00333 rcp_dynamic_cast<const Teuchos::SerialComm<Thyra::Ordinal> > (thyraComm); 00334 TEUCHOS_TEST_FOR_EXCEPTION( 00335 thyraSerialComm.is_null (), std::runtime_error, 00336 "Thyra's communicator is not a SerialComm, and MPI is not enabled, so " 00337 "it can't be an MpiComm either. That means it must be some other " 00338 "subclass of Comm, about which I don't know. " 00339 "Sorry, I have no idea what to do with it in that case."); 00340 // It's a SerialComm. Make a SerialComm of our own. 00341 // SerialComm instances are all the same, so there's no need 00342 // to keep the original one. 00343 return rcp_implicit_cast<const Teuchos::Comm<int> > (rcp (new Teuchos::SerialComm<int>)); 00344 #endif // HAVE_MPI 00345 } 00346 00350 void 00351 prepareNodeTsqr (const MV& X) 00352 { 00353 (void) X; // silence compiler warning about unused argument 00354 00355 if (node_.is_null ()) { // Create Kokkos Node instance on demand 00356 node_ = Teuchos::rcp (new node_type); 00357 } 00358 node_tsqr_factory_type::prepareNodeTsqr (nodeTsqr_, node_); 00359 } 00360 00372 void 00373 prepareDistTsqr (const MV& X) 00374 { 00375 using Teuchos::RCP; 00376 using Teuchos::rcp_implicit_cast; 00377 typedef TSQR::TeuchosMessenger<scalar_type> mess_type; 00378 typedef TSQR::MessengerBase<scalar_type> base_mess_type; 00379 00380 RCP<const Teuchos::Comm<int> > comm = getComm (X); 00381 RCP<mess_type> mess (new mess_type (comm)); 00382 RCP<base_mess_type> messBase = rcp_implicit_cast<base_mess_type> (mess); 00383 distTsqr_->init (messBase); 00384 } 00385 00405 void 00406 prepareTsqr (const MV& X) 00407 { 00408 if (! ready_) { 00409 prepareDistTsqr (X); 00410 prepareNodeTsqr (X); 00411 ready_ = true; 00412 } 00413 } 00414 00427 KokkosClassic::MultiVector<scalar_type, node_type> 00428 getNonConstView (MV& X) 00429 { 00430 // TODO (mfh 18 Jun 2013) Check whether X is constant stride. 00431 // TODO (mfh 18 Jun 2013) Extract a view of X's data. 00432 00433 return KokkosClassic::MultiVector<scalar_type, node_type> (node_); 00434 00435 // TODO (mfh 18 Jun 2013) Here is the start of code to extract a 00436 // nonconstant view of X's data. 00437 00438 // KokkosClassic::MultiVector<scalar_type, node_type> kmv (node); 00439 // const size_t numRows = ???; 00440 // const size_t numCols = ???; 00441 // const size_t stride = ???; 00442 // kmv.initializeValues (numRows, numCols, values, stride); 00443 // return kmv; 00444 } 00445 }; 00446 00447 } // namespace Tpetra 00448 00449 #endif // __Thyra_TsqrAdaptor_hpp 00450
1.7.6.1