TSFInverseLTIOp.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 TSFINVERSELTIOP_HPP
00030 #define TSFINVERSELTIOP_HPP
00031 
00032 #include "SundanceDefs.hpp"
00033 #include "TSFSimplifiedLinearOpBase.hpp"
00034 #include "TSFHomogeneouslyBlockedLinearOp.hpp"
00035 #include "TSFSimpleIdentityOpDecl.hpp"
00036 
00037 
00038 namespace TSFExtended
00039 {
00040 using namespace Teuchos;
00041 using namespace Thyra;
00042 
00043 /** 
00044  * InverseLTIOp encapsulates a block operator representation
00045  * of timestepping for a linear, time-invariant system of ODEs.
00046  * The ODEs are replaced by a discrete-time system
00047  * \f[
00048  * {\bf x}_{k+1} = {\bf A} \cdot {\bf x}_k.
00049  * \f]
00050  * This can be written as the block system
00051  * \f[
00052  * \left[
00053  * \begin{array}{cccc}
00054  * I  & 0  & 0  & \cdots \\
00055  * -A & I  & 0  & \\
00056  * 0  & -A & I  & \\
00057  * \vdots & & & \ddots 
00058  * \end{array}
00059  * \right]
00060  * \left[\begin{array}{c} x_0 \\ x_1 \\ x_2 \\ \vdots \end{array}\right]
00061  * =
00062  * \left[\begin{array}{c} x_0 \\ 0 \\ 0 \\ \vdots \end{array}\right]
00063  * \f].
00064  * The inner matrix \f$ A\f$ depends on the timestepping algorithm
00065  * used as well as the system of ODEs. 
00066  *
00067  * This class solves the system by backsubstitution.
00068  */
00069 template <class Scalar> 
00070 class InverseLTIOp
00071   : public virtual LinearOpBase<Scalar>,
00072     public virtual HomogeneouslyBlockedLinearOp<Scalar>,
00073     public virtual SimplifiedLinearOpBase<Scalar>
00074 {
00075 public:
00076 
00077   /** 
00078    * Construct a InverseLTIOp that takes <t>numTimesteps</t> steps
00079    * with the operator \f$ A\f$.
00080    */
00081   InverseLTIOp(int numTimesteps, const LinearOperator<Scalar>& A,
00082     const LinearOperator<Scalar>& At)
00083     : HomogeneouslyBlockedLinearOp<Scalar>(
00084       A.domain(), numTimesteps,
00085       A.range(), numTimesteps),
00086       A_(A), At_(At)
00087     {}
00088 
00089 
00090 
00091   /** 
00092    * Apply the operator
00093    */
00094   void applyOp(
00095     const Thyra::EOpTransp M_trans,
00096     const Vector<Scalar>& in,
00097     Vector<Scalar> out
00098     ) const 
00099     {
00100       int nbIn = in.space().numBlocks();
00101       int nbOut = out.space().numBlocks();
00102       TEST_FOR_EXCEPTION(nbIn != nbOut, std::runtime_error,
00103         "expected a square block structure, found nbIn=" << nbIn
00104         << ", nbOut=" << nbOut);
00105           
00106 
00107       LinearOperator<Scalar> I = identityOperator<Scalar>(in.space().getBlock(0));
00108 
00109       if (M_trans==Thyra::NOTRANS)
00110       {
00111         for (int i=0; i<this->numBlockRows(); i++)
00112         {
00113           if (i==0)
00114           {
00115             out.setBlock(i, I*in.getBlock(i));
00116           }
00117           else
00118           {
00119             Vector<Scalar> xi1 = out.getBlock(i-1);
00120             Vector<Scalar> bi = in.getBlock(i);
00121             out.setBlock(i, bi + A_*xi1);
00122           }
00123         }
00124       }
00125       else if (M_trans==Thyra::TRANS)
00126       {
00127         for (int i=this->numBlockCols()-1; i>=0; i--)
00128         {
00129           if (i==this->numBlockCols()-1)
00130           {
00131             out.setBlock(i, I*in.getBlock(i));
00132           }
00133           else
00134           {
00135             Vector<Scalar> bi = in.getBlock(i);
00136             Vector<Scalar> xi1 = out.getBlock(i+1);
00137             out.setBlock(i, bi + At_*xi1);
00138           }
00139         }
00140       }
00141       else
00142       {
00143         TEST_FOR_EXCEPT(true);
00144       }
00145 
00146     }
00147 
00148 private:
00149   LinearOperator<Scalar> A_;
00150   LinearOperator<Scalar> At_;
00151 
00152 };
00153 }
00154 
00155 
00156 #ifdef TRILINOS_6
00157 #undef DefaultColumnwiseMultiVector
00158 #endif
00159 
00160 #endif

Site Contact