derivtest.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004, 2005, 2006.
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_DERIVTEST
00034 #define __RVL_DERIVTEST
00035 
00036 #include "op.hh"
00037 
00038 namespace RVL {
00039 
00073   template<typename Scalar>
00074   bool DerivTest(Operator<Scalar> const & op,
00075          Vector<Scalar> const & y,
00076          Vector<Scalar> const & p,
00077          ostream & str,
00078          int n = 10,
00079          typename ScalarFieldTraits<Scalar>::AbsType hmin = 0.1, 
00080          typename ScalarFieldTraits<Scalar>::AbsType hmax = 1.0,
00081          typename ScalarFieldTraits<Scalar>::AbsType minrat = 1.95) {
00082     
00083     try {
00084       
00085       if( !y.inSpace(op.getDomain()) ) {
00086     RVLException e;
00087     e<<"Error: Operator::checkDeriv: \n";
00088     e<<"base vector is not in Domain\n";
00089     throw e;
00090       }
00091       if( !p.inSpace(op.getDomain()) ) {
00092     RVLException e;
00093     e<<"Error: Operator::CheckDeriv: \n";
00094     e<<"direction vector is not in Domain\n";
00095     throw e;
00096       }
00097 
00098       if( hmax <= hmin ) {
00099     typename ScalarFieldTraits<Scalar>::AbsType temp = hmax;
00100     hmax = hmin;
00101     hmin = temp;
00102       }
00103 
00104       if( hmin <= 0.0 ) {
00105     hmin = 0.1;
00106     hmax = 1.0;
00107       }
00108       if( n <= 0 ) n = 10;
00109 
00110 
00111       Scalar hlimit1;
00112       Scalar hlimit2;
00113 
00114       hlimit1 = op.getMaxStep( y,p );
00115       {
00116     Vector<Scalar> ptemp(op.getDomain());
00117     ptemp.scale( -1.0,p);
00118     hlimit2 = op.getMaxStep( y,ptemp );
00119       }
00120 
00121       typename ScalarFieldTraits<Scalar>::AbsType hlimit = min( abs(hlimit1),abs(hlimit2) );
00122       if( hlimit <= 0.0 ) {
00123     RVLException e;
00124     e<<"Error: Operator::CheckDeriv: direction is not \n";
00125     e<<"feasible\n";
00126     throw e;
00127       }
00128 
00129       if( hmax >= hlimit ) {
00130     hmax = 0.99*hlimit;
00131     if( hmin >= hmax ) hmin = hmax/n;
00132       }
00133 
00134       Vector<Scalar> x1(op.getDomain());
00135       Vector<Scalar> x2(op.getDomain());
00136       Vector<Scalar> g1(op.getRange());
00137       Vector<Scalar> g2(op.getRange());
00138       Vector<Scalar> dg(op.getRange());
00139 
00140       OperatorEvaluation<Scalar> Fy(op,y);
00141       Fy.getDeriv().applyOp(p,dg);
00142     
00143       int nd;
00144       if (numeric_precision<Scalar>()==1) nd = 8;
00145       if (numeric_precision<Scalar>()==2) nd = 16;
00146 
00147       int oldprecision = str.precision( nd );
00148 
00149       typename ScalarFieldTraits<Scalar>::AbsType dgnorm = dg.norm();
00150       int rflag = 1;
00151 
00152       if( dgnorm < numeric_limits<typename ScalarFieldTraits<Scalar>::AbsType >::epsilon() ) {
00153     rflag = 0;
00154     str << "DerivTest: norm of first variation = "<<dgnorm<<" is too "
00155         << endl << "small; displaying absolute error" << endl;
00156       }
00157     
00158       str<<endl<<"Operator::checkDeriv"<<endl<<endl;
00159    
00160       if( rflag )
00161     str << setw(8) << "h" << setw(nd+7) << " norm of diff." << setw(nd+8) 
00162         << "rel. error" << setw(nd+6)   << "convg. rate" << endl;
00163       else
00164     str << setw(8) << "h" << setw(nd+7) << " norm of diff." << setw(nd+6)
00165         << "convg. rate" << endl;
00166       int i;
00167       typename ScalarFieldTraits<Scalar>::AbsType hstep = (hmax-hmin)/(n-1);
00168       typename ScalarFieldTraits<Scalar>::AbsType n1p=ScalarFieldTraits<Scalar>::AbsOne();
00169       typename ScalarFieldTraits<Scalar>::AbsType tn;
00170       typename ScalarFieldTraits<Scalar>::AbsType tmp =ScalarFieldTraits<Scalar>::AbsZero();
00171 
00172       OperatorEvaluation<Scalar> opeval1(op,x1);
00173       OperatorEvaluation<Scalar> opeval2(op,x2);
00174 
00175       for( i=n-1;i>=0;i-- )  {
00176     typename ScalarFieldTraits<Scalar>::AbsType h = hmin+i*hstep;
00177     x1.copy(y);
00178     x1.linComb(-h,p);
00179     // it is essential to use evals here - otherwise the 
00180     // internal workspace created for x1 won't be reinitialized
00181     // for evaluating on x2, as the operator clone implied by
00182     // the eval constructor will not take place - you can't
00183     // just use apply, even though it's available as a class
00184     // method!!!
00185     x2.copy(y);
00186     x2.linComb(h,p);
00187     g2.copy(opeval2.getValue());
00188     Scalar one = ScalarFieldTraits<Scalar>::One();
00189     g2.linComb(-one,opeval1.getValue());
00190     g2.linComb(-one,dg,one/(2.0*h));
00191     typename ScalarFieldTraits<Scalar>::AbsType n1 = g2.norm();
00192     if (i<n-1 && !ProtectedDivision<typename ScalarFieldTraits<Scalar>::AbsType>(n1p,n1,tn)) {
00193       tmp = log(tn)/log((h+hstep)/h);
00194       if( rflag )
00195         str << setprecision(6) << setw(8) << h << " " << setprecision(nd)
00196         << setw(nd+6) << n1 << setw(nd+8) << n1/dgnorm << setw(nd+6)
00197         << tmp << endl;
00198       else
00199         str << setprecision(6) << setw(8) << h << " " << setprecision(nd)
00200         << setw(nd+6) << n1 << setw(nd+6)
00201         << tmp  << endl;
00202     }
00203     else {
00204       char * jnk = new char[nd];
00205       for (int ii=0;ii<nd;ii++) {
00206         jnk[ii]='-';
00207       }
00208       jnk[nd-1]='\0';
00209       if( rflag )
00210         str << setprecision(6) << setw(8) << h << " " << setprecision(nd)
00211         << setw(nd+6) << n1 << setw(nd+8) << n1/dgnorm << setw(nd+6)
00212         << jnk << endl;
00213       else
00214         str << setprecision(6) << setw(8) << h << " " << setprecision(nd)
00215         << setw(nd+6) << n1 << " " << setw(nd+6)
00216         << jnk  << endl;
00217       delete [] jnk;
00218     }
00219     n1p=n1;
00220       }
00221       str.precision( oldprecision );
00222       // return value pred on last value of log ratio tmp
00223       if (tmp > minrat) return true;
00224       return false;
00225     }
00226     catch (RVLException & e) {
00227       e<<"\ncalled from Operator::checkDeriv\n";
00228       throw e;
00229     }
00230 
00231   }
00232 
00233 }
00234 
00235 #endif

Generated on 5 Jan 2017 for RVL by  doxygen 1.4.7