TSFLTIProblemFactoryBase.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 TSFLTIPROBLEMFACTORYBASE_HPP
00030 #define TSFLTIPROBLEMFACTORYBASE_HPP
00031 
00032 #include "SundanceDefs.hpp"
00033 #include "TSFInverseLTIOp.hpp"
00034 
00035 
00036 namespace TSFExtended
00037 {
00038 using namespace Teuchos;
00039 using namespace Thyra;
00040 
00041 /** 
00042  * LTIProblemFactoryBase is an interface for building 
00043  * operators related to reduced-order
00044  * LTI problems. The operators are
00045  *
00046  * <UL>
00047  * <LI> \f$ A \f$ -- operator defining a single step of 
00048  * the discrete time dynamical system
00049  * <LI> \f$ C \f$ -- operator defining the transformation from state
00050  * variables to observed variables at a single timestep
00051  * <LI> \f$ {\hat A}^{-1} \f$ -- block operator that produces a sequence
00052  * of state variables. This will be of type InverseLTIOp
00053  * <LI> \f$ {\hat C} \f$ -- block diagonal consisting of observation operators
00054  * for all timesteps.
00055  * <LI> \f$ F \f$ -- operator that maps the initial state to a full
00056  * space-time state vector padded with zeros: 
00057  * \f$ F = \left[\begin{array}{cccc} I & 0 & 0 & \cdots\end{array}\right]\f$
00058  * </UL>
00059  *
00060  * <H1> Create() methods versus get() methods </H1>
00061  * 
00062  * The create methods actually construct operators. They are protected and
00063  * can therefore only be called by internal methods. Client access to
00064  * operators should be through the get() methods. You will need to write a
00065  * couple of create() methods, but you'll probably never need
00066  * do call one.
00067  *
00068  * The get methods don't construct operators directly; if the operator
00069  * already exists, a cached value is returned. Otherwise, the create()
00070  * method is called and the newly-created operator is cached. 
00071  * 
00072  * <H1> How to implement a Hessian factory for your problem </H1>
00073  *
00074  * There are two pure virtual methods you must implement: createA() 
00075  * and createC(), which produce the single-timestep advance operator
00076  * and observation operator, respectively. 
00077  * 
00078  * The other create() methods have default implementations in terms
00079  * of implicit operators, and normally won't need to be overridden. 
00080  * In some cases you may want to override them; for example, you might
00081  * want to use an explicitly-formed transpose or matrix-matrix product
00082  * rather than the implicit implementations of these. 
00083  */
00084 template <class Scalar> 
00085 class LTIProblemFactoryBase
00086 {
00087 public:
00088   /** Constructor */
00089   LTIProblemFactoryBase(int nSteps)
00090     : nSteps_(nSteps), 
00091       A_(), C_(), 
00092       At_(), Ct_(), 
00093       bigAInv_(), bigAInvT_(),
00094       bigF_(), bigFt_(),
00095       bigC_(), bigCt_(),
00096       H_()
00097     {}
00098 
00099   /** */
00100   virtual ~LTIProblemFactoryBase() {;}
00101 
00102   /** \name Access to single-timestep operators */
00103   //@{
00104   /** Access the single-timestep advance operator */
00105   LinearOperator<Scalar> getA() const 
00106     {
00107       if (A_.ptr().get()==0) A_ = createA();
00108       return A_;
00109     }
00110 
00111   /** Access the single-timestep observation operator */
00112   LinearOperator<Scalar> getC() const
00113     {
00114       if (C_.ptr().get()==0) C_ = createC();
00115       return C_;
00116     }
00117 
00118 
00119   /** Access the single-timestep adjoint advance operator */
00120   LinearOperator<Scalar> getAt() const 
00121     {
00122       if (At_.ptr().get()==0) At_ = createAt();
00123       return At_;
00124     }
00125 
00126 
00127   /** Access the single-timestep adjoint observation operator */
00128   LinearOperator<Scalar> getCt() const 
00129     {
00130       if (Ct_.ptr().get()==0) Ct_ = createCt();
00131       return Ct_;
00132     }
00133   //@}
00134 
00135   /** \name Multiple-timestep operators */
00136   //@{
00137   /** Access the multiple-timestep advance operator */
00138   LinearOperator<Scalar> getBigAInv() const 
00139     {
00140       if (bigAInv_.ptr().get()==0) bigAInv_ = createBigAInv();
00141       return bigAInv_;
00142     }
00143 
00144   /** Access the zero-padding operator */
00145   LinearOperator<Scalar> getBigF() const 
00146     {
00147       if (bigF_.ptr().get()==0) bigF_ = createBigF();
00148       return bigF_;
00149     }
00150 
00151   /** Access the multiple-timestep observation operator */
00152   LinearOperator<Scalar> getBigC() const
00153     {
00154       if (bigC_.ptr().get()==0) bigC_ = createBigC();
00155       return bigC_;
00156     }
00157 
00158 
00159   /** Access the multiple-timestep adjoint advance operator */
00160   LinearOperator<Scalar> getBigAInvT() const 
00161     {
00162       if (bigAInvT_.ptr().get()==0) bigAInvT_ = createBigAInvT();
00163       return bigAInvT_;
00164     }
00165 
00166 
00167   /** Access the multiple-timestep adjoint observation operator */
00168   LinearOperator<Scalar> getBigCt() const 
00169     {
00170       if (bigCt_.ptr().get()==0) bigCt_ = createBigCt();
00171       return bigCt_;
00172     }
00173 
00174 
00175   /** Access the multiple-timestep adjoint zero-padding operator */
00176   LinearOperator<Scalar> getBigFt() const 
00177     {
00178       if (bigFt_.ptr().get()==0) bigFt_ = createBigFt();
00179       return bigFt_;
00180     }
00181 
00182   /** Access the space-time Hessian. This consists of a forward
00183    * calculation followed by an adjoint calculation */
00184   LinearOperator<Scalar> getH() const 
00185     {
00186       if (H_.ptr().get()==0) H_ = createH();
00187       return H_;
00188     }
00189   //@}
00190 
00191 protected:
00192 
00193   /** \name Pure virtual functions you must implement when setting up a concrete LTI problem */
00194   //@{
00195   /** Create the operator that advances the system through one timestep. */
00196   virtual LinearOperator<Scalar> createA() const = 0 ;
00197 
00198   /** Create the operator that produces the observable quantities given
00199    * a state. */
00200   virtual LinearOperator<Scalar> createC() const = 0 ;
00201   //@}
00202 
00203   /** \name Utilities */
00204   //@{
00205   /** Create a block vector space in which a space is replicated n times. */
00206   VectorSpace<Scalar> blockSpace(
00207     int n,
00208     const VectorSpace<Scalar>& sp
00209     ) const 
00210     {
00211       Array<VectorSpace<Scalar> > s(n, sp);
00212       return productSpace(s);
00213     }
00214 
00215   /** Create a block diagonal operator with a single block repeated
00216    * on all diagonal entries. */
00217   LinearOperator<Scalar> blockDiag(
00218     int n,
00219     const LinearOperator<Scalar>& C
00220     ) const 
00221     {
00222       Array<VectorSpace<Scalar> > d(n, C.domain());
00223       Array<VectorSpace<Scalar> > r(n, C.range());
00224       
00225       RCP<LinearOpBase<Scalar> > op
00226         = rcp(new BlockOperator<Scalar>(productSpace(d), productSpace(r)));
00227       LinearOperator<Scalar> rtn = op;
00228       for (int i=0; i<n; i++) rtn.setBlock(i, i, C);
00229       rtn.endBlockFill();
00230       return rtn;
00231     }
00232   //@}
00233   
00234   /** \name Create() methods with good default implementations */
00235   //@{
00236   /** */
00237   virtual LinearOperator<Scalar> createBigAInv() const 
00238     {
00239       RCP<LinearOpBase<Scalar> > rtn 
00240         = rcp(new InverseLTIOp<Scalar>(nSteps_, getA(), getAt()));
00241       return rtn;
00242     }
00243 
00244   /** */
00245   virtual LinearOperator<Scalar> createBigC() const 
00246     {return blockDiag(nSteps_, this->getC());}
00247 
00248   /** */
00249   virtual LinearOperator<Scalar> createBigF() const 
00250     {
00251       LinearOperator<Scalar> A = this->getA();
00252       std::cout << "A.domain().dim() = " << A.domain().dim() << std::endl;
00253       VectorSpace<Scalar> littleDomain = productSpace<Scalar>(tuple(A.domain()));
00254       
00255       LinearOperator<Scalar> I = identityOperator<Scalar>(A.domain());
00256       LinearOperator<Scalar> Z = zeroOperator<Scalar>(A.domain(), A.range());
00257       VectorSpace<Scalar> bigRange = this->blockSpace(nSteps_, A.range());
00258       std::cout << "bigRange.dim() = " << bigRange.dim() << std::endl;
00259 
00260       RCP<LinearOpBase<Scalar> > op
00261         = rcp(new BlockOperator<Scalar>(littleDomain, bigRange));
00262       LinearOperator<Scalar> rtn = op;
00263 
00264       rtn.setBlock(0, 0, I);
00265       for (int i=1; i<bigRange.numBlocks(); i++)
00266       {
00267         rtn.setBlock(i, 0, Z);
00268       }
00269       rtn.endBlockFill();
00270       return rtn;
00271     }
00272 
00273   /** By default, we create an implicit transpose of A. However, when
00274    * a transpose solver is unavailable, we should override this
00275    * function with one that returns an explicit transpose
00276    * of A. See the class ExplicitlyTransposedLTIProblemFactory for
00277    * a simple implementation of this. */
00278   virtual LinearOperator<Scalar> createAt() const 
00279     {return this->getA().transpose();}
00280 
00281   /** */
00282   virtual LinearOperator<Scalar> createCt() const 
00283     {return this->getC().transpose();}
00284 
00285   /** */
00286   virtual LinearOperator<Scalar> createBigAInvT() const 
00287     {return this->getBigAInv().transpose();}
00288 
00289   /** */
00290   virtual LinearOperator<Scalar> createBigFt() const 
00291     {return this->getBigF().transpose();}
00292 
00293   /** */
00294   virtual LinearOperator<Scalar> createBigCt() const 
00295     {return this->getBigC().transpose();}
00296 
00297   /** */
00298   virtual LinearOperator<Scalar> createH() const 
00299     {
00300       LinearOperator<Scalar> bigAInv = this->getBigAInv();
00301       LinearOperator<Scalar> bigAInvT = this->getBigAInvT();
00302       LinearOperator<Scalar> bigF = this->getBigF();
00303       LinearOperator<Scalar> bigC = this->getBigC();
00304       LinearOperator<Scalar> bigFt = this->getBigFt();
00305       LinearOperator<Scalar> bigCt = this->getBigCt();
00306 
00307       H_ = bigFt*bigAInvT*bigCt*bigC*bigAInv*bigF;
00308       return H_;
00309     }
00310   //@}
00311   
00312 private:
00313   int nSteps_;
00314   mutable LinearOperator<Scalar> A_;
00315   mutable LinearOperator<Scalar> C_;
00316 
00317   mutable LinearOperator<Scalar> At_;
00318   mutable LinearOperator<Scalar> Ct_;
00319 
00320   mutable LinearOperator<Scalar> bigAInv_;
00321   mutable LinearOperator<Scalar> bigAInvT_;
00322 
00323   mutable LinearOperator<Scalar> bigF_;
00324   mutable LinearOperator<Scalar> bigFt_;
00325 
00326   mutable LinearOperator<Scalar> bigC_;
00327   mutable LinearOperator<Scalar> bigCt_;
00328 
00329   mutable LinearOperator<Scalar> H_;
00330 };
00331 }
00332 
00333 
00334 #endif

Site Contact