Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit e133834

Browse files
qichenghuaOpenModelica-Hudson
authored andcommitted
added more accurate (4th order) method of computing the finite difference approximation to the jacobian of the algloop.
1 parent 7187f70 commit e133834

File tree

2 files changed

+43
-22
lines changed

2 files changed

+43
-22
lines changed

SimulationRuntime/cpp/Include/Solver/Nox/NoxLapackInterface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ class NoxLapackInterface : public LOCA::LAPACK::Interface {
4343
int _numberofhomotopytries;
4444
bool _evaluatedJacobianAtInitialGuess;
4545
Teuchos::RCP<NOX::LAPACK::Matrix<double>> _J;//F'(x_0)
46+
bool _UseAccurateJacobian;
4647
};

SimulationRuntime/cpp/Solver/Nox/NoxLapackInterface.cpp

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)