blockop.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004, 2005, 2006, 2007, 2008, 2009, 2010
00004 All rights reserved.
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a
00007 copy of this software and associated documentation files (the "Software"),
00008 to deal in the Software without restriction, including without limitation
00009 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, provided that the above copyright notice(s) and this
00012 permission notice appear in all copies of the Software and that both the
00013 above copyright notice(s) and this permission notice appear in supporting
00014 documentation.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00019 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00020 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00021 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00022 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00023 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00024 THIS SOFTWARE.
00025 
00026 Except as contained in this notice, the name of a copyright holder shall
00027 not be used in advertising or otherwise to promote the sale, use or other
00028 dealings in this Software without prior written authorization of the
00029 copyright holder.
00030 
00031 **************************************************************************/
00032 
00033 #ifndef __RVL_BLOCKOP
00034 #define __RVL_BLOCKOP
00035 
00036 #include "op.hh"
00037 
00038 namespace RVL {
00039 
00047   template<class Scalar> 
00048   class BlockOperator: public Operator<Scalar> {
00049 
00050     friend class OperatorEvaluation<Scalar>;
00051 
00052   protected:
00053 
00054     virtual void applyComponent(int i, 
00055                 const Vector<Scalar> & x,
00056                 Vector<Scalar> & yi) const = 0;
00057 
00058     virtual void apply(Vector<Scalar> const & x,
00059                Vector<Scalar> & y) const {
00060       try {
00061     Components<Scalar> yc(y);
00062     for (int i=0;i<(int)yc.getSize();i++) 
00063       applyComponent(i,x,yc[i]);
00064       }
00065       catch (RVLException & e) {
00066     e<<"\ncalled from BlockOperator::apply\n";
00067     throw e;
00068       }
00069     }
00070 
00072     virtual void applyComponentDeriv(int i, 
00073                      const Vector<Scalar> & x, 
00074                      const Vector<Scalar> & dx,
00075                      Vector<Scalar> & dyi) const = 0;
00076   
00081     virtual void applyDeriv(const Vector<Scalar> & x, 
00082                 const Vector<Scalar> & dx,
00083                 Vector<Scalar> & dy) const {
00084       try {
00085     Components<Scalar> dyc(dy);
00086     for (int i=0;i<(int)dyc.getSize();i++) 
00087       applyComponentDeriv(i,x,dx,dyc[i]);
00088       }
00089       catch (RVLException & e) {
00090     e<<"\ncalled from BlockOperator::applyDeriv\n";
00091     throw e;
00092       }
00093     }
00094 
00096     virtual void applyComponentAdjDeriv(int i, 
00097                     const Vector<Scalar> & x, 
00098                     const Vector<Scalar> & dyi,
00099                     Vector<Scalar> & dx) const = 0;
00100 
00104     virtual void applyAdjDeriv(const Vector<Scalar> & x, 
00105                    const Vector<Scalar> & dy,
00106                    Vector<Scalar> & dx) const {
00107       try {
00108     Components<Scalar> dyc(dy);
00109     applyComponentAdjDeriv(0,x,dyc[0],dx);
00110     if (dyc.getSize()>0) {
00111       Vector<Scalar> tmp(this->getDomain(),true);
00112       for (int i=1; i<(int)dyc.getSize(); i++) {
00113         applyComponentAdjDeriv(i,x,dyc[i],tmp);
00114         dx.linComb(1.0,tmp);
00115       }
00116     }
00117       }
00118       catch (RVLException & e) {
00119     e<<"\ncalled from BlockOperator::applyAdjDeriv\n";
00120     throw e;
00121       }
00122     }
00123 
00125     virtual void applyComponentDeriv2(int i,
00126                       const Vector<Scalar> & x,
00127                       const Vector<Scalar> & dx0,
00128                       const Vector<Scalar> & dx1,
00129                       Vector<Scalar> & dyi) const = 0;
00130       
00135     virtual void applyDeriv2(const Vector<Scalar> & x,
00136                  const Vector<Scalar> & dx0,
00137                  const Vector<Scalar> & dx1,
00138                  Vector<Scalar> & dy) const {
00139       try {
00140     Components<Scalar> dyc(dy);
00141     for (int i=0;i<(int)dyc.getSize();i++)
00142       applyComponentDeriv2(i,x,dx0,dx1,dyc[i]);
00143       }
00144       catch (RVLException & e) {
00145     e<<"\ncalled from BlockOperator::applyDeriv2\n";
00146     throw e;
00147       }
00148     }
00150     virtual void applyComponentAdjDeriv2(int i,
00151                      const Vector<Scalar> & x,
00152                      const Vector<Scalar> & dx0,
00153                      const Vector<Scalar> & dyi,
00154                      Vector<Scalar> & dx1) const = 0;
00155       
00159     virtual void applyAdjDeriv2(const Vector<Scalar> & x,
00160                 const Vector<Scalar> & dx0,
00161                 const Vector<Scalar> & dy,
00162                 Vector<Scalar> & dx1) const {
00163       try {
00164     Components<Scalar> dyc(dy);
00165     applyComponentAdjDeriv2(0,x,dx0,dyc[0],dx1);
00166     if (dyc.getSize()>0) {
00167       Vector<Scalar> tmp(this->getDomain(),true);
00168       for (int i=1; i<(int)dyc.getSize(); i++) {
00169         applyComponentAdjDeriv2(i,x,dx0,dyc[i],tmp);
00170         dx1.linComb(1.0,tmp);
00171       }
00172     }
00173       }
00174       catch (RVLException & e) {
00175     e<<"\ncalled from BlockOperator::applyAdjDeriv2\n";
00176     throw e;
00177       }
00178     }
00181     virtual BlockOperator<Scalar> * cloneBlockOp() const = 0;
00182     Operator<Scalar> * clone() const { return cloneBlockOp(); }
00183 
00184   public:
00185 
00186     BlockOperator() {}
00187     BlockOperator(const BlockOperator<Scalar> &) {}
00188     virtual ~BlockOperator() {}
00189 
00191     virtual const ProductSpace<Scalar> & getProductRange() const = 0;
00193     const Space<Scalar> & getRange() const { 
00194       return getProductRange(); 
00195     }
00196   
00197   };
00198 
00201   template<typename Scalar>
00202   class TensorOp: public BlockOperator<Scalar> {
00203 
00204   private:
00205 
00206     Operator<Scalar> const & op1;
00207     Operator<Scalar> const & op2;
00208     StdProductSpace<Scalar> rng;
00209 
00210     TensorOp();
00211 
00212   protected:
00213 
00214     void applyComponent(int i, 
00215             const Vector<Scalar> & x,
00216             Vector<Scalar> & yi) const {
00217       try {
00218     if (i==0) this->export_apply(op1,x,yi);
00219     else if (i==1) this->export_apply(op2,x,yi);
00220     else {
00221       RVLException e;
00222       e<<"Error: TensorOp::applyComponent\n";
00223       e<<"index "<<i<<" out of range [0,1]\n";
00224       throw e;
00225     }
00226       }
00227       catch (RVLException & e) {
00228     e<<"\ncalled from TensorOp::applyComponent\n";
00229     throw e;
00230       }
00231     }
00232 
00233     void applyComponentDeriv(int i,
00234                  const Vector<Scalar> & x, 
00235                  const Vector<Scalar> & dx,
00236                  Vector<Scalar> & dyi) const {
00237       try {
00238     if (i==0) this->export_applyDeriv(op1,x,dx,dyi);
00239     else if (i==1) this->export_applyDeriv(op2,x,dx,dyi);
00240     else {
00241       RVLException e;
00242       e<<"Error: TensorOp::applyComponentDeriv\n";
00243       e<<"index "<<i<<" out of range [0,1]\n";
00244       throw e;
00245     }
00246       }
00247       catch (RVLException & e) {
00248     e<<"\ncalled from TensorOp::applyComponentDeriv\n";
00249     throw e;
00250       }
00251     }
00252 
00253     void applyComponentAdjDeriv(int i, 
00254                 const Vector<Scalar> & x, 
00255                 const Vector<Scalar> & dyi,
00256                 Vector<Scalar> & dx) const {
00257       try {
00258     if (i==0) this->export_applyAdjDeriv(op1,x,dyi,dx);
00259     else if (i==1) this->export_applyAdjDeriv(op2,x,dyi,dx);
00260     else {
00261       RVLException e;
00262       e<<"Error: TensorOp::applyComponentAdjDeriv\n";
00263       e<<"index "<<i<<" out of range [0,1]\n";
00264       throw e;
00265     }
00266       }
00267       catch (RVLException & e) {
00268     e<<"\ncalled from TensorOp::applyComponentAdjDeriv\n";
00269     throw e;
00270       }
00271     }
00272   
00273     void applyComponentDeriv2(int i,
00274                   const Vector<Scalar> & x,
00275                   const Vector<Scalar> & dx0,
00276                   const Vector<Scalar> & dx1,
00277                   Vector<Scalar> & dyi) const {
00278       try {
00279     if (i==0) this->export_applyDeriv2(op1,x,dx0,dx1,dyi);
00280     else if (i==1) this->export_applyDeriv2(op2,x,dx0,dx1,dyi);
00281     else {
00282       RVLException e;
00283       e<<"Error: TensorOp::applyComponentDeriv2\n";
00284       e<<"index "<<i<<" out of range [0,1]\n";
00285       throw e;
00286     }
00287       }
00288       catch (RVLException & e) {
00289     e<<"\ncalled from TensorOp::applyComponentDeriv2\n";
00290     throw e;
00291       }
00292     }
00293       
00294     void applyComponentAdjDeriv2(int i,
00295                  const Vector<Scalar> & x,
00296                  const Vector<Scalar> & dx0,
00297                  const Vector<Scalar> & dyi,
00298                  Vector<Scalar> & dx1) const{
00299       try {
00300     if (i==0) this->export_applyAdjDeriv2(op1,x,dx0,dyi,dx1);
00301     else if (i==1) this->export_applyAdjDeriv2(op2,x,dx0,dyi,dx1);
00302     else {
00303       RVLException e;
00304       e<<"Error: TensorOp::applyComponentAdjDeriv2\n";
00305       e<<"index "<<i<<" out of range [0,1]\n";
00306       throw e;
00307     }
00308       }
00309       catch (RVLException & e) {
00310     e<<"\ncalled from TensorOp::applyComponentAdjDeriv2\n";
00311     throw e;
00312       }
00313     }
00314       
00315     TensorOp<Scalar> * cloneTensorOp() const { return new TensorOp(*this); }
00316     BlockOperator<Scalar> * cloneBlockOp() const { return cloneTensorOp(); }
00317 
00318   public:
00319 
00320     TensorOp(Operator<Scalar> const & _op1,
00321          Operator<Scalar> const & _op2)
00322       : op1(_op1), op2(_op2), rng(op1.getRange(),op2.getRange()) {
00323       try {
00324     if (op1.getDomain() != op2.getDomain()) {
00325       RVLException e;
00326       e<<"Error: TensorOp constructor\n";
00327       e<<"input operators do not have same domain\n";
00328       throw e;
00329     }
00330       }
00331       catch (RVLException & e) {
00332     e<<"\ncalled from TensorOp constructor\n";
00333     throw e;
00334       }
00335     }
00336 
00337     TensorOp(TensorOp<Scalar> const & op)
00338       : op1(op.op1), op2(op.op2), rng(op1.getRange(),op2.getRange()) {}
00339 
00340     ~TensorOp() {}
00341 
00342     Space<Scalar> const & getDomain() const { return op1.getDomain(); }
00343     ProductSpace<Scalar> const & getProductRange() const { return rng; }
00344 
00345     ostream & write(ostream & str) const {
00346       str<<"TensorOp: 2x1 block operator\n";
00347       str<<"*** operator[0,0]:\n";
00348       op1.write(str);
00349       str<<"*** operator[1,0]:\n";
00350       op2.write(str);
00351       return str;
00352     }
00353   };
00354 
00360   template<typename Scalar>
00361   class DiagOp: public Operator<Scalar> {
00362 
00363   private:
00364 
00365     std::vector<Operator<Scalar> const * > op;
00366     StdProductSpace<Scalar> dom;
00367     StdProductSpace<Scalar> rng;
00368 
00369     bool init() const {
00370       for (int i=0; i<op.size(); i++)
00371     if (!(op[i])) return false;
00372       return true;
00373     }
00374     
00375     DiagOp();
00376 
00377   protected:
00378 
00379     void apply(const Vector<Scalar> & x,
00380            Vector<Scalar> & y) const {
00381       try {
00382     if (!init()) {
00383       RVLException e;
00384       e<<"ERROR: DiagOp::apply\n";
00385       e<<"  not initialized\n";
00386       throw e;
00387     }
00388     //  cerr<<"DiagOp::apply\n";
00389     
00390     Components<Scalar> cx(x);
00391     Components<Scalar> cy(y);
00392     if ((cx.getSize() != op.size()) ||
00393         (cy.getSize() != op.size())) {
00394       RVLException e;
00395       e<<"ERROR: DiagOp::apply\n";
00396       e<<"  input or output vector has wrong number of args\n";
00397       throw e;
00398     }
00399     for (int i=0;i<op.size();i++)
00400       RVL::Operator<Scalar>::export_apply(*(op[i]),cx[i],cy[i]);
00401       }
00402       catch (RVLException & e) {
00403     e<<"\ncalled from DiagOp::apply\n";
00404     throw e;
00405       }
00406     }
00407 
00408     void applyDeriv(const Vector<Scalar> & x,
00409             const Vector<Scalar> & dx,
00410             Vector<Scalar> & dy) const {
00411       try {
00412     if (!init()) {
00413       RVLException e;
00414       e<<"ERROR: DiagOp::applyDeriv\n";
00415       e<<"  not initialized\n";
00416       throw e;
00417     }
00418     Components<Scalar> cx(x);
00419     Components<Scalar> cdx(dx);
00420     Components<Scalar> cdy(dy);
00421     if ((cx.getSize() != op.size()) ||
00422         (cdx.getSize() != op.size()) ||
00423         (cdy.getSize() != op.size())) {
00424       RVLException e;
00425       e<<"ERROR: DiagOp::applyDeriv\n";
00426       e<<"  input or output vector has wrong number of args\n";
00427       throw e;
00428     }
00429     for (int i=0; i<op.size(); i++) 
00430       RVL::Operator<Scalar>::export_applyDeriv(*(op[i]),cx[i],cdx[i],cdy[i]);
00431       }
00432       catch (RVLException & e) {
00433     e<<"\ncalled from DiagOp::applyDeriv\n";
00434     throw e;
00435       }
00436     }
00437 
00438     void applyAdjDeriv(const Vector<Scalar> & x,
00439                const Vector<Scalar> & dy,
00440                Vector<Scalar> & dx) const {
00441       try {
00442     if (!init()) {
00443       RVLException e;
00444       e<<"ERROR: DiagOp::applyAdjDeriv\n";
00445       e<<"  not initialized\n";
00446       throw e;
00447     }
00448         
00449     Components<Scalar> cx(x);
00450     Components<Scalar> cdx(dx);
00451     Components<Scalar> cdy(dy);
00452     if ((cx.getSize() != op.size()) ||
00453         (cdx.getSize() != op.size()) ||
00454         (cdy.getSize() != op.size())) {
00455       RVLException e;
00456       e<<"ERROR: DiagOp::applyAdjDeriv\n";
00457       e<<"  input or output vector has wrong number of args\n";
00458       throw e;
00459     }   
00460     for (int i=0; i<op.size(); i++) 
00461       RVL::Operator<Scalar>::export_applyAdjDeriv(*(op[i]),cx[i],cdy[i],cdx[i]);
00462       }
00463       catch (RVLException & e) {
00464     e<<"\ncalled from DiagOp::applyAdjDeriv\n";
00465     throw e;
00466       }
00467     }
00468 
00469     void applyDeriv2(const Vector<Scalar> & x,
00470              const Vector<Scalar> & dx0,
00471              const Vector<Scalar> & dx1,
00472              Vector<Scalar> & dy) const {
00473       try {
00474     if (!init()) {
00475       RVLException e;
00476       e<<"ERROR: DiagOp::applyDeriv2\n";
00477       e<<"  not initialized\n";
00478       throw e;
00479     }
00480 
00481     Components<Scalar> cx(x);
00482     Components<Scalar> cdx0(dx0);
00483     Components<Scalar> cdx1(dx1);
00484     Components<Scalar> cdy(dy);
00485     if ((cx.getSize() != op.size()) ||
00486         (cdx0.getSize() != op.size()) ||
00487         (cdx1.getSize() != op.size()) ||
00488         (cdy.getSize() != op.size())) {
00489       RVLException e;
00490       e<<"ERROR: DiagOp::applyDeriv2\n";
00491       e<<"  input or output vector has wrong number of args\n";
00492       throw e;
00493     }
00494     for (int i=0; i<op.size(); i++) 
00495       RVL::Operator<Scalar>::export_applyDeriv2(*(op[i]),cx[i],cdx0[i],cdx1[i],cdy[i]);
00496       }
00497       catch (RVLException & e) {
00498     e<<"\ncalled from DiagOp::applyDeriv2\n";
00499     throw e;
00500       }
00501     }
00502 
00503     void applyAdjDeriv2(const Vector<Scalar> & x,
00504             const Vector<Scalar> & dx0,
00505             const Vector<Scalar> & dy,
00506             Vector<Scalar> & dx1) const {
00507       try {
00508     if (!init()) {
00509       RVLException e;
00510       e<<"ERROR: DiagOp::applyAdjDeriv2\n";
00511       e<<"  not initialized\n";
00512       throw e;
00513     }
00514 
00515     Components<Scalar> cx(x);
00516     Components<Scalar> cdx0(dx0);
00517     Components<Scalar> cdx1(dx1);
00518     Components<Scalar> cdy(dy);
00519     if ((cx.getSize() != op.size()) ||
00520         (cdx0.getSize() != op.size()) ||
00521         (cdx1.getSize() != op.size()) ||
00522         (cdy.getSize() != op.size())) {
00523       RVLException e;
00524       e<<"ERROR: DiagOp::applyAdjDeriv2\n";
00525       e<<"  input or output vector has wrong number of args\n";
00526       throw e;
00527     }
00528     for (int i=0; i<op.size(); i++) 
00529       RVL::Operator<Scalar>::export_applyAdjDeriv2(*(op[i]),cx[i],cdx0[i],cdy[i],cdx1[i]);
00530 
00531       }
00532       catch (RVLException & e) {
00533     e<<"\ncalled from DiagOp::applyAdjDeriv2\n";
00534     throw e;
00535       }
00536     }
00537 
00538     Operator<Scalar> * clone() const { return new DiagOp(*this); }
00539 
00540   public:
00541 
00542     DiagOp(size_t nfac)
00543       : op(nfac, NULL), dom(nfac), rng(nfac) {}
00544 
00545     DiagOp(DiagOp<Scalar> const & x)
00546       : op(x.op), dom(x.dom), rng(x.rng) {}
00547 
00548     ~DiagOp() {}
00549 
00550     void set(Operator<Scalar> const & a, size_t i) {
00551       if (op[i]) {
00552     RVLException e;
00553     e<<"ERROR: DiagOp::set\n";
00554     e<<"  entry "<<i<<" already set\n";
00555     throw e;
00556       }
00557       op[i] = RVL::Operator<Scalar>::export_clone(a);
00558       dom.set(a.getDomain(),i);
00559       rng.set(a.getRange(),i);
00560     }
00561     
00562     Space<Scalar> const & getDomain() const { return dom; }
00563     Space<Scalar> const & getRange() const { return rng; }
00564 
00565     ostream & write(ostream & str) const {
00566       str<<"DiagOp: diagonal block operator\n";
00567       if (this->init()) {
00568     for (int i=0; i<op.size(); i++) {
00569       str<<"*** operator["<<i<<","<<i<<"]:\n";
00570       op[i]->write(str);
00571     }
00572       }
00573       else {
00574     str<<"  incompletely initialized\n";
00575       }
00576       return str;
00577     }
00578   };
00579 
00580   // forward declaration
00581   template<typename Scalar>
00582   class BlockLinearOpBlock;
00583 
00589   template<class Scalar>
00590   class BlockLinearOp: public LinearOp<Scalar> {
00591         
00592     friend class BlockLinearOpBlock<Scalar>;
00593 
00594   protected:
00595         
00597     virtual void apply(int i, int j,
00598                const Vector<Scalar> & xj,
00599                Vector<Scalar> & yi) const = 0;
00600       
00601     virtual void apply(Vector<Scalar> const & x,
00602                Vector<Scalar> & y) const {
00603       try {
00604     Components<Scalar> yc(y);
00605     Components<Scalar> xc(x);
00606     for (int i=0;i<(int)yc.getSize();i++)  {
00607       yc[i].zero();
00608       Vector<Scalar> tmp(yc[i].getSpace());
00609       for (int j=0; j< (int)xc.getSize(); j++) {
00610         apply(i,j,xc[j],tmp);
00611         yc[i].linComb(ScalarFieldTraits<Scalar>::One(),tmp);
00612       }
00613     }
00614       }
00615       catch (RVLException & e) {
00616     e<<"\ncalled from BlockLinearOp::apply\n";
00617     throw e;
00618       }
00619     }
00620    
00622     virtual void applyAdj(int i, int j,
00623               const Vector<Scalar> & yi,
00624               Vector<Scalar> & xj) const = 0;
00625         
00629     virtual void applyAdj(const Vector<Scalar> & y,
00630               Vector<Scalar> & x) const {
00631       try {
00632     Components<Scalar> xc(x);
00633     Components<Scalar> yc(y);
00634     for (int j=0; j<(int)xc.getSize();j++) {
00635       xc[j].zero();
00636       Vector<Scalar> tmp(xc[j].getSpace());
00637       for (int i=0; i<(int)yc.getSize(); i++) {
00638         applyAdj(i,j,yc[i],tmp);
00639         xc[j].linComb(ScalarFieldTraits<Scalar>::One(),tmp);
00640       }
00641     }
00642       }
00643       catch (RVLException & e) {
00644     e<<"\ncalled from BlockLinearOp::applyAdjDeriv\n";
00645     throw e;
00646       }
00647     }
00648 
00651     virtual BlockLinearOp<Scalar> * cloneBlockLinearOp() const = 0;
00652     LinearOp<Scalar> * clone() const { return cloneBlockLinearOp(); }
00653         
00654   public:
00655         
00656     BlockLinearOp() {}
00657     BlockLinearOp(const BlockLinearOp<Scalar> &) {}
00658     virtual ~BlockLinearOp() {}
00659         
00661     virtual const ProductSpace<Scalar> & getProductDomain() const = 0;
00663     const Space<Scalar> & getDomain() const { 
00664       return getProductDomain(); 
00665     }
00667     virtual const ProductSpace<Scalar> & getProductRange() const = 0;
00669     const Space<Scalar> & getRange() const { 
00670       return getProductRange(); 
00671     }
00672         
00673   };
00674 
00677   template<class Scalar>
00678   class BlockLinearOpBlock: public LinearOp<Scalar> {
00679 
00680   private:
00681 
00682     BlockLinearOp<Scalar> const & blk;
00683     int row;
00684     int col;
00685 
00686   protected:
00687         
00688     virtual void apply(const Vector<Scalar> & xj,
00689                Vector<Scalar> & yi) const {
00690       try {
00691     blk.apply(row, col, xj, yi);
00692       }      
00693       catch (RVLException & e) {
00694     e<<"\ncalled from BlockLinearOpBlock::apply\n";
00695     throw e;
00696       }
00697     }
00698       
00699     virtual void applyAdj(const Vector<Scalar> & yi,
00700               Vector<Scalar> & xj) const {
00701       try {
00702     blk.applyAdj(row, col, yi, xj);
00703       }
00704       catch (RVLException & e) {
00705     e<<"\ncalled from BlockLinearOpBlock::applyAdj\n";
00706     throw e;
00707       }
00708     }
00709 
00710     LinearOp<Scalar> * clone() const { return BlockLinearOpBlock(*this); }
00711         
00712   public:
00713         
00714     BlockLinearOpBlock(BlockLinearOp<Scalar> const & _blk, int _row, int _col): blk(_blk), row(_row), col(_col) {}
00715     BlockLinearOpBlock(const BlockLinearOpBlock<Scalar> & b): blk(b.blk), row(b.row), col(b.col) {}
00716     ~BlockLinearOpBlock() {}
00717         
00719     const Space<Scalar> & getDomain() const { 
00720       return blk.getProductDomain()[col]; 
00721     }
00723     const Space<Scalar> & getRange() const { 
00724       return blk.getProductRange()[row]; 
00725     }
00726         
00727   };
00728 
00733   template<class Scalar>
00734   class ColumnLinearOp: public LinearOp<Scalar> {
00735         
00736     friend class OperatorEvaluation<Scalar>;
00737         
00738   protected:
00739         
00740     virtual void applyComponent(int i,
00741                const Vector<Scalar> & x,
00742                Vector<Scalar> & yi) const = 0;
00743       
00744     virtual void apply(Vector<Scalar> const & x,
00745                Vector<Scalar> & y) const {
00746       try {
00747     Components<Scalar> yc(y);
00748     for (int i=0;i<(int)yc.getSize();i++) 
00749       applyComponent(i,x,yc[i]);
00750       }
00751       catch (RVLException & e) {
00752     e<<"\ncalled from ColumnLinearOp::apply\n";
00753     throw e;
00754       }
00755     }
00756 
00757         
00759     virtual void applyComponentAdj(int i,
00760                    const Vector<Scalar> & yi,
00761                    Vector<Scalar> & x) const = 0;
00762         
00766     virtual void applyAdj(const Vector<Scalar> & x,
00767               Vector<Scalar> & y) const {
00768       try {
00769     Components<Scalar> xc(x);
00770     applyComponentAdj(0,xc[0],y);
00771     if (xc.getSize()>0) {
00772       Vector<Scalar> tmp(this->getDomain(),true);
00773       for (int i=1; i<(int)xc.getSize(); i++) {
00774         applyComponentAdj(i,xc[i],tmp);
00775         y.linComb(1.0,tmp);
00776       }
00777     }
00778       }
00779       catch (RVLException & e) {
00780     e<<"\ncalled from ColumnLinearOp::applyAdjDeriv\n";
00781     throw e;
00782       }
00783     }
00784 
00787     virtual ColumnLinearOp<Scalar> * cloneColumnLinearOp() const = 0;
00788     LinearOp<Scalar> * clone() const { return cloneColumnLinearOp(); }
00789         
00790   public:
00791         
00792     ColumnLinearOp() {}
00793     ColumnLinearOp(const ColumnLinearOp<Scalar> &) {}
00794     virtual ~ColumnLinearOp() {}
00795         
00797     virtual const ProductSpace<Scalar> & getProductRange() const = 0;
00799     const Space<Scalar> & getRange() const { 
00800       return getProductRange(); 
00801     }
00802         
00803   };
00804     
00809   template<typename Scalar>
00810   class TensorLinearOp: public ColumnLinearOp<Scalar> {
00811         
00812   private:
00813         
00814     LinearOp<Scalar> const & op1;
00815     LinearOp<Scalar> const & op2;
00816     StdProductSpace<Scalar> rng;
00817         
00818     TensorLinearOp();
00819         
00820   protected:
00821         
00822     void applyComponent(int i,
00823             const Vector<Scalar> & x,
00824             Vector<Scalar> & yi) const {
00825       try {
00826     if (i==0) this->export_apply(op1,x,yi);
00827     else if (i==1) this->export_apply(op2,x,yi);
00828     else {
00829       RVLException e;
00830       e<<"Error: TensorLinearOp::applyComponent\n";
00831       e<<"index "<<i<<" out of range [0,1]\n";
00832       throw e;
00833     }
00834       }
00835       catch (RVLException & e) {
00836     e<<"\ncalled from TensorLinearOp::applyComponent\n";
00837     throw e;
00838       }
00839     }
00840         
00841     void applyComponentAdj(int i,
00842                const Vector<Scalar> & yi,
00843                Vector<Scalar> & x) const {
00844       try {
00845     if (i==0) op1.applyAdjOp(yi,x); //this->export_applyAdj(op1,yi,x);
00846     else if (i==1) op2.applyAdjOp(yi,x); //this->export_applyAdj(op2,yi,x);
00847     else {
00848       RVLException e;
00849       e<<"Error: TensorLinearOp::applyComponentAdj\n";
00850       e<<"index "<<i<<" out of range [0,1]\n";
00851       throw e;
00852     }
00853       }
00854       catch (RVLException & e) {
00855     e<<"\ncalled from TensorLinearOp::applyComponentAdj\n";
00856     throw e;
00857       }
00858     }
00859         
00860     TensorLinearOp<Scalar> * cloneTensorLinearOp() const { return new TensorLinearOp(*this); }
00861     ColumnLinearOp<Scalar> * cloneColumnLinearOp() const { return cloneTensorLinearOp(); }
00862         
00863   public:
00864         
00865     TensorLinearOp(LinearOp<Scalar> const & _op1,
00866            LinearOp<Scalar> const & _op2)
00867       : op1(_op1), op2(_op2), rng(op1.getRange(),op2.getRange()) {
00868       try {
00869     if (op1.getDomain() != op2.getDomain()) {
00870       RVLException e;
00871       e<<"Error: TensorLinearOp constructor\n";
00872       e<<"input operators do not have same domain\n";
00873       throw e;
00874     }
00875       }
00876       catch (RVLException & e) {
00877     e<<"\ncalled from TensorLinearOp constructor\n";
00878     throw e;
00879       }
00880     }
00881         
00882     TensorLinearOp(TensorLinearOp<Scalar> const & op)
00883       : op1(op.op1), op2(op.op2), rng(op1.getRange(),op2.getRange()) {}
00884         
00885     ~TensorLinearOp() {}
00886         
00887     Space<Scalar> const & getDomain() const { return op1.getDomain(); }
00888     ProductSpace<Scalar> const & getProductRange() const { return rng; }
00889         
00890     ostream & write(ostream & str) const {
00891       str<<"TensorLinearOp: 2x1 block operator\n";
00892       str<<"*** LinearOp[0,0]:\n";
00893       op1.write(str);
00894       str<<"*** LinearOp[1,0]:\n";
00895       op2.write(str);
00896       return str;
00897     }
00898   };
00899 
00900   /* FO implementation. 
00901 
00902      FOs arranged in BlockFO form. For an n x m BlockOpFO, the apply
00903      FOs are stored in a BlockFO of length n. The nm partial derivs
00904      are stored in a length-n std::vector of BlockFOs of length m, and
00905      adjoint partial derivatives in a length-m std::vector of BlockFOs
00906      of length n (i.e. the transpose structure). Because BlockFOs may
00907      themselves store persistent state, the vectors for deriv and adj
00908      deriv store pointers.
00909 
00910      Each FO in the apply BlockFO should define evaluation for argument
00911      vectors of length m.
00912 
00913      Deriv and adj deriv FOs should define evaluation for vectors of
00914      length m+1, and arg vector should take form
00915      
00916      (x[0],...,x[m-1],dx)
00917 
00918      in which dx is a perturbation of one of the jth input component
00919      for applyPartialDeriv(i,j,...), or of the ith output component
00920      for applyAdjPartialDeriv(i,j,...).
00921 
00922      Additionally provide for extra parameters in the form of
00923      RVL::Vectors, supplied in the form of a std::vector of
00924      pointers. These extra Vectors do not participate in domain or
00925      range definition, but simply parametrize the action of the
00926      FOs. Non-Vector parameters should be passed as member data of the
00927      FOs.
00928   */
00929 
00930   /*
00931     template<typename Scalar>
00932     class BlockOpFO: public BlockOperator<Scalar> {
00933 
00934     private:
00935 
00936     ProductSpace<Scalar> const & dom;
00937     ProductSpace<Scalar> const & rng;
00938     std::vector<FunctionObject *> & f; // F_i
00939     std::vector<std::vector<FunctionObject *> *> & dff; // DF_i/Dx_j
00940     std::vector<std::vector<FunctionObject *> *> & dfa; // DF_i/Dx_j^T
00941     std::vector<RVL::Vector<Scalar> const *> & par; // parameters
00942     BlockOpFO();
00943 
00944     protected:
00945 
00946     virtual void applyComponent(int i, 
00947     const Vector<Scalar> & x,
00948     Vector<Scalar> & yi) const {
00949     try {
00950     // standard sanity check
00951     if (x.getSpace() != dom) {
00952     RVLException e;
00953     e<<"Error: BlockFO::applyComponent\n";
00954     e<<"input reference arg not in domain\n";
00955     throw e;
00956     }
00957     if (yi.getSpace() != rng[i]) {
00958     RVLException e;
00959     e<<"Error: BlockFO::applyComponent\n";
00960     e<<"input arg not in component "<<i<<" of range\n";
00961     throw e;
00962     }
00963     Components<Scalar> xc(x);
00964     std::vector< RVL::Vector<Scalar> const * > xv(xc.getSize()+par.size());
00965     for (int j=0;j<xc.getSize();j++) xv[j]=&xc[j];
00966     for (int j=0;j<par.size();j++) xv[j+xc.getSize()]=par[j];
00967     yi.eval(*(f.at(i)),xv);
00968     }
00969     catch (RVLException & e) {
00970     e<<"\ncalled from BlockOpFO::apply\n";
00971     throw e;
00972     }
00973     catch (out_of_range) {
00974     RVLException e;
00975     e<<"Error: out-of-range exception in BlockOpFO::apply\n";
00976     throw e;
00977     }
00978     }
00979 
00980     virtual void applyPartialDeriv(int i, int j,
00981     const Vector<Scalar> & x, 
00982     const Vector<Scalar> & dxj,
00983     Vector<Scalar> & dyi) const {
00984     try {
00985     // standard sanity check
00986     if (x.getSpace() != dom) {
00987     RVLException e;
00988     e<<"Error: BlockFO::applyPartialDeriv\n";
00989     e<<"input reference arg not in domain\n";
00990     throw e;
00991     }
00992     if (dyi.getSpace() != rng[i]) {
00993     RVLException e;
00994     e<<"Error: BlockFO::applyPartialDeriv\n";
00995     e<<"output pert arg not in component "<<i<<" of range\n";
00996     throw e;
00997     }
00998     if (dxj.getSpace() != dom[j]) {
00999     RVLException e;
01000     e<<"Error: BlockFO::applyPartialDeriv\n";
01001     e<<"input pert arg not in component "<<j<<" of domain\n";
01002     throw e;
01003     }
01004 
01005     Components<Scalar> xc(x);
01006     std::vector<RVL::Vector<Scalar> const * > xv(xc.getSize()+1+par.size());
01007     for (int k=0;k<xc.getSize();k++) xv[k]=&xc[k];
01008     xv[xc.getSize()]=&dxj;
01009     for (int k=0;k<par.size();k++) xv[k+xc.getSize()+1]=par[k];
01010     dyi.eval(*((dff.at(i))->at(j)),xv);
01011     }
01012     catch (RVLException & e) {
01013     e<<"\ncalled from BlockOpFO::applyPartialDeriv\n";
01014     throw e;
01015     }
01016     catch (out_of_range) {
01017     RVLException e;
01018     e<<"Error: out-of-range exception in BlockOpFO::applyPartialDeriv\n";
01019     throw e;
01020     }
01021     }
01022 
01023     virtual void applyAdjPartialDeriv(int i, int j,
01024     const Vector<Scalar> & x, 
01025     const Vector<Scalar> & dyi,
01026     Vector<Scalar> & dxj) const {
01027     try {
01028     // standard sanity check
01029     if (x.getSpace() != dom) {
01030     RVLException e;
01031     e<<"Error: BlockFO::applyAdjPartialDeriv\n";
01032     e<<"input reference arg not in domain\n";
01033     throw e;
01034     }
01035     if (dyi.getSpace() != rng[i]) {
01036     RVLException e;
01037     e<<"Error: BlockFO::applyAdjPartialDeriv\n";
01038     e<<"input pert arg not in component "<<i<<" of range\n";
01039     throw e;
01040     }
01041     if (dxj.getSpace() != dom[j]) {
01042     RVLException e;
01043     e<<"Error: BlockFO::applyAdjPartialDeriv\n";
01044     e<<"output pert arg not in component "<<j<<" of domain\n";
01045     throw e;
01046     }
01047 
01048     Components<Scalar> xc(x);
01049     std::vector<RVL::Vector<Scalar> const * > xv(xc.getSize()+1+par.size());
01050     for (int k=0;k<xc.getSize();k++) xv[k]=&xc[k];
01051     xv[xc.getSize()]=&dyi;
01052     for (int k=0;k<par.size();k++) xv[k+xc.getSize()+1]=par[k];
01053     dxj.eval(*((dfa.at(j))->at(i)),xv);
01054     }
01055     catch (RVLException & e) {
01056     e<<"\ncalled from BlockOpFO::applyAdjPartialDeriv\n";
01057     throw e;
01058     }
01059     catch (out_of_range) {
01060     RVLException e;
01061     e<<"Error: out-of-range exception in BlockOpFO::applyAdjPartialDeriv\n";
01062     throw e;
01063     }
01064     }
01065 
01066     virtual BlockOperator<Scalar> * cloneBlockOp() const {
01067     return new BlockOpFO<Scalar>(*this);
01068     }
01069 
01070     public:
01071 
01072     BlockOpFO(ProductSpace<Scalar> const & _dom,
01073     ProductSpace<Scalar> const & _rng,
01074     std::vector< FunctionObject *> const & _f,
01075     std::vector< std::vector< FunctionObject *> *> const & _dff,
01076     std::vector< std::vector< FunctionObject *> *> const & _dfa,
01077     std::vector< Vector<Scalar> const *> const & _par)
01078     : dom(_dom), rng(_rng), f(_f), dff(_dff), dfa(_dfa), par(_par) {
01079     // sanity tests
01080     int m=dom.getSize();
01081     int n=rng.getSize();
01082 
01083     bool testdim = true;
01084     testdim = testdim && (n == f.size());
01085     testdim = testdim && (n == dff.size());
01086     for (int i=0;i<n;i++) 
01087     testdim = testdim && (m == (dff.at(i))->size());
01088     testdim = testdim && (m == dfa.size());
01089     for (int j=0;j<m;j++) 
01090     testdim = testdim && (n == (dfa.at(j))->size());
01091 
01092     if (!testdim) {
01093     RVLException e;
01094     e<<"Error: BlockOpFO construction failed, rows="<<n<<" cols="<<m<<"\n";
01095     e<<"incompatible input FO vectors\n";
01096     throw e;
01097     }
01098     }
01099 
01100     BlockOpFO(const BlockOpFO<Scalar> & a)
01101     : dom(a.dom), rng(a.rng), f(a.f), dff(a.dff), dfa(a.dfa), par(a.par) {
01102     // copy parameter vectors
01103     //      for (int i=0;i<a.par.size();i++) par[i]=a.par[i];
01104     }
01105 
01106     ~BlockOpFO() {}
01107    
01108     virtual const ProductSpace<Scalar> & getProductDomain() const { return dom; }
01109     virtual const ProductSpace<Scalar> & getProductRange() const { return rng; }
01110     };
01111 
01112   */
01113 
01136   template<typename Scalar>
01137   class InjectOp: public Operator<Scalar> {
01138     
01139   private:
01140 
01141     std::shared_ptr<Vector<Scalar> > ref;
01142     Components<Scalar> cref; 
01143     StdProductSpace<Scalar> dom;
01144     std::vector<int> icvec;
01145     
01146   protected:
01147     
01148     void apply(Vector<Scalar> const & x,
01149            Vector<Scalar> & y) const {
01150       // rely on built-in error trapping
01151       try {
01152     //  cerr<<"InjectOp::apply\n";
01153     y.copy(*ref);
01154     Components<Scalar> cy(y);
01155     Components<Scalar> cx(x);
01156     for (int i=0; i<icvec.size(); i++) 
01157       cy[icvec[i]].copy(cx[i]);
01158       }
01159       catch (RVLException &e) {
01160     e<<"\ncalled from InjectOp::apply\n";
01161     throw e;
01162       }
01163     }
01164 
01165     void applyDeriv(Vector<Scalar> const & x,
01166             Vector<Scalar> const & dx,
01167             Vector<Scalar> & dy) const {
01168       try {
01169     dy.zero();
01170     Components<Scalar> cx(dx);
01171     Components<Scalar> cy(dy);
01172     for (int i=0; i<icvec.size(); i++) 
01173       cy[icvec[i]].copy(cx[i]);
01174       }
01175       catch (RVLException &e) {
01176     e<<"\ncalled from InjectOp::applyDeriv\n";
01177     throw e;
01178       }
01179     }
01180     
01181     void applyAdjDeriv(Vector<Scalar> const & x,
01182                Vector<Scalar> const & dy,
01183                Vector<Scalar> & dx) const {
01184       try {
01185     Components<Scalar> cy(dy);
01186     Components<Scalar> cx(dx);
01187     for (int i=0; i<icvec.size(); i++) 
01188       cx[i].copy(cy[icvec[i]]);
01189       }
01190       catch (RVLException &e) {
01191     e<<"\ncalled from InjectOp::applyAdjDeriv\n";
01192     throw e;
01193       }
01194     }
01195 
01196     Operator<Scalar> * clone() const { return new InjectOp(*this); }
01197 
01198   public:
01199 
01200     InjectOp(std::shared_ptr<Vector<Scalar> > _ref,
01201          int _icomp)
01202       : ref(_ref), cref(*ref),
01203     dom(cref[_icomp].getSpace()),
01204     icvec(1,_icomp) {}
01205 
01206     InjectOp(std::shared_ptr<Vector<Scalar> > _ref,
01207          std::vector<int> _icvec)
01208       : ref(_ref), cref(*ref), icvec(_icvec), dom(_icvec.size()) {
01209       for (int i=0; i<icvec.size(); i++)
01210     dom.set(cref[i].getSpace(),i);
01211     }
01212     
01213     InjectOp(InjectOp<Scalar> const & f)
01214       : ref(f.ref), cref(*ref), dom(f.dom), icvec(f.icvec) {}
01215 
01216     ~InjectOp() {}
01217 
01218     Space<Scalar> const & getDomain() const { return dom; }
01219     Space<Scalar> const & getRange() const {
01220       return ref->getSpace();
01221     }
01222 
01223     ostream & write(ostream & str) const {
01224       str<<"InjectOp object\n";
01225       str<<"components = \n";
01226       for (int i=0; i<icvec.size(); i++) str<<"  index = "<<i<<" value = "<<icvec[i]<<"\n";
01227       str<<"reference vector in output product space:\n";
01228       ref->write(str);
01229       return str;
01230     }
01231   };
01232 }
01233     
01234 #endif

Generated on 5 Jan 2017 for RVL by  doxygen 1.4.7