21 #if defined(DEBUG) || defined(WARNINGMSG)
41 FunctionGradient Numerical2PGradientCalculator::operator()(
const MinimumParameters& par)
const {
44 InitialGradientCalculator gc(fFcn, fTransformation, fStrategy);
45 FunctionGradient gra = gc(par);
47 return (*
this)(par, gra);
52 FunctionGradient Numerical2PGradientCalculator::operator()(
const std::vector<double>& params)
const {
55 int npar = params.size();
57 MnAlgebraicVector par(npar);
58 for (
int i = 0; i < npar; ++i) {
62 double fval = Fcn()(par);
64 MinimumParameters minpars = MinimumParameters(par, fval);
66 return (*
this)(minpars);
72 FunctionGradient Numerical2PGradientCalculator::operator()(
const MinimumParameters& par,
const FunctionGradient& Gradient)
const {
80 assert(par.IsValid());
83 double fcnmin = par.Fval();
86 double eps2 = Precision().Eps2();
87 double eps = Precision().Eps();
89 double dfmin = 8.*eps2*(fabs(fcnmin)+Fcn().Up());
90 double vrysml = 8.*eps*eps;
96 unsigned int n = (par.Vec()).size();
97 unsigned int ncycle = Ncycle();
99 MnAlgebraicVector grd = Gradient.Grad();
100 MnAlgebraicVector g2 = Gradient.G2();
101 MnAlgebraicVector gstep = Gradient.Gstep();
104 MPIProcess mpiproc(n,0);
108 std::cout <<
"Calculating Gradient at x = " << par.Vec() << std::endl;
109 int pr = std::cout.precision(13);
110 std::cout <<
"fcn(x) = " << fcnmin << std::endl;
111 std::cout.precision(pr);
116 MnAlgebraicVector x = par.Vec();
118 unsigned int startElementIndex = mpiproc.StartElementIndex();
119 unsigned int endElementIndex = mpiproc.EndElementIndex();
121 for(
unsigned int i = startElementIndex; i < endElementIndex; i++) {
131 for(
int i = 0; i < int(n); i++) {
136 int ith = omp_get_thread_num();
142 MnAlgebraicVector x = par.Vec();
146 double epspri = eps2 + fabs(grd(i)*eps2);
148 for(
unsigned int j = 0; j < ncycle; j++) {
149 double optstp = sqrt(dfmin/(fabs(g2(i))+epspri));
150 double step = std::max(optstp, fabs(0.1*gstep(i)));
152 if(Trafo().Parameter(Trafo().ExtOfInt(i)).HasLimits()) {
153 if(step > 0.5) step = 0.5;
155 double stpmax = 10.*fabs(gstep(i));
156 if(step > stpmax) step = stpmax;
158 double stpmin = std::max(vrysml, 8.*fabs(eps2*x(i)));
159 if(step < stpmin) step = stpmin;
162 if(fabs((step-stepb4)/step) < StepTolerance()) {
176 double fs1 = Fcn()(x);
178 double fs2 = Fcn()(x);
181 double grdb4 = grd(i);
182 grd(i) = 0.5*(fs1 - fs2)/step;
183 g2(i) = (fs1 + fs2 - 2.*fcnmin)/step/step;
186 pr = std::cout.precision(13);
187 std::cout <<
"cycle " << j <<
" x " << x(i) <<
" step " << step <<
" f1 " << fs1 <<
" f2 " << fs2
188 <<
" grd " << grd(i) <<
" g2 " << g2(i) << std::endl;
189 std::cout.precision(pr);
192 if(fabs(grdb4-grd(i))/(fabs(grd(i))+dfmin/step) < GradTolerance()) {
205 std::cout <<
"Gradient for thread " << ith <<
" " << i <<
" " << std::setprecision(15) << grd(i) <<
" " << g2(i) << std::endl;
215 pr = std::cout.precision(13);
216 int iext = Trafo().ExtOfInt(i);
217 std::cout <<
"Parameter " << Trafo().Name(iext) <<
" Gradient = " << grd(i) <<
" g2 = " << g2(i) <<
" step " << gstep(i) << std::endl;
218 std::cout.precision(pr);
223 mpiproc.SyncVector(grd);
224 mpiproc.SyncVector(g2);
225 mpiproc.SyncVector(gstep);
229 std::cout <<
"Calculated Gradient at x = " << par.Vec() << std::endl;
230 std::cout <<
"fcn(x) = " << fcnmin << std::endl;
231 std::cout <<
"Computed gradient in N2PGC " << grd << std::endl;
234 return FunctionGradient(grd, g2, gstep);
237 const MnMachinePrecision& Numerical2PGradientCalculator::Precision()
const {
239 return fTransformation.Precision();
242 unsigned int Numerical2PGradientCalculator::Ncycle()
const {
244 return Strategy().GradientNCycles();
247 double Numerical2PGradientCalculator::StepTolerance()
const {
249 return Strategy().GradientStepTolerance();
252 double Numerical2PGradientCalculator::GradTolerance()
const {
254 return Strategy().GradientTolerance();