|
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 00049 #include <Teuchos_GlobalMPISession.hpp> 00050 #include <Teuchos_oblackholestream.hpp> 00051 #include <Teuchos_TimeMonitor.hpp> 00052 #include <Tpetra_CrsMatrix.hpp> 00053 #include <Tpetra_DefaultPlatform.hpp> 00054 #include <Tpetra_Version.hpp> 00055 #include <iostream> 00056 00057 00058 template<class TpetraMatrixType> 00059 class MatrixFactory { 00060 public: 00061 // Fetch typedefs from the Tpetra::CrsMatrix. 00062 typedef typename TpetraMatrixType::scalar_type scalar_type; 00063 typedef typename TpetraMatrixType::local_ordinal_type local_ordinal_type; 00064 typedef typename TpetraMatrixType::global_ordinal_type global_ordinal_type; 00065 typedef typename TpetraMatrixType::node_type node_type; 00066 00067 // The type of Map objects to use. 00068 typedef Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> map_type; 00069 00070 // Create and return a simple example CrsMatrix, with row 00071 // distribution over the given Map. 00072 Teuchos::RCP<const TpetraMatrixType> 00073 create (const Teuchos::RCP<const map_type>& map) const 00074 { 00075 using Teuchos::arcp; 00076 using Teuchos::ArrayRCP; 00077 using Teuchos::ArrayView; 00078 using Teuchos::RCP; 00079 using Teuchos::rcp; 00080 using Teuchos::Time; 00081 using Teuchos::TimeMonitor; 00082 using Teuchos::tuple; 00083 typedef Tpetra::global_size_t GST; 00084 00085 // Create a timer for sparse matrix creation. 00086 RCP<Time> timer = TimeMonitor::getNewCounter ("Sparse matrix creation"); 00087 00088 // Time the whole scope of this routine, not counting timer lookup. 00089 TimeMonitor monitor (*timer); 00090 00091 // Create a Tpetra::Matrix using the Map, with dynamic allocation. 00092 RCP<TpetraMatrixType> A = rcp (new TpetraMatrixType (map, 3)); 00093 00094 // Add rows one at a time. Off diagonal values will always be -1. 00095 const scalar_type two = static_cast<scalar_type>( 2.0); 00096 const scalar_type negOne = static_cast<scalar_type>(-1.0); 00097 00098 const GST numGlobalElements = map->getGlobalNumElements (); 00099 // const size_t numMyElements = map->getNodeNumElements (); 00100 00101 // The list of global elements owned by this MPI process. 00102 ArrayView<const global_ordinal_type> myGlobalElements = 00103 map->getNodeElementList (); 00104 00105 typedef typename ArrayView<const global_ordinal_type>::const_iterator iter_type; 00106 for (iter_type it = myGlobalElements.begin(); it != myGlobalElements.end(); ++it) { 00107 const local_ordinal_type i_local = *it; 00108 const global_ordinal_type i_global = map->getGlobalElement (i_local); 00109 00110 // Can't insert local indices without a column map, so we insert 00111 // global indices here. 00112 if (i_global == 0) { 00113 A->insertGlobalValues (i_global, 00114 tuple (i_global, i_global+1), 00115 tuple (two, negOne)); 00116 } else if (static_cast<GST> (i_global) == numGlobalElements - 1) { 00117 A->insertGlobalValues (i_global, 00118 tuple (i_global-1, i_global), 00119 tuple (negOne, two)); 00120 } else { 00121 A->insertGlobalValues (i_global, 00122 tuple (i_global-1, i_global, i_global+1), 00123 tuple (negOne, two, negOne)); 00124 } 00125 } 00126 00127 // Finish up the matrix. 00128 A->fillComplete (); 00129 return A; 00130 } 00131 }; 00132 00133 00134 template<class NodeType> 00135 void 00136 example (const Teuchos::RCP<const Teuchos::Comm<int> >& comm, 00137 const Teuchos::RCP<NodeType>& node, 00138 std::ostream& out, 00139 std::ostream& err) 00140 { 00141 using std::endl; 00142 using Teuchos::ParameterList; 00143 using Teuchos::RCP; 00144 using Teuchos::rcp; 00145 using Teuchos::Time; 00146 using Teuchos::TimeMonitor; 00147 typedef Tpetra::global_size_t GST; 00148 00149 // Print out the Tpetra software version information. 00150 out << Tpetra::version() << endl << endl; 00151 00152 // Set up Tpetra typedefs. 00153 typedef double scalar_type; 00154 typedef int local_ordinal_type; 00155 typedef long global_ordinal_type; 00156 typedef NodeType node_type; 00157 typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type, 00158 global_ordinal_type, node_type> matrix_type; 00159 00160 // The type of the Tpetra::Map that describes how the matrix is distributed. 00161 typedef Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> map_type; 00162 00163 // The global number of rows in the matrix A to create. We scale 00164 // this relative to the number of (MPI) processes, so that no matter 00165 // how many MPI processes you run, every process will have 10 rows. 00166 const GST numGlobalElements = 10 * comm->getSize (); 00167 00168 const global_ordinal_type indexBase = 0; 00169 00170 // Construct a Map that is global (not locally replicated), but puts 00171 // all the equations on MPI Proc 0. 00172 RCP<const map_type> procZeroMap; 00173 { 00174 const size_t numLocalElements = 00175 (comm->getRank() == 0) ? numGlobalElements : 0; 00176 procZeroMap = rcp (new map_type (numGlobalElements, numLocalElements, 00177 indexBase, comm, node)); 00178 } 00179 00180 // Construct a Map that puts approximately the same number of 00181 // equations on each processor. 00182 RCP<const map_type> globalMap = 00183 rcp (new map_type (numGlobalElements, indexBase, comm, 00184 Tpetra::GloballyDistributed, node)); 00185 00186 // Create a sparse matrix using procZeroMap. 00187 RCP<const matrix_type> A = MatrixFactory<matrix_type> ().create (procZeroMap); 00188 00189 // 00190 // We've created a sparse matrix that lives entirely on MPI Proc 0. 00191 // Now we want to distribute it over all the processes. 00192 // 00193 00194 // Make a timer for sparse matrix redistribution. 00195 RCP<Time> exportTimer = 00196 TimeMonitor::getNewCounter ("Sparse matrix redistribution"); 00197 00198 // Redistribute the matrix. Since both the source and target Maps 00199 // are one-to-one, we could use either an Import or an Export. If 00200 // only the source Map were one-to-one, we would have to use an 00201 // Import; if only the target Map were one-to-one, we would have to 00202 // use an Export. We do not allow redistribution using Import or 00203 // Export if neither source nor target Map is one-to-one. 00204 RCP<matrix_type> B; 00205 { 00206 TimeMonitor monitor (*exportTimer); // Time the redistribution 00207 00208 // Make an export object with procZeroMap as the source Map, and 00209 // globalMap as the target Map. The Export type has the same 00210 // template parameters as a Map. Note that Export does not depend 00211 // on the Scalar template parameter of the objects it 00212 // redistributes. You can reuse the same Export for different 00213 // Tpetra object types, or for Tpetra objects of the same type but 00214 // different Scalar template parameters (e.g., Scalar=float or 00215 // Scalar=double). 00216 typedef Tpetra::Export<local_ordinal_type, global_ordinal_type, 00217 node_type> export_type; 00218 export_type exporter (procZeroMap, globalMap); 00219 00220 // Make a new sparse matrix whose row map is the global Map. 00221 B = rcp (new matrix_type (globalMap, 0)); 00222 00223 // Redistribute the data, NOT in place, from matrix A (which lives 00224 // entirely on Proc 0) to matrix B (which is distributed evenly over 00225 // the processes). 00226 B->doExport (*A, exporter, Tpetra::INSERT); 00227 } 00228 00229 // We time redistribution of B separately from fillComplete(). 00230 B->fillComplete (); 00231 } 00232 00233 00234 int 00235 main (int argc, char *argv[]) 00236 { 00237 using std::endl; 00238 using Teuchos::RCP; 00239 using Teuchos::Time; 00240 using Teuchos::TimeMonitor; 00241 00242 Teuchos::oblackholestream blackHole; 00243 Teuchos::GlobalMPISession mpiSession (&argc, &argv, &blackHole); 00244 RCP<const Teuchos::Comm<int> > comm = 00245 Tpetra::DefaultPlatform::getDefaultPlatform().getComm(); 00246 00247 typedef Kokkos::DefaultNode::DefaultNodeType node_type; 00248 RCP<node_type> node = Kokkos::DefaultNode::getDefaultNode (); 00249 00250 const int myRank = comm->getRank(); 00251 //const int numProcs = comm->getSize(); 00252 std::ostream& out = (myRank == 0) ? std::cout : blackHole; 00253 std::ostream& err = (myRank == 0) ? std::cerr : blackHole; 00254 00255 // Make a timer for sparse matrix redistribution. 00256 // 00257 // If you are using Trilinos 10.6 instead of the development branch 00258 // (10.7), just delete this line of code, and make the other change 00259 // mentioned above. 00260 RCP<Time >exportTimer = 00261 TimeMonitor::getNewCounter ("Sparse matrix redistribution"); 00262 00263 // Run the whole example: create the sparse matrix, and compute the preconditioner. 00264 example (comm, node, out, err); 00265 00266 // Summarize global performance timing results, for all timers 00267 // created using TimeMonitor::getNewCounter(). 00268 TimeMonitor::summarize (out); 00269 00270 // This tells the Trilinos test framework that the test passed. 00271 if (myRank == 0) { 00272 std::cout << "End Result: TEST PASSED" << std::endl; 00273 } 00274 00275 return 0; 00276 }
1.7.6.1