Tpetra Matrix/Vector Services Version of the Day
Tpetra_SerialPlatform.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2008) Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
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 Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #ifndef TPETRA_SERIALPLATFORM_HPP
00043 #define TPETRA_SERIALPLATFORM_HPP
00044 
00045 #include <Tpetra_ConfigDefs.hpp>
00046 #include <Tpetra_Core.hpp>
00047 #include <Kokkos_DefaultNode.hpp>
00048 #include <Teuchos_DefaultSerialComm.hpp>
00049 #include <Teuchos_Describable.hpp>
00050 
00051 namespace Tpetra {
00052 
00081   template <class Node>
00082   class SerialPlatform : public Teuchos::Describable {
00083   public:
00085 
00086 
00088     typedef Node NodeType;
00089 
00091 
00092 
00093 
00099     explicit SerialPlatform (int* argc, char*** argv) :
00100       comm_ (Teuchos::null),
00101       node_ (Teuchos::null)
00102     {
00103       initialize (argc, argv);
00104       comm_ = getDefaultComm ();
00105 
00106       // mfh 29 Jun 2014: Don't initialize the Node yet.  This ensures
00107       // that (new) Kokkos won't get initialized with the wrong
00108       // command-line arguments, at least not until getNode() is
00109       // called.  Initializing Kokkos with the wrong command-line
00110       // arguments may result in poor performance due to the wrong
00111       // assignment of software threads to hardware execution units.
00112       //
00113       // if (node_.is_null ()) {
00114       //   node_ = KokkosClassic::Details::getNode<NodeType> ();
00115       // }
00116     }
00117 
00123     explicit SerialPlatform (const Teuchos::RCP<NodeType>& node) :
00124       comm_ (Teuchos::rcp (new Teuchos::SerialComm<int> ())),
00125       node_ (node)
00126     {
00127       // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00128     }
00129 
00138     explicit SerialPlatform (int* argc, char*** argv,
00139                              const Teuchos::RCP<NodeType>& node) :
00140       comm_ (Teuchos::null),
00141       node_ (node)
00142     {
00143       initialize (argc, argv);
00144       comm_ = getDefaultComm ();
00145       // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00146     }
00147 
00149     virtual ~SerialPlatform () {}
00150 
00152 
00153 
00154 
00156     Teuchos::RCP<const Teuchos::Comm<int> > getComm () const {
00157       return comm_;
00158     }
00159 
00161     Teuchos::RCP<Node> getNode () const {
00162       typedef SerialPlatform<NodeType> this_type;
00163       if (node_.is_null ()) {
00164         // NOTE (mfh 29 Jun 2014): Creating an instance of one of the
00165         // new Kokkos wrapper Nodes _must_ call Kokkos::initialize.
00166         // If Kokkos has not been initialized yet, this may result in
00167         // Kokkos being initialized correctly, since we have no way to
00168         // pass it the command-line arguments at this point.  This is
00169         // why we should prefer the *Platform constructors that take
00170         // argc and argv, since they can (and do) call
00171         // Kokkos::initialize (by calling Tpetra::initialize).
00172         //
00173         // mfh 29 Jun 2014: We're only keeping the *Platform classes
00174         // for backwards compatibility anyway, so I don't feel bad
00175         // about the const_cast here.
00176         const_cast<this_type*> (this)->node_ =
00177           KokkosClassic::Details::getNode<NodeType> ();
00178         TEUCHOS_TEST_FOR_EXCEPTION(
00179           node_.is_null (), std::logic_error, "Tpetra::MpiPlatform::getNode: "
00180           "KokkosClassic::Details::getNode<NodeType>() returned null.  "
00181           "This should never happen.  "
00182           "Please report this bug to the Tpetra developers.");
00183       }
00184       return node_;
00185     }
00186 
00188   protected:
00190     Teuchos::RCP<const Teuchos::Comm<int> > comm_;
00192     Teuchos::RCP<NodeType> node_;
00193 
00194   private:
00196     SerialPlatform (const SerialPlatform<NodeType>& platform);
00198     SerialPlatform& operator= (const SerialPlatform<NodeType>& platform);
00199   };
00200 
00217   template <>
00218   class SerialPlatform<KokkosClassic::DefaultNode::DefaultNodeType> :
00219     public Teuchos::Describable {
00220   public:
00222 
00223 
00225     typedef KokkosClassic::DefaultNode::DefaultNodeType NodeType;
00226 
00228 
00229 
00230 
00237     SerialPlatform () :
00238       comm_ (Teuchos::rcp (new Teuchos::SerialComm<int> ())),
00239       node_ (Teuchos::null)
00240     {
00241       // mfh 29 Jun 2014: Don't initialize the Node yet.  This ensures
00242       // that (new) Kokkos won't get initialized with the wrong
00243       // command-line arguments, at least not until getNode() is
00244       // called.  Initializing Kokkos with the wrong command-line
00245       // arguments may result in poor performance due to the wrong
00246       // assignment of software threads to hardware execution units.
00247       //
00248       // if (node_.is_null ()) {
00249       //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00250       // }
00251     }
00252 
00258     explicit SerialPlatform (int* argc, char*** argv) :
00259       comm_ (Teuchos::null),
00260       node_ (Teuchos::null)
00261     {
00262       initialize (argc, argv);
00263       comm_ = getDefaultComm ();
00264       // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00265     }
00266 
00279     explicit SerialPlatform (const Teuchos::RCP<NodeType>& node) :
00280       comm_ (Teuchos::rcp (new Teuchos::SerialComm<int> ())),
00281       node_ (node)
00282     {
00283       // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00284     }
00285 
00294     explicit SerialPlatform (int* argc, char*** argv,
00295                              const Teuchos::RCP<NodeType>& node) :
00296       comm_ (Teuchos::null),
00297       node_ (node)
00298     {
00299       initialize (argc, argv);
00300       comm_ = getDefaultComm ();
00301       // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00302     }
00303 
00305     virtual ~SerialPlatform () {}
00306 
00308 
00309 
00310 
00312     Teuchos::RCP<const Teuchos::Comm<int> > getComm() const {
00313       return comm_;
00314     }
00315 
00317     Teuchos::RCP<KokkosClassic::DefaultNode::DefaultNodeType> getNode () const {
00318       typedef SerialPlatform<NodeType> this_type;
00319       if (node_.is_null ()) {
00320         // NOTE (mfh 29 Jun 2014): Creating an instance of one of the
00321         // new Kokkos wrapper Nodes _must_ call Kokkos::initialize.
00322         // If Kokkos has not been initialized yet, this may result in
00323         // Kokkos being initialized correctly, since we have no way to
00324         // pass it the command-line arguments at this point.  This is
00325         // why we should prefer the *Platform constructors that take
00326         // argc and argv, since they can (and do) call
00327         // Kokkos::initialize (by calling Tpetra::initialize).
00328         //
00329         // mfh 29 Jun 2014: We're only keeping the *Platform classes
00330         // for backwards compatibility anyway, so I don't feel bad
00331         // about the const_cast here.
00332         const_cast<this_type*> (this)->node_ =
00333           KokkosClassic::Details::getNode<NodeType> ();
00334         TEUCHOS_TEST_FOR_EXCEPTION(
00335           node_.is_null (), std::logic_error, "Tpetra::MpiPlatform::getNode: "
00336           "KokkosClassic::Details::getNode<NodeType>() returned null.  "
00337           "This should never happen.  "
00338           "Please report this bug to the Tpetra developers.");
00339       }
00340       return node_;
00341     }
00342 
00344   private:
00346     SerialPlatform (const SerialPlatform<NodeType>& platform);
00347 
00349     SerialPlatform& operator= (const SerialPlatform<NodeType>& platform);
00350 
00351   protected:
00353     Teuchos::RCP<const Teuchos::Comm<int> > comm_;
00354 
00356     Teuchos::RCP<NodeType> node_;
00357   };
00358 
00359 } // namespace Tpetra
00360 
00361 #endif // TPETRA_SERIALPLATFORM_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines