source: ThirdParty/mpqc_open/src/lib/math/optimize/newton.cc@ 23612c

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 23612c was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 6.2 KB
Line 
1//
2// newton.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <math.h>
33#include <float.h>
34
35#include <math/optimize/newton.h>
36#include <util/keyval/keyval.h>
37#include <util/misc/formio.h>
38#include <util/state/stateio.h>
39
40using namespace std;
41using namespace sc;
42
43/////////////////////////////////////////////////////////////////////////
44// NewtonOpt
45
46static ClassDesc NewtonOpt_cd(
47 typeid(NewtonOpt),"NewtonOpt",1,"public Optimize",
48 0, create<NewtonOpt>, create<NewtonOpt>);
49
50NewtonOpt::NewtonOpt(const Ref<KeyVal>&keyval):
51 Optimize(keyval)
52{
53 init();
54
55 accuracy_ = keyval->doublevalue("accuracy",KeyValValuedouble(0.0001));
56 print_x_ = keyval->booleanvalue("print_x");
57 print_hessian_ = keyval->booleanvalue("print_hessian");
58 print_gradient_ = keyval->booleanvalue("print_gradient");
59}
60
61NewtonOpt::NewtonOpt(StateIn&s):
62 SavableState(s),
63 Optimize(s)
64{
65 s.get(accuracy_);
66 s.get(maxabs_gradient);
67 s.get(print_hessian_);
68 s.get(print_x_);
69 s.get(print_gradient_);
70}
71
72NewtonOpt::~NewtonOpt()
73{
74}
75
76void
77NewtonOpt::save_data_state(StateOut&s)
78{
79 Optimize::save_data_state(s);
80 s.put(accuracy_);
81 s.put(maxabs_gradient);
82 s.put(print_hessian_);
83 s.put(print_x_);
84 s.put(print_gradient_);
85}
86
87void
88NewtonOpt::init()
89{
90 Optimize::init();
91 maxabs_gradient = -1.0;
92}
93
94int
95NewtonOpt::update()
96{
97 // these are good candidates to be input options
98 const double maxabs_gradient_to_desired_accuracy = 0.05;
99 const double maxabs_gradient_to_next_desired_accuracy = 0.005;
100 const double roundoff_error_factor = 1.1;
101
102 // the gradient convergence criterion.
103 double old_maxabs_gradient = maxabs_gradient;
104 RefSCVector xcurrent;
105 RefSCVector gcurrent;
106
107 // get the next gradient at the required level of accuracy.
108 // usually only one pass is needed, unless we happen to find
109 // that the accuracy was set too low.
110 int accurate_enough;
111 do {
112 // compute the current point
113 function()->set_desired_gradient_accuracy(accuracy_);
114
115 xcurrent = function()->get_x();
116 gcurrent = function()->gradient().copy();
117
118 // compute the gradient convergence criterion now so i can see if
119 // the accuracy needs to be tighter
120 maxabs_gradient = gcurrent.maxabs();
121 // compute the required accuracy
122 accuracy_ = maxabs_gradient * maxabs_gradient_to_desired_accuracy;
123
124 if (accuracy_ < DBL_EPSILON) accuracy_ = DBL_EPSILON;
125
126 // The roundoff_error_factor is thrown in to allow for round off making
127 // the current gcurrent.maxabs() a bit smaller than the previous,
128 // which would make the current required accuracy less than the
129 // gradient's actual accuracy and cause everything to be recomputed.
130 accurate_enough = (
131 function()->actual_gradient_accuracy()
132 <= accuracy_*roundoff_error_factor);
133
134 if (!accurate_enough) {
135 ExEnv::out0().unsetf(ios::fixed);
136 ExEnv::out0() << indent
137 << "NOTICE: function()->actual_gradient_accuracy() > accuracy_:\n"
138 << indent
139 << scprintf(
140 " function()->actual_gradient_accuracy() = %15.8e",
141 function()->actual_gradient_accuracy()) << endl << indent
142 << scprintf(
143 " accuracy_ = %15.8e",
144 accuracy_) << endl;
145 }
146 } while(!accurate_enough);
147
148 if (old_maxabs_gradient >= 0.0 && old_maxabs_gradient < maxabs_gradient) {
149 ExEnv::out0() << indent
150 << scprintf("NOTICE: maxabs_gradient increased from %8.4e to %8.4e",
151 old_maxabs_gradient, maxabs_gradient) << endl;
152 }
153
154 RefSymmSCMatrix hessian = function()->hessian();
155 RefSymmSCMatrix ihessian = function()->inverse_hessian(hessian);
156
157 if (print_hessian_) {
158 hessian.print("hessian");
159 }
160 if (print_x_) {
161 int n = xcurrent.n();
162 ExEnv::out0() << indent << "x = [";
163 for (int i=0; i<n; i++) {
164 ExEnv::out0() << scprintf(" % 16.12f",double(xcurrent(i)));
165 }
166 ExEnv::out0() << " ]" << endl;
167 }
168 if (print_gradient_) {
169 int n = gcurrent.n();
170 ExEnv::out0() << indent << "gradient = [";
171 for (int i=0; i<n; i++) {
172 ExEnv::out0() << scprintf(" % 16.12f",double(gcurrent(i)));
173 }
174 ExEnv::out0() << " ]" << endl;
175 }
176
177 // take the step
178 RefSCVector xdisp = -1.0*(ihessian * gcurrent);
179 // scale the displacement vector if it's too large
180 double tot = sqrt(xdisp.scalar_product(xdisp));
181 if (tot > max_stepsize_) {
182 double scal = max_stepsize_/tot;
183 ExEnv::out0() << endl << indent
184 << scprintf("stepsize of %f is too big, scaling by %f",tot,scal)
185 << endl;
186 xdisp.scale(scal);
187 tot *= scal;
188 }
189
190 RefSCVector xnext = xcurrent + xdisp;
191
192 conv_->reset();
193 conv_->get_grad(function());
194 conv_->get_x(function());
195 conv_->set_nextx(xnext);
196
197 // check for convergence before resetting the geometry
198 int converged = conv_->converged();
199 if (converged)
200 return converged;
201
202 ExEnv::out0() << endl << indent
203 << scprintf("taking step of size %f", tot) << endl;
204
205 function()->set_x(xnext);
206
207 // make the next gradient computed more accurate, since it will
208 // be smaller
209 accuracy_ = maxabs_gradient * maxabs_gradient_to_next_desired_accuracy;
210
211 return converged;
212}
213
214/////////////////////////////////////////////////////////////////////////////
215
216// Local Variables:
217// mode: c++
218// c-file-style: "ETS"
219// End:
Note: See TracBrowser for help on using the repository browser.