@@ -18,6 +18,7 @@ NoxLapackInterface::NoxLapackInterface(INonLinearAlgLoop *algLoop, int numberofh
1818 ,_computedinitialguess(false )
1919 ,_numberofhomotopytries(numberofhomotopytries)
2020 ,_evaluatedJacobianAtInitialGuess(false )
21+ ,_UseAccurateJacobian(false )
2122{
2223 _dimSys = _algLoop->getDimReal ();
2324 _initialGuess = Teuchos::rcp (new NOX::LAPACK::Vector (_dimSys));
@@ -225,9 +226,10 @@ bool NoxLapackInterface::computeJacobian(NOX::LAPACK::Matrix<double>& J, const N
225226 double beta=1.0e-9 ;
226227 NOX::LAPACK::Vector f1 (_dimSys);// f(x+(alpha*|x_i|+beta)*e_i)
227228 NOX::LAPACK::Vector f2 (_dimSys);// f(x)
229+ NOX::LAPACK::Vector f3 (_dimSys);// f(x)
230+ NOX::LAPACK::Vector f4 (_dimSys);// f(x)
228231 NOX::LAPACK::Vector xplushei (x);// x+(alpha*|x_i|+beta)*e_i
229232
230- computeF (f2,x);
231233
232234 if (_generateoutput){
233235 std::cout << " we are at simtime " << _algLoop->getSimTime () << " and at position (seen by NOX) x=(" ;
@@ -240,30 +242,48 @@ bool NoxLapackInterface::computeJacobian(NOX::LAPACK::Matrix<double>& J, const N
240242 x.print (std::cout);
241243 }
242244
245+ if (_UseAccurateJacobian){
246+ for (int i=0 ;i<_dimSys;i++){
247+ double h = std::max (1.0e-3 ,1.0e-10 *std::abs (xplushei (i)));
248+ // adding the denominator of the difference quotient
249+ xplushei (i)+=h;
250+ computeF (f2,xplushei);
251+ xplushei (i)+=h;
252+ computeF (f1,xplushei);
253+ xplushei (i)=x (i);
254+
255+ xplushei (i)-=h;
256+ computeF (f3,xplushei);
257+ xplushei (i)-=h;
258+ computeF (f4,xplushei);
259+
260+ for (int j=0 ;j<_dimSys;j++){
261+ // J(j,i) = (f1(j)-f2(j))/(xplushei(i)-x(i));//=\partial_i f_j
262+ J (j,i) = (8 *(f2 (j)-f3 (j))-(f1 (j)-f4 (j)))/(6.0 *(x (i)-xplushei (i)));// =\partial_i f_j
263+ // print error compared with central difference
264+ if (std::abs (J (j,i)-(f2 (j)-f3 (j))/(2 *h))>1.0e-10 ){
265+ std::cout << " absolute error of J(" << j << " ," << i << " ): " << std::abs (J (j,i)-(f2 (j)-f3 (j))/(2 *h)) << std::endl;
266+ std::cout << " relative error of J(" << j << " ," << i << " ): " << (std::abs ((J (j,i)-(f2 (j)-f3 (j))/(2 *h))/(J (j,i)))-1.0 )/100.0 << " %" << std::endl;
267+ }
268+ }
269+ xplushei (i)=x (i);
270+ }
271+ }else {
272+ computeF (f2,x);
273+ for (int i=0 ;i<_dimSys;i++){
274+ // adding the denominator of the difference quotient
275+ xplushei (i)+=alpha*std::abs (xplushei (i))+beta;
276+ computeF (f1,xplushei);
277+ for (int j=0 ;j<_dimSys;j++){
278+ J (j,i) = (f1 (j)-f2 (j))/(xplushei (i)-x (i));// =\partial_i f_j
279+ }
280+ xplushei (i)=x (i);
281+ }
282+ }
243283
244- for (int i=0 ;i<_dimSys;i++){
245- // adding the denominator of the difference quotient
246- xplushei (i)+=alpha*std::abs (xplushei (i))+beta;
247- computeF (f1,xplushei);
248- for (int j=0 ;j<_dimSys;j++){
249- J (j,i) = (f1 (j)-f2 (j))/(xplushei (i)-x (i));// =\partial_i f_j
250- }
251- xplushei (i)=x (i);
252- }
253-
254- // if (_generateoutput){
255- // std::cout << "the Jacobian is given by (the transpose of) " << std::endl;
256- // for (int i=0;i<_dimSys;i++){
257- // for (int j=0;j<_dimSys;j++){
258- // std::cout << J(j,i) << " ";
259- // }
260- // std::cout << std::endl;
261- // }
262- // std::cout << std::endl << "done computing Jacobian" << std::endl;
263- // }
264284 if (_generateoutput){
265285 std::cout << " the Jacobian is given by" << std::endl;
266- J.print (std::cout);// is correct, no transposing necessary.
286+ J.print (std::cout);
267287 }
268288 return true ;
269289}
0 commit comments