Tpetra Matrix/Vector Services  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
lesson02_init_map_vec.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 
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines