00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00180
00181
00182
00183
00184
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
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