Tpetra Matrix/Vector Services Version of the Day
MultiPrecDriver.hpp
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 // 
00005 //          Tpetra: Templated Linear Algebra Services Package
00006 //                 Copyright (2008) Sandia Corporation
00007 // 
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 // 
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00039 // 
00040 // ************************************************************************
00041 // @HEADER
00042 */
00043 
00044 #ifndef MULTIPREC_DRIVER_HPP
00045 #define MULTIPREC_DRIVER_HPP
00046 
00047 #include <Teuchos_TypeNameTraits.hpp>
00048 #include <Teuchos_TimeMonitor.hpp>
00049 #include <Teuchos_ParameterList.hpp>
00050 #include <Teuchos_FancyOStream.hpp>
00051 
00052 #include <Tpetra_Version.hpp>
00053 #include <Tpetra_MatrixIO.hpp>
00054 #include <Tpetra_RTI.hpp>
00055 #include <Tpetra_CrsMatrix.hpp>
00056 #include <Tpetra_Vector.hpp>
00057 
00058 #include "MultiPrecCG.hpp"
00059 
00060 template <class MPStack>
00061 class MultiPrecDriver {
00062   public:
00063   // input
00064   Teuchos::RCP<Teuchos::FancyOStream>     out; 
00065   Teuchos::RCP<Teuchos::ParameterList> params;
00066   std::string                      matrixFile;
00067   bool                             unfusedTest;
00068   // output
00069   bool                             testPassed;
00070 
00071   template <class Node> 
00072   void run(Teuchos::ParameterList &myMachPL, const Teuchos::RCP<const Teuchos::Comm<int> > &comm, const Teuchos::RCP<Node> &node) 
00073   {
00074     using std::pair;
00075     using std::make_pair;
00076     using std::plus;
00077     using std::endl;
00078     using Teuchos::RCP;
00079     using Teuchos::ParameterList;
00080     using TpetraExamples::make_pair_op;
00081     using Tpetra::RTI::reductionGlob;
00082     using Tpetra::RTI::ZeroOp;
00083     using Tpetra::RTI::binary_pre_transform_reduce;
00084     using Tpetra::RTI::binary_transform;
00085 
00086     // Static types
00087     typedef typename MPStack::type   S;
00088     typedef int                     LO;
00089     typedef int                     GO;
00090     typedef Tpetra::CrsMatrix<S,LO,GO,Node> CrsMatrix;
00091     typedef Tpetra::Vector<S,LO,GO,Node>       Vector;
00092 
00093     *out << "Running test with Node==" << Teuchos::typeName(*node) << " on rank " << comm->getRank() << "/" << comm->getSize() << std::endl;
00094 
00095     // read the matrix
00096     RCP<CrsMatrix> A;
00097     Tpetra::Utils::readHBMatrix(matrixFile,comm,node,A);
00098 
00099     // init the solver stack
00100     TpetraExamples::RFPCGInit<S,LO,GO,Node> init(A);
00101     RCP<ParameterList> db = Tpetra::Ext::initStackDB<MPStack>(*params,init);
00102 
00103     testPassed = true;
00104 
00105     // choose a solution, compute a right-hand-side
00106     auto x = Tpetra::createVector<S>(A->getRowMap()),
00107          b = Tpetra::createVector<S>(A->getRowMap());
00108     x->randomize();
00109     A->apply(*x,*b);
00110     {
00111       // init the rhs
00112       auto bx = db->get<RCP<Vector>>("bx");
00113       binary_transform( *bx, *b, [](S, S bi) {return bi;}); // bx = b
00114     }
00115 
00116     // call the solve
00117     TpetraExamples::recursiveFPCG<MPStack,LO,GO,Node>(out,*db);
00118 
00119     // check that residual is as requested
00120     {
00121       auto xhat = db->get<RCP<Vector>>("bx"),
00122            bhat = Tpetra::createVector<S>(A->getRowMap());
00123       A->apply(*xhat,*bhat);
00124       // compute bhat-b, while simultaneously computing |bhat-b|^2 and |b|^2
00125       auto nrms = binary_pre_transform_reduce(*bhat, *b, 
00126                                               reductionGlob<ZeroOp<pair<S,S>>>( 
00127                                                 [](S bhati, S bi){ return bi-bhati;}, // bhati = bi-bhat
00128                                                 [](S bhati, S bi){ return make_pair(bhati*bhati, bi*bi); },
00129                                                 make_pair_op<S,S>(plus<S>())) );
00130       const S enrm = Teuchos::ScalarTraits<S>::squareroot(nrms.first),
00131               bnrm = Teuchos::ScalarTraits<S>::squareroot(nrms.second);
00132       // check that residual is as requested
00133       *out << "|b - A*x|/|b|: " << enrm / bnrm << endl;
00134       const double tolerance = db->get<double>("tolerance");
00135       if (MPStack::bottom) {
00136         // give a little slack
00137         if (enrm / bnrm > 5*tolerance) testPassed = false;
00138       }
00139       else {
00140         if (enrm / bnrm > tolerance) testPassed = false;
00141       }
00142     }
00143 
00144     // 
00145     // solve again, with the unfused version, just for timings purposes
00146     if (unfusedTest) 
00147     {
00148       // init the rhs
00149       auto bx = db->get<RCP<Vector>>("bx");
00150       binary_transform( *bx, *b, [](S, S bi) {return bi;}); // bx = b
00151       // call the solve
00152       TpetraExamples::recursiveFPCGUnfused<MPStack,LO,GO,Node>(out,*db);
00153       //
00154       // test the result
00155       auto xhat = db->get<RCP<Vector>>("bx"),
00156            bhat = Tpetra::createVector<S>(A->getRowMap());
00157       A->apply(*xhat,*bhat);
00158       // compute bhat-b, while simultaneously computing |bhat-b|^2 and |b|^2
00159       auto nrms = binary_pre_transform_reduce(*bhat, *b, 
00160                                               reductionGlob<ZeroOp<pair<S,S>>>( 
00161                                                 [](S bhati, S bi){ return bi-bhati;}, // bhati = bi-bhat
00162                                                 [](S bhati, S bi){ return make_pair(bhati*bhati, bi*bi); },
00163                                                 make_pair_op<S,S>(plus<S>())) );
00164       const S enrm = Teuchos::ScalarTraits<S>::squareroot(nrms.first),
00165               bnrm = Teuchos::ScalarTraits<S>::squareroot(nrms.second);
00166       // check that residual is as requested
00167       *out << "|b - A*x|/|b|: " << enrm / bnrm << endl;
00168       const double tolerance = db->get<double>("tolerance");
00169       if (MPStack::bottom) {
00170         // give a little slack
00171         if (enrm / bnrm > 5*tolerance) testPassed = false;
00172       }
00173       else {
00174         if (enrm / bnrm > tolerance) testPassed = false;
00175       }
00176     }    
00177          
00178          
00179     // print timings
00180     Teuchos::TimeMonitor::summarize( *out );
00181   }
00182 };
00183 
00184 #endif // MULTIPREC_DRIVER_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines