Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Thyra_TsqrAdaptor.hpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines