Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_Factory_def.hpp
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack2: Tempated Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2009) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
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 
00043 #ifndef IFPACK2_FACTORY_DEF_HPP
00044 #define IFPACK2_FACTORY_DEF_HPP
00045 
00046 #include "Ifpack2_Details_OneLevelFactory.hpp"
00047 #include "Ifpack2_AdditiveSchwarz.hpp"
00048 #include "Ifpack2_Krylov.hpp"
00049 #if defined(HAVE_IFPACK2_EXPERIMENTAL) && defined(HAVE_IFPACK2_SUPPORTGRAPH)
00050 #  include "Ifpack2_SupportGraph.hpp"
00051 #endif // defined(HAVE_IFPACK2_EXPERIMENTAL) && defined(HAVE_IFPACK2_SUPPORTGRAPH)
00052 #include "Ifpack2_RILUK.hpp"
00053 
00054 namespace Ifpack2 {
00055 
00056 template<class MatrixType>
00057 Teuchos::RCP<Preconditioner<typename MatrixType::scalar_type,
00058                             typename MatrixType::local_ordinal_type,
00059                             typename MatrixType::global_ordinal_type,
00060                             typename MatrixType::node_type> >
00061 Factory::create (const std::string& precType,
00062                  const Teuchos::RCP<const MatrixType>& matrix,
00063                  const int overlap)
00064 {
00065   using Teuchos::RCP;
00066   using Teuchos::rcp;
00067   typedef typename MatrixType::scalar_type scalar_type;
00068   typedef typename MatrixType::local_ordinal_type local_ordinal_type;
00069   typedef typename MatrixType::global_ordinal_type global_ordinal_type;
00070   typedef typename MatrixType::node_type node_type;
00071   typedef Preconditioner<scalar_type, local_ordinal_type,
00072                          global_ordinal_type, node_type> prec_base_type;
00073 
00074   RCP<prec_base_type> prec;
00075 
00076   // precTypeUpper is the upper-case version of precType.
00077   std::string precTypeUpper (precType);
00078   if (precTypeUpper.size () > 0) {
00079     std::locale locale;
00080     for (size_t k = 0; k < precTypeUpper.size (); ++k) {
00081       precTypeUpper[k] = std::toupper<char> (precTypeUpper[k], locale);
00082     }
00083   }
00084 
00085   const bool one_mpi_rank = (matrix->getComm ()->getSize () == 1);
00086   // Forestall "unused variable" warnings.
00087   (void) one_mpi_rank;
00088 
00089   if (precTypeUpper == "SCHWARZ") {
00090     // Discussion related to Bug 5987: The line of code below will
00091     // give AdditiveSchwarz a default subdomain solver by default.
00092     // However, you can change it later via setParameters() or
00093     // setInnerPreconditioner().  In the former case, AdditiveSchwarz
00094     // will not create the subdomain solver until you call
00095     // initialize(), so there is no performance loss in waiting after
00096     // calling AdditiveSchwarz's constructor before specifying the
00097     // subdomain solver's type.
00098     //
00099     // FIXME (mfh 14 Jan 2014) Use of "CUSTOM" in AdditiveSchwarz may
00100     // destroy information needed for fixing Bug 5987.  In particular,
00101     // the input ParameterList needs to keep its subdomain solver
00102     // info.  setInnerPreconditioner must _not_ destroy that info _if_
00103     // the Factory creates the AdditiveSchwarz instance.
00104     prec = rcp (new AdditiveSchwarz<MatrixType> (matrix, overlap));
00105   }
00106   else if (precTypeUpper == "KRYLOV") {
00107     prec = rcp (new Krylov<MatrixType> (matrix));
00108   }
00109 #if defined(HAVE_IFPACK2_EXPERIMENTAL) && defined(HAVE_IFPACK2_SUPPORTGRAPH)
00110   else if (precTypeUpper == "SUPPORTGRAPH") {
00111     prec = rcp (new SupportGraph<MatrixType> (matrix));
00112   }
00113 #endif
00114   else {
00115     try {
00116       Details::OneLevelFactory<MatrixType> factory;
00117       prec = factory.create (precType, matrix);
00118     } catch (std::invalid_argument&) {
00119       TEUCHOS_TEST_FOR_EXCEPTION(
00120         true, std::invalid_argument, "Ifpack2::Factory::create: "
00121         "Invalid preconditioner type \"" << precType << "\".");
00122     }
00123   }
00124   return prec;
00125 }
00126 
00127 
00128 template<class MatrixType>
00129 Teuchos::RCP<Preconditioner<typename MatrixType::scalar_type,
00130                                      typename MatrixType::local_ordinal_type,
00131                                      typename MatrixType::global_ordinal_type,
00132                                      typename MatrixType::node_type> >
00133 Factory::create (const std::string& precType,
00134                  const Teuchos::RCP<const MatrixType>& matrix)
00135 {
00136   using Teuchos::RCP;
00137   using Teuchos::rcp;
00138   typedef typename MatrixType::scalar_type scalar_type;
00139   typedef typename MatrixType::local_ordinal_type local_ordinal_type;
00140   typedef typename MatrixType::global_ordinal_type global_ordinal_type;
00141   typedef typename MatrixType::node_type node_type;
00142   typedef Preconditioner<scalar_type,
00143                          local_ordinal_type,
00144                          global_ordinal_type,
00145                          node_type> prec_base_type;
00146 
00147   RCP<prec_base_type> prec;
00148 
00149   // precTypeUpper is the upper-case version of precType.
00150   std::string precTypeUpper (precType);
00151   if (precTypeUpper.size () > 0) {
00152     std::locale locale;
00153     for (size_t k = 0; k < precTypeUpper.size (); ++k) {
00154       precTypeUpper[k] = std::toupper<char> (precTypeUpper[k], locale);
00155     }
00156   }
00157 
00158   const bool one_mpi_rank = (matrix->getComm ()->getSize () == 1);
00159   // Forestall "unused variable" warnings.
00160   (void) one_mpi_rank;
00161 
00162   if (precTypeUpper == "SCHWARZ") {
00163     // Discussion related to Bug 5987: The line of code below will
00164     // give AdditiveSchwarz a default subdomain solver by default.
00165     // However, you can change it later via setParameters() or
00166     // setInnerPreconditioner().  In the former case, AdditiveSchwarz
00167     // will not create the subdomain solver until you call
00168     // initialize(), so there is no performance loss in waiting after
00169     // calling AdditiveSchwarz's constructor before specifying the
00170     // subdomain solver's type.
00171     //
00172     // FIXME (mfh 14 Jan 2014) Use of "CUSTOM" in AdditiveSchwarz may
00173     // destroy information needed for fixing Bug 5987.  In particular,
00174     // the input ParameterList needs to keep its subdomain solver
00175     // info.  setInnerPreconditioner must _not_ destroy that info _if_
00176     // the Factory creates the AdditiveSchwarz instance.
00177     //
00178     // "CUSTOM" isn't necessary.  If Inverse_ is not null, then
00179     // AdditiveSchwarz's initialize() should just use the inner
00180     // preconditioner as it is.  If Inverse_ is null, then we assume
00181     // you want the default inner preconditioner.  You shouldn't have
00182     // called setInnerPreconditioner() with a null argument if that's
00183     // not what you meant!
00184     prec = rcp (new AdditiveSchwarz<MatrixType> (matrix));
00185   }
00186   else if (precTypeUpper == "KRYLOV") {
00187     prec = rcp (new Krylov<MatrixType> (matrix));
00188   }
00189 #if defined(HAVE_IFPACK2_EXPERIMENTAL) && defined(HAVE_IFPACK2_SUPPORTGRAPH)
00190   else if (precTypeUpper == "SUPPORTGRAPH") {
00191     prec = rcp (new SupportGraph<MatrixType> (matrix));
00192   }
00193 #endif
00194   else {
00195     bool success = false;
00196     std::ostringstream err;
00197     try {
00198       Details::OneLevelFactory<MatrixType> factory;
00199       prec = factory.create (precType, matrix);
00200       success = true;
00201     } catch (std::invalid_argument& e) {
00202       err << "Ifpack2::Factory::create: Invalid preconditioner type \""
00203           << precType << "\".  More information for Ifpack2 developers: "
00204           << e.what ();
00205     }
00206     TEUCHOS_TEST_FOR_EXCEPTION(! success, std::invalid_argument, err.str ());
00207   }
00208 
00209   TEUCHOS_TEST_FOR_EXCEPTION(
00210     prec.is_null (), std::logic_error, "Ifpack2::Factory::create: "
00211     "Return value is null right before return.  This should never happen.  "
00212     "Please report this bug to the Ifpack2 developers.");
00213   return prec;
00214 }
00215 
00216 template<class InputMatrixType, class OutputMatrixType>
00217 Teuchos::RCP<Preconditioner<typename OutputMatrixType::scalar_type,
00218                             typename OutputMatrixType::local_ordinal_type,
00219                             typename OutputMatrixType::global_ordinal_type,
00220                             typename OutputMatrixType::node_type> >
00221 Factory::clone (const Teuchos::RCP<Preconditioner<typename InputMatrixType::scalar_type,
00222                                                   typename InputMatrixType::local_ordinal_type,
00223                                                   typename InputMatrixType::global_ordinal_type,
00224                                                   typename InputMatrixType::node_type> >& prec,
00225                 const Teuchos::RCP<const OutputMatrixType>& matrix,
00226                 const Teuchos::ParameterList& params)
00227 {
00228   using Teuchos::null;
00229   using Teuchos::RCP;
00230   using Teuchos::rcp;
00231   using Teuchos::rcp_dynamic_cast;
00232 
00233   // FIXME (mfh 09 Nov 2013) The code below assumes that the old and
00234   // new scalar, local ordinal, and global ordinal types are the same.
00235 
00236   typedef typename OutputMatrixType::scalar_type scalar_type;
00237   typedef typename OutputMatrixType::local_ordinal_type local_ordinal_type;
00238   typedef typename OutputMatrixType::global_ordinal_type global_ordinal_type;
00239   typedef typename OutputMatrixType::node_type new_node_type;
00240   typedef Preconditioner<scalar_type, local_ordinal_type,
00241                          global_ordinal_type, new_node_type> output_prec_type;
00242 
00243   // FIXME (mfh 09 Nov 2013) The code below only knows how to clone
00244   // two different kinds of preconditioners.  This is probably because
00245   // only two subclasses of Preconditioner implement a clone() method.
00246 
00247   RCP<output_prec_type> new_prec;
00248   RCP<Chebyshev<InputMatrixType> > chebyPrec;
00249   chebyPrec = rcp_dynamic_cast<Chebyshev<InputMatrixType> > (prec);
00250   if (chebyPrec != null) {
00251     new_prec = chebyPrec->clone (matrix, params);
00252     return new_prec;
00253   }
00254   RCP<RILUK<InputMatrixType> > luPrec;
00255   luPrec = rcp_dynamic_cast<RILUK<InputMatrixType> > (prec);
00256   if (luPrec != null) {
00257     new_prec = luPrec->clone (matrix);
00258     return new_prec;
00259   }
00260   TEUCHOS_TEST_FOR_EXCEPTION(
00261     true, std::logic_error, "Ifpack2::Factory::clone: Not implemented for the "
00262     "current preconditioner type.  The only supported types thus far are "
00263     "Chebyshev and RILUK.");
00264 }
00265 
00266 } // namespace Ifpack2
00267 
00268 #define IFPACK2_FACTORY_INSTANT(S,LO,GO,N)                              \
00269   template Teuchos::RCP<Ifpack2::Preconditioner<S, LO, GO, N> >         \
00270   Ifpack2::Factory::create<Tpetra::CrsMatrix< S, LO, GO, N> > (         \
00271     const std::string&,                                                 \
00272     const Teuchos::RCP<const Tpetra::CrsMatrix<S, LO, GO, N> >&);       \
00273   template Teuchos::RCP<Ifpack2::Preconditioner<S, LO, GO, N> >         \
00274   Ifpack2::Factory::create<Tpetra::CrsMatrix< S, LO, GO, N> > (         \
00275     const std::string&,                                                 \
00276     const Teuchos::RCP<const Tpetra::CrsMatrix<S, LO, GO, N> >&,        \
00277     const int);
00278 
00279 #endif // IFPACK2_FACTORY_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends