|
Tpetra Matrix/Vector Services
Version of the Day
|
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_Core.hpp> 00043 #ifdef HAVE_TPETRA_MPI 00044 # include <Teuchos_DefaultMpiComm.hpp>// this includes mpi.h too 00045 #else 00046 # include <Teuchos_DefaultSerialComm.hpp> 00047 #endif // HAVE_TPETRA_MPI 00048 #ifdef TPETRA_HAVE_KOKKOS_REFACTOR 00049 # include <Kokkos_Core.hpp> 00050 #endif // TPETRA_HAVE_KOKKOS_REFACTOR 00051 00052 namespace Tpetra { 00053 namespace { // (anonymous) 00054 // Whether one of the Tpetra::initialize() functions has been called before. 00055 bool tpetraIsInitialized_ = false; 00056 00057 // Tpetra's default communicator, wrapped in a Teuchos wrapper. 00058 // After Tpetra::finalize() is called, this GOES AWAY (is set to null). 00059 Teuchos::RCP<const Teuchos::Comm<int> > wrappedDefaultComm_; 00060 00061 #ifdef HAVE_TPETRA_MPI 00062 // Initialize MPI, if needed, and check for errors. 00063 void initMpi (int* argc, char*** argv) 00064 { 00065 int isInitialized = 0; 00066 int err = MPI_Initialized (&isInitialized); 00067 00068 TEUCHOS_TEST_FOR_EXCEPTION( 00069 err != MPI_SUCCESS, std::runtime_error, "MPI_Initialized failed with " 00070 "error code " << err << " != MPI_SUCCESS. This probably indicates " 00071 "that your MPI library is corrupted or that it is incorrectly linked " 00072 "to your program, since this function should otherwise always " 00073 "succeed."); 00074 00075 if (isInitialized == 0) { // MPI not yet initialized 00076 // Tpetra doesn't currently need to call MPI_Init_thread, since 00077 // with Tpetra, only one thread ever calls MPI functions. If we 00078 // ever want to explore MPI_THREAD_MULTIPLE, here would be the 00079 // place to call MPI_Init_thread. 00080 err = MPI_Init (argc, argv); 00081 } 00082 00083 TEUCHOS_TEST_FOR_EXCEPTION( 00084 err != MPI_SUCCESS, std::runtime_error, "MPI_Init failed with error " 00085 "code " << err << " != MPI_SUCCESS. If MPI was set up correctly, this " 00086 "should not happen, since we have already checked that MPI_Init (or " 00087 "MPI_Init_thread) has not yet been called. This may indicate that " 00088 "your MPI library is corrupted or that it is incorrectly linked to " 00089 "your program."); 00090 } 00091 #endif // HAVE_TPETRA_MPI 00092 00093 } // namespace (anonymous) 00094 00095 bool isInitialized () { 00096 return tpetraIsInitialized_; 00097 } 00098 00099 Teuchos::RCP<const Teuchos::Comm<int> > getDefaultComm () 00100 { 00101 TEUCHOS_TEST_FOR_EXCEPTION( 00102 tpetraIsInitialized_, std::runtime_error, "Tpetra::getDefaultComm: " 00103 "You must call Tpetra::initialize before you may get a default " 00104 "communicator."); 00105 TEUCHOS_TEST_FOR_EXCEPTION( 00106 wrappedDefaultComm_.is_null (), std::logic_error, 00107 "Tpetra::getDefaultComm: wrappedDefaultComm_ is null! " 00108 "This should never happen, because Tpetra claims that it has been " 00109 "initialized. Please report this bug to the Tpetra developers."); 00110 return wrappedDefaultComm_; 00111 } 00112 00113 00114 void initialize (int* argc, char*** argv) 00115 { 00116 #ifdef HAVE_TPETRA_MPI 00117 initMpi (argc, argv); 00118 #endif // HAVE_TPETRA_MPI 00119 00120 if (! tpetraIsInitialized_) { 00121 #ifdef TPETRA_HAVE_KOKKOS_REFACTOR 00122 // Unlike MPI_Init, Kokkos promises not to modify argc and argv. 00123 Kokkos::initialize (*argc, *argv); 00124 #endif // TPETRA_HAVE_KOKKOS_REFACTOR 00125 00126 #ifdef HAVE_TPETRA_MPI 00127 wrappedDefaultComm_ = 00128 Teuchos::rcp (new Teuchos::MpiComm<int> (MPI_COMM_WORLD)); 00129 #else 00130 wrappedDefaultComm_ = Teuchos::rcp (new Teuchos::SerialComm<int> ()); 00131 #endif // HAVE_TPETRA_MPI 00132 tpetraIsInitialized_ = true; 00133 } 00134 } 00135 00136 00137 #ifdef HAVE_TPETRA_MPI 00138 void initialize (int* argc, char*** argv, MPI_Comm comm) 00139 { 00140 #ifdef HAVE_TPETRA_MPI 00141 initMpi (argc, argv); 00142 #endif // HAVE_TPETRA_MPI 00143 00144 // Set the default communicator. What if users have already 00145 // called initialize() before, but with a different default 00146 // communicator? There are two possible things we could do here: 00147 // 00148 // 1. Test via MPI_Comm_compare whether comm differs from the 00149 // raw MPI communicator in wrappedDefaultComm_ (if indeed it 00150 // is an MpiComm). 00151 // 2. Accept that the user might want to change the default 00152 // communicator, and let them do it. 00153 // 00154 // I prefer #2. Perhaps it would be sensible to print a warning 00155 // here, but on which process? Would we use the old or the new 00156 // communicator to find that process' rank? We don't want to 00157 // use MPI_COMM_WORLD's Process 0, since neither communicator 00158 // might include that process. Furthermore, in some 00159 // environments, only Process 0 in MPI_COMM_WORLD is allowed to 00160 // do I/O. Thus, we just let the change go without a warning. 00161 wrappedDefaultComm_ = Teuchos::rcp (new Teuchos::MpiComm<int> (comm)); 00162 00163 if (! tpetraIsInitialized_) { 00164 #ifdef TPETRA_HAVE_KOKKOS_REFACTOR 00165 // Unlike MPI_Init, Kokkos promises not to modify argc and argv. 00166 Kokkos::initialize (*argc, *argv); 00167 #endif // TPETRA_HAVE_KOKKOS_REFACTOR 00168 tpetraIsInitialized_ = true; 00169 } 00170 } 00171 #endif // HAVE_TPETRA_MPI 00172 00173 00174 void 00175 initialize (int* argc, char*** argv, 00176 const Teuchos::RCP<const Teuchos::Comm<int> >& comm) 00177 { 00178 #ifdef HAVE_TPETRA_MPI 00179 initMpi (argc, argv); 00180 #endif // HAVE_TPETRA_MPI 00181 00182 // Set the default communicator. What if users have already 00183 // called initialize() before, but with a different default 00184 // communicator? There are two possible things we could do here: 00185 // 00186 // 1. Test via MPI_Comm_compare whether comm differs from the 00187 // raw MPI communicator in wrappedDefaultComm_ (if indeed it 00188 // is an MpiComm). 00189 // 2. Accept that the user might want to change the default 00190 // communicator, and let them do it. 00191 // 00192 // I prefer #2. Perhaps it would be sensible to print a warning 00193 // here, but on which process? Would we use the old or the new 00194 // communicator to find that process' rank? We don't want to 00195 // use MPI_COMM_WORLD's Process 0, since neither communicator 00196 // might include that process. Furthermore, in some 00197 // environments, only Process 0 in MPI_COMM_WORLD is allowed to 00198 // do I/O. Thus, we just let the change go without a warning. 00199 wrappedDefaultComm_ = comm; 00200 00201 if (! tpetraIsInitialized_) { 00202 #ifdef TPETRA_HAVE_KOKKOS_REFACTOR 00203 // Unlike MPI_Init, Kokkos promises not to modify argc and argv. 00204 Kokkos::initialize (*argc, *argv); 00205 #endif // TPETRA_HAVE_KOKKOS_REFACTOR 00206 tpetraIsInitialized_ = true; 00207 } 00208 } 00209 00210 00211 void finalize () 00212 { 00213 using std::cerr; 00214 using std::endl; 00215 00216 if (! tpetraIsInitialized_) { 00217 // If the user didn't call initialize(), then we shouldn't call 00218 // MPI_Finalize() or otherwise shut anything else off. For 00219 // example, the user might want to use Kokkos without Tpetra, so 00220 // they might have called Kokkos::initialize() without calling 00221 // Tpetra::initialize(). In that case, we shouldn't call 00222 // Kokkos::initialize() here. 00223 return; 00224 } 00225 00226 #ifdef TPETRA_HAVE_KOKKOS_REFACTOR 00227 Kokkos::finalize (); 00228 #endif // TPETRA_HAVE_KOKKOS_REFACTOR 00229 00230 // Make sure that no outstanding references to the communicator 00231 // remain. If users gave initialize() an MPI_Comm, _they_ are 00232 // responsible for freeing it before calling finalize(). 00233 wrappedDefaultComm_ = Teuchos::null; 00234 00235 #ifdef HAVE_TPETRA_MPI 00236 int isInitialized = 0; 00237 int err = MPI_Initialized (&isInitialized); 00238 00239 // finalize() is a kind of destructor, so it's a bad idea to throw 00240 // an exception. Instead, just print out an error message and 00241 // hope for the best. 00242 if (err != MPI_SUCCESS) { 00243 cerr << "MPI_Initialized failed with error code " << err << " != " 00244 "MPI_SUCCESS. This probably indicates that your MPI library is " 00245 "corrupted or that it is incorrectly linked to your program, since " 00246 "this function should otherwise always succeed." << endl; 00247 } 00248 else if (isInitialized != 0) { 00249 // This must be called by the same thread that called MPI_Init 00250 // (possibly, but not necessarily, in Tpetra::initialize()). 00251 err = MPI_Finalize (); 00252 00253 // finalize() is a kind of destructor, so it's a bad idea to 00254 // throw an exception. Instead, just print out an error message 00255 // and hope for the best. 00256 if (err != MPI_SUCCESS) { 00257 cerr << "MPI_Finalize failed with error code " << err << " != " 00258 "MPI_SUCCESS. I'm not sure how to recover from this safely, " 00259 "so I will keep going and hope for the best." << endl; 00260 } 00261 } 00262 #endif // HAVE_TPETRA_MPI 00263 00264 tpetraIsInitialized_ = false; // it's not anymore. 00265 } 00266 } // namespace Tpetra
1.7.6.1