|
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 00050 #include <Tpetra_DefaultPlatform.hpp> 00051 #include <Tpetra_Vector.hpp> 00052 #include <Tpetra_Version.hpp> 00053 #include <Teuchos_GlobalMPISession.hpp> 00054 #include <Teuchos_oblackholestream.hpp> 00055 00056 void 00057 exampleRoutine (const Teuchos::RCP<const Teuchos::Comm<int> >& comm, 00058 std::ostream& out) 00059 { 00060 using std::endl; 00061 using Teuchos::Array; 00062 using Teuchos::ArrayView; 00063 using Teuchos::RCP; 00064 using Teuchos::rcp; 00065 00066 // Print out the Tpetra software version information. 00067 out << Tpetra::version () << endl << endl; 00068 00069 // 00070 // The first thing you might notice that makes Tpetra objects 00071 // different than their Epetra counterparts, is that Tpetra objects 00072 // take several template parameters. These template parameters give 00073 // Tpetra its features of being able to solve very large problems 00074 // (of more than 2 billion unknowns) and to exploit intranode 00075 // parallelism. Most Tpetra objects come with default values of 00076 // those template parameters. In many cases, you might not have to 00077 // specify _any_ of those values explicitly! You can also control 00078 // some of their default values, like that of the Node type, when 00079 // configuring Trilinos. 00080 // 00081 // It's common to begin a Tpetra application with some typedefs to 00082 // make the code more concise and readable. They also make the code 00083 // more maintainable, since you can change the typedefs without 00084 // changing the rest of the program. You may also want to 00085 // abbreviate the template parameters. Standard abbreviations are 00086 // "LO" for local_ordinal_type and "GO" for global_ordinal_type. 00087 // 00088 00089 // The "Scalar" type is the type of the values stored in the Tpetra 00090 // objects. Valid Scalar types include real or complex 00091 // (std::complex<T>) floating-point types, or more exotic objects 00092 // with similar behavior. We use the default type here, which we 00093 // get from Vector. "Vector<>" means that we let all template 00094 // parameters' values revert to their defaults. 00095 typedef Tpetra::Vector<>::scalar_type scalar_type; 00096 00097 // The "LocalOrdinal" (LO) type is the type of "local" indices. 00098 // Both Epetra and Tpetra index local entries differently than 00099 // global entries. Tpetra exploits this so that you can use a 00100 // shorter integer type for local indices. This saves bandwidth 00101 // when computing sparse matrix-vector products. We use the default 00102 // LO type here, which we get from Tpetra::Vector. We could also 00103 // get it from Tpetra::Map. 00104 typedef Tpetra::Vector<>::local_ordinal_type local_ordinal_type; 00105 00106 // The "GlobalOrdinal" (GO) type is the type of "global" indices. 00107 // We use the default GO type here, which we get from 00108 // Tpetra::Vector. We could also get it from Tpetra::Map. 00109 typedef Tpetra::Vector<>::global_ordinal_type global_ordinal_type; 00110 00111 // The Kokkos "Node" type describes the type of shared-memory 00112 // parallelism that Tpetra will use _within_ an MPI process. The 00113 // available Node types depend on Trilinos' build options and the 00114 // availability of certain third-party libraries. In almost all 00115 // cases, the default setting will do. You may set the default Node 00116 // type when configuring Trilinos. In this case, we access the 00117 // default Node type using the typedef in Tpetra::Vector. Almost 00118 // all Tpetra classes have default template parameter values. 00119 typedef Tpetra::Vector<>::node_type node_type; 00120 00121 // Maps know how to convert between local and global indices, so of 00122 // course they are templated on the local and global Ordinal types. 00123 // They are also templated on the Kokkos Node type, because Tpetra 00124 // objects that use Tpetra::Map are. It's important not to mix up 00125 // Maps for different Kokkos Node types. In this case, we use all 00126 // default template parameters, which are the same as the 00127 // corresponding template parameters of Vector. 00128 typedef Tpetra::Map<> map_type; 00129 00131 // Create some Tpetra Map objects 00133 00134 // 00135 // Like Epetra, Tpetra has local and global Maps. Local maps 00136 // describe objects that are replicated over all participating MPI 00137 // processes. Global maps describe distributed objects. You can do 00138 // imports and exports between local and global maps; this is how 00139 // you would turn locally replicated objects into distributed 00140 // objects and vice versa. 00141 // 00142 00143 // The total (global, i.e., over all MPI processes) number of 00144 // entries in the Map. Tpetra's global_size_t type is an unsigned 00145 // type and is at least 64 bits long on 64-bit machines. 00146 // 00147 // For this example, we scale the global number of entries in the 00148 // Map with the number of MPI processes. That way, you can run this 00149 // example with any number of MPI processes and every process will 00150 // still have a positive number of entries. 00151 const Tpetra::global_size_t numGlobalEntries = comm->getSize() * 5; 00152 00153 // Tpetra can index the entries of a Map starting with 0 (C style), 00154 // 1 (Fortran style), or any base you want. 1-based indexing is 00155 // handy when interfacing with Fortran. We choose 0-based indexing 00156 // here. 00157 const global_ordinal_type indexBase = 0; 00158 00159 // Construct a Map that puts the same number of equations on each 00160 // processor. It's typical to create a const Map. Maps should be 00161 // considered immutable objects. If you want a new data 00162 // distribution, create a new Map. 00163 RCP<const map_type> contigMap = 00164 rcp (new map_type (numGlobalEntries, indexBase, comm, 00165 Tpetra::GloballyDistributed)); 00166 00167 // contigMap is contiguous by construction. 00168 TEUCHOS_TEST_FOR_EXCEPTION(! contigMap->isContiguous(), std::logic_error, 00169 "The supposedly contiguous Map isn't contiguous."); 00170 00171 // Let's create a second Map. It will have the same number of 00172 // global entries per process, but will distribute them 00173 // differently, in round-robin (1-D cyclic) fashion instead of 00174 // contiguously. 00175 RCP<const map_type> cyclicMap; 00176 { 00177 // We'll use the version of the Map constructor that takes, on 00178 // each MPI process, a list of the global entries in the Map 00179 // belonging to that process. You can use this constructor to 00180 // construct an overlapping (also called "not 1-to-1") Map, in 00181 // which one or more entries are owned by multiple processes. We 00182 // don't do that here; we make a nonoverlapping (also called 00183 // "1-to-1") Map. 00184 Array<global_ordinal_type>::size_type numEltsPerProc = 5; 00185 Array<global_ordinal_type> elementList (numEltsPerProc); 00186 00187 const int numProcs = comm->getSize(); 00188 const int myRank = comm->getRank(); 00189 for (Array<global_ordinal_type>::size_type k = 0; k < numEltsPerProc; ++k) 00190 elementList[k] = myRank + k*numProcs; 00191 00192 cyclicMap = rcp (new map_type (numGlobalEntries, elementList, indexBase, comm)); 00193 } 00194 00195 // If there's more than one MPI process in the communicator, 00196 // then cyclicMap is definitely NOT contiguous. 00197 TEUCHOS_TEST_FOR_EXCEPTION( 00198 comm->getSize() > 1 && cyclicMap->isContiguous(), 00199 std::logic_error, 00200 "The cyclic Map claims to be contiguous."); 00201 00202 // contigMap and cyclicMap should always be compatible. However, if 00203 // the communicator contains more than 1 process, then contigMap and 00204 // cyclicMap are NOT the same. 00205 TEUCHOS_TEST_FOR_EXCEPTION(! contigMap->isCompatible (*cyclicMap), 00206 std::logic_error, 00207 "contigMap should be compatible with cyclicMap, but it's not."); 00208 TEUCHOS_TEST_FOR_EXCEPTION(comm->getSize() > 1 && contigMap->isSameAs (*cyclicMap), 00209 std::logic_error, 00210 "contigMap should be compatible with cyclicMap, but it's not."); 00211 00213 // We have maps now, so we can create vectors. 00215 00216 // Since Tpetra::Vector takes four template parameters, its type is 00217 // long. Here, we use all default values for the template 00218 // parameters, which helps with the length. However, I still prefer 00219 // to use a typedef for encapsulation, so that we only have to 00220 // change one line of code if we decide to change the template 00221 // parameters of Vector. 00222 typedef Tpetra::Vector<> vector_type; 00223 00224 // Create a Vector with the contiguous Map. This version of the 00225 // constructor will fill in the vector with zeros. 00226 RCP<vector_type> x = rcp (new vector_type (contigMap)); 00227 00228 // The copy constructor performs a deep copy. 00229 // x and y have the same Map. 00230 RCP<vector_type> y = rcp (new vector_type (*x)); 00231 00232 // Create a Vector with the 1-D cyclic Map. Calling the constructor 00233 // with false for the second argument leaves the data uninitialized, 00234 // so that you can fill it later without paying the cost of 00235 // initially filling it with zeros. 00236 RCP<vector_type> z = rcp (new vector_type (contigMap, false)); 00237 00238 // Set the entries of z to (pseudo)random numbers. Please don't 00239 // consider this a good parallel pseudorandom number generator. 00240 z->randomize (); 00241 00242 // Set the entries of x to all ones. 00243 // 00244 // The code below works because scalar_type=double, and C++ 00245 // defines the implicit conversion from the integer 1 to double. 00246 // In general, you may use the commented-out line of code, if 00247 // the conversion from int to scalar_type is not defined for your 00248 // scalar type. 00249 x->putScalar (1); 00250 //x->putScalar (Teuchos::ScalarTraits<scalar_type>::one()); 00251 00252 // See comment above about type conversions to scalar_type. 00253 const scalar_type alpha = 3.14159; 00254 const scalar_type beta = 2.71828; 00255 const scalar_type gamma = -10; 00256 00257 // x = beta*x + alpha*z 00258 // 00259 // This is a legal operation! Even though the Maps of x and z are 00260 // not the same, their Maps are compatible. Whether it makes sense 00261 // or not depends on your application. 00262 x->update (alpha, *z, beta); 00263 00264 // See comment above about type conversions to scalar_type. 00265 y->putScalar (42); 00266 // y = gamma*y + alpha*x + beta*z 00267 y->update (alpha, *x, beta, *z, gamma); 00268 00269 // Compute the 2-norm of y. 00270 // 00271 // The norm may have a different type than scalar_type. 00272 // For example, if scalar_type is complex, then the norm is real. 00273 // The ScalarTraits "traits class" gives us the type of the norm. 00274 typedef Teuchos::ScalarTraits<scalar_type>::magnitudeType magnitude_type; 00275 const magnitude_type theNorm = y->norm2 (); 00276 00277 // Print the norm of y on Proc 0. 00278 out << "Norm of y: " << theNorm << endl; 00279 } 00280 00281 // 00282 // The same main() driver routine as in the first Tpetra lesson. 00283 // 00284 int 00285 main (int argc, char *argv[]) 00286 { 00287 using std::endl; 00288 using Teuchos::RCP; 00289 00290 Teuchos::oblackholestream blackHole; 00291 Teuchos::GlobalMPISession mpiSession (&argc, &argv, &blackHole); 00292 RCP<const Teuchos::Comm<int> > comm = 00293 Tpetra::DefaultPlatform::getDefaultPlatform ().getComm (); 00294 00295 const int myRank = comm->getRank (); 00296 std::ostream& out = (myRank == 0) ? std::cout : blackHole; 00297 00298 // We have a communicator and an output stream. 00299 // Let's do something with them! 00300 exampleRoutine (comm, out); 00301 00302 // This tells the Trilinos test framework that the test passed. 00303 if (myRank == 0) { 00304 std::cout << "End Result: TEST PASSED" << std::endl; 00305 } 00306 00307 return 0; 00308 }
1.7.6.1