Tpetra Matrix/Vector Services  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
Tpetra_MpiPlatform.cpp
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 #include <Tpetra_ConfigDefs.hpp>
00043 
00044 // mfh 29 Jun 2014: It makes life easier for Sierra developers if
00045 // Trilinos just builds all .cpp files unconditionally, rather than
00046 // making the decision whether to build them dependent on CMake
00047 // options.  Thus, we just exclude all the content of this file if MPI
00048 // is not enabled.
00049 #ifdef HAVE_TPETRA_MPI
00050 #  include <Tpetra_MpiPlatform.hpp>
00051 
00052 namespace Tpetra {
00053 
00054   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00055   MpiPlatform () :
00056     comm_ (Teuchos::createMpiComm<int> (Teuchos::opaqueWrapper<MPI_Comm> (MPI_COMM_WORLD))),
00057     node_ (Teuchos::null)
00058   {
00059     // mfh 29 Jun 2014: Don't initialize the Node yet.  This ensures
00060     // that (new) Kokkos won't get initialized with the wrong
00061     // command-line arguments, at least not until getNode() is called.
00062     // Initializing Kokkos with the wrong command-line arguments may
00063     // result in poor performance due to the wrong assignment of
00064     // software threads to hardware execution units.
00065     //
00066     // if (node_.is_null ()) {
00067     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00068     // }
00069   }
00070 
00071   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00072   MpiPlatform (int* argc, char*** argv) :
00073     comm_ (Teuchos::null),
00074     node_ (Teuchos::null)
00075   {
00076     initialize (argc, argv);
00077     comm_ = getDefaultComm ();
00078 
00079     // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00080     //
00081     // if (node_.is_null ()) {
00082     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00083     // }
00084   }
00085 
00086   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00087   MpiPlatform (const Teuchos::RCP<NodeType>& node) :
00088     comm_ (Teuchos::createMpiComm<int> (Teuchos::opaqueWrapper<MPI_Comm> (MPI_COMM_WORLD))),
00089     node_ (node)
00090   {
00091     // mfh 29 Jun 2014: Don't initialize the Node yet.  This ensures
00092     // that (new) Kokkos won't get initialized with the wrong
00093     // command-line arguments, at least not until getNode() is
00094     // called.  Initializing Kokkos with the wrong command-line
00095     // arguments may result in poor performance due to the wrong
00096     // assignment of software threads to hardware execution units.
00097     //
00098     // if (node_.is_null ()) {
00099     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00100     // }
00101   }
00102 
00103   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00104   MpiPlatform (int* argc, char*** argv, const Teuchos::RCP<NodeType>& node) :
00105     comm_ (Teuchos::null),
00106     node_ (node)
00107   {
00108     initialize (argc, argv);
00109     comm_ = getDefaultComm ();
00110 
00111     // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00112     //
00113     // if (node_.is_null ()) {
00114     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00115     // }
00116   }
00117 
00118   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00119   MpiPlatform (const Teuchos::RCP<NodeType>& node,
00120                const Teuchos::RCP<const Teuchos::OpaqueWrapper<MPI_Comm> >& rawMpiComm)
00121     : comm_ (Teuchos::null),
00122       node_ (node)
00123   {
00124     TEUCHOS_TEST_FOR_EXCEPTION(
00125       rawMpiComm.is_null (), std::invalid_argument, "Tpetra::MpiPlatform "
00126       "constructor: The input RCP<OpaqueWrapper<MPI_Comm> > is null.  That "
00127       "means something different than MPI_COMM_NULL.  If you want to give "
00128       "MPI_COMM_NULL to this constructor, please wrap MPI_COMM_NULL in a "
00129       "nonnull Teuchos::OpaqueWrapper by using the "
00130       "Teuchos::opaqueWrapper<MPI_Comm>() nonmember constructor.");
00131     comm_ = Teuchos::createMpiComm<int> (rawMpiComm);
00132 
00133     // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00134     //
00135     // if (node_.is_null ()) {
00136     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00137     // }
00138   }
00139 
00140   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00141   MpiPlatform (int* argc,
00142                char*** argv,
00143                const Teuchos::RCP<NodeType>& node,
00144                const Teuchos::RCP<const Teuchos::OpaqueWrapper<MPI_Comm> >& rawMpiComm)
00145     : comm_ (Teuchos::null),
00146       node_ (node)
00147   {
00148     TEUCHOS_TEST_FOR_EXCEPTION(
00149       rawMpiComm.is_null (), std::invalid_argument, "Tpetra::MpiPlatform "
00150       "constructor: The input RCP<OpaqueWrapper<MPI_Comm> > is null.  That "
00151       "means something different than MPI_COMM_NULL.  If you want to give "
00152       "MPI_COMM_NULL to this constructor, please wrap MPI_COMM_NULL in a "
00153       "nonnull Teuchos::OpaqueWrapper by using the "
00154       "Teuchos::opaqueWrapper<MPI_Comm>() nonmember constructor.");
00155     comm_ = Teuchos::createMpiComm<int> (rawMpiComm);
00156 
00157     // NOTE (mfh 29 Jun 2014): The OpaqueWrapper might wrap the
00158     // MPI_Comm in something that calls MPI_Comm_free.  Thus, we
00159     // can't just ignore it; we have to give it to the comm_ so that
00160     // its destructor (which might call MPI_Comm_free) will be
00161     // called at the right time.  This is why we don't set comm
00162     // using getDefaultComm().  This is also why we pass comm_
00163     // directly to initialize(): that way there aren't two
00164     // references to the raw MPI_Comm floating around, and comm_'s
00165     // destructor will get to do the right thing.
00166     initialize (argc, argv, comm_);
00167 
00168     // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00169     //
00170     // if (node_.is_null ()) {
00171     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00172     // }
00173   }
00174 
00175   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00176   MpiPlatform (const Teuchos::RCP<NodeType>& node, MPI_Comm rawMpiComm)
00177     : comm_ (Teuchos::createMpiComm<int> (Teuchos::opaqueWrapper<MPI_Comm> (rawMpiComm))),
00178       node_ (node)
00179   {
00180     // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00181     //
00182     // if (node_.is_null ()) {
00183     //   node_ = KokkosClassic::DefaultNode::getDefaultNode ();
00184     // }
00185   }
00186 
00187   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00188   MpiPlatform (int* argc,
00189                char*** argv,
00190                const Teuchos::RCP<NodeType>& node,
00191                MPI_Comm rawMpiComm)
00192     : comm_ (Teuchos::null),
00193       node_ (node)
00194   {
00195     initialize (argc, argv, rawMpiComm);
00196     comm_ = getDefaultComm ();
00197 
00198     // mfh 29 Jun 2014: Don't initialize the Node yet.  See above note.
00199     //
00200     // if (node_.is_null ()) {
00201     //   node_ = KokkosClassic::Details::getNode<Node> ();
00202     // }
00203   }
00204 
00205   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00206   ~MpiPlatform () {}
00207 
00208   Teuchos::RCP<const Teuchos::Comm<int> >
00209   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00210   getComm () const {
00211     TEUCHOS_TEST_FOR_EXCEPTION(
00212       comm_.is_null (), std::logic_error, "Tpetra::MpiPlatform::getComm: "
00213       "The default communicator is null.  This should never happen.  "
00214       "Please report this bug to the Tpetra developers.");
00215     return comm_;
00216   }
00217 
00218   Teuchos::RCP<MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::NodeType>
00219   MpiPlatform<KokkosClassic::DefaultNode::DefaultNodeType>::
00220   getNode () const
00221   {
00222     typedef MpiPlatform<NodeType> this_type;
00223     if (node_.is_null ()) {
00224       // NOTE (mfh 29 Jun 2014): Creating an instance of one of the
00225       // new Kokkos wrapper Nodes _must_ call Kokkos::initialize.
00226       // If Kokkos has not been initialized yet, this may result in
00227       // Kokkos being initialized correctly, since we have no way to
00228       // pass it the command-line arguments at this point.  This is
00229       // why we should prefer the *Platform constructors that take
00230       // argc and argv, since they can (and do) call
00231       // Kokkos::initialize (by calling Tpetra::initialize).
00232       //
00233       // mfh 29 Jun 2014: We're only keeping the *Platform classes
00234       // for backwards compatibility anyway, so I don't feel bad
00235       // about the const_cast here.
00236       const_cast<this_type*> (this)->node_ =
00237         KokkosClassic::DefaultNode::getDefaultNode ();
00238       TEUCHOS_TEST_FOR_EXCEPTION(
00239         node_.is_null (), std::logic_error, "Tpetra::MpiPlatform::getNode: "
00240         "KokkosClassic::DefaultNode::getDefaultNode() returned null.  "
00241         "This should never happen.  "
00242         "Please report this bug to the Tpetra developers.");
00243     }
00244     return node_;
00245   }
00246 
00247 } // namespace Tpetra
00248 
00249 #endif // HAVE_TPETRA_MPI
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines