TSFExplicitlyTransposedLTIProblemFactory.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 /* ***********************************************************************
00003 // 
00004 //           TSFExtended: Trilinos Solver Framework Extended
00005 //                 Copyright (2004) 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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // **********************************************************************/
00027  /* @HEADER@ */
00028 
00029 #ifndef TSF_EXPLICITLYTRANSPOSED_LTI_PROBLEMFACTORY_HPP
00030 #define TSF_EXPLICITLYTRANSPOSED_LTI_PROBLEMFACTORY_HPP
00031 
00032 
00033 #include "SundanceDefs.hpp"
00034 #include "TSFDefaultLTIProblemFactory.hpp"
00035 #include "TSFEpetraMatrix.hpp"
00036 #include "EpetraExt_Transpose_RowMatrix.h"
00037 
00038 
00039 namespace TSFExtended
00040 {
00041 using namespace Teuchos;
00042 using namespace Thyra;
00043 
00044 /** 
00045  * This class produces LTI problems where any transpose solves are
00046  * done using explicit transforms. For example, with backwards Euler
00047  * time stepping, the advance matrix \f$ A\f$ will be 
00048  * \f$ A = M B^{-1}, \f$ 
00049  * where \f$ M \f$ is the mass matrix and \f$ B = M - \Delta t K \f$. However,
00050  * with the AztecOO solver we can't do a transpose solve on B, so we will want
00051  * to form \f$ B^T\f$ explicitly, after which we can form \f$ A^T \f$ 
00052  * implicitly as \f$ A^T = (B^T)^{-1} M^T.\f$ In this formulation
00053  * we are only doing a solve on the {\it explicit} transpose of \f$ B. \f$
00054  */
00055 template <class Scalar> 
00056 class ExplicitlyTransposedLTIProblemFactory
00057   : public DefaultLTIProblemFactory<Scalar>
00058 {
00059 public:
00060   /** Constructor */
00061   ExplicitlyTransposedLTIProblemFactory(int nSteps)
00062     : DefaultLTIProblemFactory<Scalar>(nSteps),
00063       inputAt_()
00064     {}
00065 
00066 
00067 
00068   /** 
00069    * After construction, the user should set the operators by calling
00070    * init().
00071    *
00072    * \param A The "small" A operator. Small A does the advance through 
00073    * a single timestep.
00074    * \param C The "small" C operator. Small C does state observations
00075    * at a single timestep.
00076    * \param At The explicit transpose of small A. 
00077    */
00078   void init(
00079     const LinearOperator<Scalar>& A,
00080     const LinearOperator<Scalar>& At,
00081     const LinearOperator<Scalar>& C
00082     ) 
00083     {
00084       /* Call the init method on the default type. This will initialize
00085        * the "small" A and C operators. */
00086       DefaultLTIProblemFactory<Scalar>::init(A, C);
00087 
00088       /* Set the "small" A^T operator to the value given by the user */
00089       inputAt_ = At;
00090     }
00091 
00092 protected:    
00093 
00094   /** This is a helper function that forms an explicit transpose of
00095    * an operator. For now, this only works if the operator is an 
00096    * Epetra_CrsMatrix. We'll want to generalize this later to other operator
00097    * types.
00098    *
00099    * One clumsy feature of this function is that because of the way the 
00100    * EpetraExt explicit transposer has been written, the storage for
00101    * the transposed operator is managed by the transposer object. 
00102    * Therefore, we need to keep a copy of the transposer object around 
00103    * for as long as the transposed matrix exists. We keep a copy
00104    * of it here, as the transposer_  data member of the factory object. 
00105    * This means that the factory object had better not go out of scope while
00106    * the matrices it produces still exist. This is dangerous. We should
00107    * talk with Rob H and Mike H about redesigning the EpetraExt transformation
00108    * objects so that the objects they produce have integrity independent
00109    * of the transformation objects.
00110    */
00111   LinearOperator<Scalar> formExplicitTranspose(const LinearOperator<Scalar>& X) const 
00112     {
00113       /* create a transposer object, and store it in the transposer_ 
00114        * data member. See the comment above about why ythis is bad but
00115        * necessary. */
00116       transposer_ = rcp(new EpetraExt::RowMatrix_Transpose(true));
00117 
00118       /* The transposer will act on an epetra crs matrix. Extract a 
00119        * Crs matrix from the input operator X. This will throw an exception
00120        * if the object handled by X is not an EpetraMatrix. */
00121       Epetra_CrsMatrix& epX = EpetraMatrix::getConcrete(X);
00122 
00123       /* Do the transpose operation, which returns a Crs matrix but in the
00124        * form of its base class, an Epetra_RowMatrix.  */
00125       Epetra_RowMatrix& eprXt = (*transposer_)(epX);
00126 
00127       /* The TSF EpetraMatrix works with Epetra_CrsMatrix, so we need
00128        * to cast the RowMatrix to a CrsMatrix. This should always work, 
00129        * because the transposer is implemented in terms of CrsMatrix. If it
00130        * doesn't work, there's been an error somehere in Trilinos. */
00131       Epetra_CrsMatrix* epXt = dynamic_cast<Epetra_CrsMatrix*>(&eprXt);
00132       TEST_FOR_EXCEPTION(epXt == 0, std::runtime_error, "expected return type "
00133         "of EpetraExt tranposer to be a CrsMatrix");
00134 
00135       
00136       /* We need Epetra spaces for the domain and range spaces of the new
00137        * operator. We simply get these from the original, untransposed 
00138        * operator and then swap the order of domain and range. The operator
00139        * interface returns generic Thyra VectorSpace objects, which we
00140        * dynamic cast into Epetra VectorSpace objects. This cast should
00141        * always work. 
00142        */ 
00143       RCP<const EpetraVectorSpace> epXRange = rcp_dynamic_cast<const EpetraVectorSpace>(X.range().ptr());
00144       RCP<const EpetraVectorSpace> epXDomain = rcp_dynamic_cast<const EpetraVectorSpace>(X.domain().ptr());
00145 
00146 
00147       /* We can now create a TSF linear operator for the transpose. We need 
00148        * to pass an ownership flag of "false" for the RCP of the 
00149        * Epetra_CrsMatrix because the transposed matrix is
00150        * owned by the transposer. We also swap the original operator's 
00151        * domain and range spaces in creating the transpose. */
00152       RCP<LinearOpBase<Scalar> > XtPtr = rcp(new EpetraMatrix(rcp(epXt, false), 
00153           epXRange, epXDomain));
00154       LinearOperator<Scalar> Xt = XtPtr;
00155 
00156       /** all done! */
00157       return Xt;
00158     }
00159 
00160   /** Return the transpose of A */
00161   virtual LinearOperator<Scalar> createAt() const 
00162     {
00163       TEST_FOR_EXCEPT(inputAt_.ptr().get() == 0);
00164       return inputAt_;
00165     }
00166 
00167 private:
00168   LinearOperator<Scalar> inputAt_;
00169   /** Hack hack hack.... we need to keep the Epetra_Transposer object around
00170    * because it manages the memory of the transposed matrix. */
00171   mutable RCP<EpetraExt::RowMatrix_Transpose> transposer_;
00172 };
00173 }
00174 
00175 
00176 #endif

Site Contact