ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-3.0/src/minimizers/OOPSEMinimizer.cpp
Revision: 1884
Committed: Tue Dec 14 19:08:44 2004 UTC (19 years, 9 months ago) by tim
File size: 19284 byte(s)
Log Message:
more fix in MPI version

File Contents

# User Rev Content
1 tim 1884 #include <cmath>
2 tim 1826
3     #include "minimizers/OOPSEMinimizer.hpp"
4     #include "integrators/Integrator.cpp"
5    
6 tim 1884 namespace oopse {
7 tim 1826
8 tim 1884 OOPSEMinimizer::OOPSEMinimizer(SimInfo* theInfo, MinimizerParameterSet *param) :
9     info(theInfo), paramSet(param), bShake(true), bVerbose(false) {
10 tim 1826
11 tim 1884 calcDim();
12     curX = getCoor();
13     curG.resize(ndim);
14 tim 1826
15     }
16    
17 tim 1884 OOPSEMinimizer::~OOPSEMinimizer() {
18     delete paramSet;
19 tim 1826 }
20    
21 tim 1884 void OOPSEMinimizer::calcEnergyGradient(std::vector < double > &x,
22     std::vector < double > &grad, double&energy, int&status) {
23 tim 1826
24 tim 1884 DirectionalAtom *dAtom;
25     int index;
26     double force[3];
27     double dAtomGrad[6];
28 tim 1826
29 tim 1884 int shakeStatus;
30 tim 1826
31 tim 1884 status = 1;
32 tim 1826
33 tim 1884 setCoor(x);
34 tim 1826
35 tim 1884 if (nConstrained && bShake) {
36     shakeStatus = shakeR();
37     }
38 tim 1826
39 tim 1884 calcForce(1, 1);
40 tim 1826
41 tim 1884 if (nConstrained && bShake) {
42     shakeStatus = shakeF();
43     }
44 tim 1826
45 tim 1884 x = getCoor();
46 tim 1826
47 tim 1884 index = 0;
48 tim 1826
49 tim 1884 for(int i = 0; i < integrableObjects.size(); i++) {
50     if (integrableObjects[i]->isDirectional()) {
51     integrableObjects[i]->getGrad(dAtomGrad);
52 tim 1826
53 tim 1884 //gradient is equal to -f
54 tim 1826
55 tim 1884 grad[index++] = -dAtomGrad[0];
56 tim 1826
57 tim 1884 grad[index++] = -dAtomGrad[1];
58 tim 1826
59 tim 1884 grad[index++] = -dAtomGrad[2];
60 tim 1826
61 tim 1884 grad[index++] = -dAtomGrad[3];
62 tim 1826
63 tim 1884 grad[index++] = -dAtomGrad[4];
64 tim 1826
65 tim 1884 grad[index++] = -dAtomGrad[5];
66     } else {
67     integrableObjects[i]->getFrc(force);
68 tim 1826
69 tim 1884 grad[index++] = -force[0];
70 tim 1826
71 tim 1884 grad[index++] = -force[1];
72 tim 1826
73 tim 1884 grad[index++] = -force[2];
74     }
75 tim 1826 }
76    
77 tim 1884 energy = tStats->getPotential();
78 tim 1826 }
79    
80 tim 1884 void OOPSEMinimizer::setCoor(std::vector<double> &x) {
81     Vector3d position;
82     Vector3d eulerAngle;
83     SimInfo::MoleculeIterator i;
84     Molecule::IntegrableObjectIterator j;
85     Molecule* mol;
86     StuntDouble* integrableObject;
87     int index = 0;
88 tim 1826
89 tim 1884 for (mol = info->beginMolecule(i); mol != NULL; mol = info->nextMolecule(i)) {
90     for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
91     integrableObject = mol->nextIntegrableObject(j)) {
92 tim 1826
93 tim 1884 position[0] = x[index++];
94 tim 1826
95 tim 1884 position[1] = x[index++];
96 tim 1826
97 tim 1884 position[2] = x[index++];
98 tim 1826
99 tim 1884 integrableObject->setPos(position);
100 tim 1826
101 tim 1884 if (integrableObject->isDirectional()) {
102     eulerAngle[0] = x[index++];
103 tim 1826
104 tim 1884 eulerAngle[1] = x[index++];
105 tim 1826
106 tim 1884 eulerAngle[2] = x[index++];
107 tim 1826
108 tim 1884 integrableObject->setEuler(eulerAngle);
109     }
110     }
111 tim 1826 }
112    
113     }
114    
115 tim 1884 std::vector<double> OOPSEMinimizer::getCoor() {
116     Vector3d position;
117     Vector3d eulerAngle;
118     SimInfo::MoleculeIterator i;
119     Molecule::IntegrableObjectIterator j;
120     Molecule* mol;
121     StuntDouble* integrableObject;
122     int index = 0;
123     std::vector<double> x(getDim());
124 tim 1826
125 tim 1884 for (mol = info->beginMolecule(i); mol != NULL; mol = info->nextMolecule(i)) {
126     for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
127     integrableObject = mol->nextIntegrableObject(j)) {
128    
129     position = integrableObject->getPos();
130     x[index++] = position[0];
131     x[index++] = position[1];
132     x[index++] = position[2];
133 tim 1826
134 tim 1884 if (integrableObject->isDirectional()) {
135     eulerAngle = integrableObject->getEuler();
136     x[index++] = eulerAngle[0];
137     x[index++] = eulerAngle[1];
138     x[index++] = eulerAngle[2];
139     }
140     }
141 tim 1826 }
142 tim 1884 return x;
143 tim 1826 }
144    
145    
146 tim 1884 /*
147     int OOPSEMinimizer::shakeR() {
148     int i, j;
149 tim 1826
150 tim 1884 int done;
151 tim 1826
152 tim 1884 double posA[3], posB[3];
153 tim 1826
154 tim 1884 double velA[3], velB[3];
155 tim 1826
156 tim 1884 double pab[3];
157 tim 1826
158 tim 1884 double rab[3];
159 tim 1826
160 tim 1884 int a, b,
161     ax, ay,
162     az, bx,
163     by, bz;
164 tim 1826
165 tim 1884 double rma, rmb;
166 tim 1826
167 tim 1884 double dx, dy,
168     dz;
169 tim 1826
170 tim 1884 double rpab;
171 tim 1826
172 tim 1884 double rabsq, pabsq,
173     rpabsq;
174 tim 1826
175 tim 1884 double diffsq;
176 tim 1826
177 tim 1884 double gab;
178 tim 1826
179 tim 1884 int iteration;
180 tim 1826
181 tim 1884 for(i = 0; i < nAtoms; i++) {
182     moving[i] = 0;
183 tim 1826
184 tim 1884 moved[i] = 1;
185     }
186 tim 1826
187 tim 1884 iteration = 0;
188 tim 1826
189 tim 1884 done = 0;
190 tim 1826
191 tim 1884 while (!done && (iteration < maxIteration)) {
192     done = 1;
193 tim 1826
194 tim 1884 for(i = 0; i < nConstrained; i++) {
195     a = constrainedA[i];
196 tim 1826
197 tim 1884 b = constrainedB[i];
198 tim 1826
199 tim 1884 ax = (a * 3) + 0;
200 tim 1826
201 tim 1884 ay = (a * 3) + 1;
202 tim 1826
203 tim 1884 az = (a * 3) + 2;
204 tim 1826
205 tim 1884 bx = (b * 3) + 0;
206 tim 1826
207 tim 1884 by = (b * 3) + 1;
208 tim 1826
209 tim 1884 bz = (b * 3) + 2;
210 tim 1826
211 tim 1884 if (moved[a] || moved[b]) {
212     posA = atoms[a]->getPos();
213 tim 1826
214 tim 1884 posB = atoms[b]->getPos();
215 tim 1826
216 tim 1884 for(j = 0; j < 3; j++)
217     pab[j] = posA[j] - posB[j];
218 tim 1826
219 tim 1884 //periodic boundary condition
220 tim 1826
221 tim 1884 info->wrapVector(pab);
222 tim 1826
223 tim 1884 pabsq = pab[0] * pab[0] + pab[1] * pab[1] + pab[2] * pab[2];
224 tim 1826
225 tim 1884 rabsq = constrainedDsqr[i];
226 tim 1826
227 tim 1884 diffsq = rabsq - pabsq;
228 tim 1826
229 tim 1884 // the original rattle code from alan tidesley
230 tim 1826
231 tim 1884 if (fabs(diffsq) > (tol * rabsq * 2)) {
232     rab[0] = oldPos[ax] - oldPos[bx];
233 tim 1826
234 tim 1884 rab[1] = oldPos[ay] - oldPos[by];
235 tim 1826
236 tim 1884 rab[2] = oldPos[az] - oldPos[bz];
237 tim 1826
238 tim 1884 info->wrapVector(rab);
239 tim 1826
240 tim 1884 rpab = rab[0] * pab[0] + rab[1] * pab[1] + rab[2] * pab[2];
241 tim 1826
242 tim 1884 rpabsq = rpab * rpab;
243 tim 1826
244 tim 1884 if (rpabsq < (rabsq * -diffsq)) {
245 tim 1826
246     #ifdef IS_MPI
247    
248 tim 1884 a = atoms[a]->getGlobalIndex();
249 tim 1826
250 tim 1884 b = atoms[b]->getGlobalIndex();
251 tim 1826
252     #endif //is_mpi
253    
254 tim 1884 //std::cerr << "Waring: constraint failure" << std::endl;
255 tim 1826
256 tim 1884 gab = sqrt(rabsq / pabsq);
257 tim 1826
258 tim 1884 rab[0] = (posA[0] - posB[0])
259     * gab;
260 tim 1826
261 tim 1884 rab[1] = (posA[1] - posB[1])
262     * gab;
263 tim 1826
264 tim 1884 rab[2] = (posA[2] - posB[2])
265     * gab;
266 tim 1826
267 tim 1884 info->wrapVector(rab);
268 tim 1826
269 tim 1884 rpab =
270     rab[0] * pab[0] + rab[1] * pab[1] + rab[2] * pab[2];
271     }
272 tim 1826
273 tim 1884 //rma = 1.0 / atoms[a]->getMass();
274 tim 1826
275 tim 1884 //rmb = 1.0 / atoms[b]->getMass();
276 tim 1826
277 tim 1884 rma = 1.0;
278 tim 1826
279 tim 1884 rmb = 1.0;
280 tim 1826
281 tim 1884 gab = diffsq / (2.0 * (rma + rmb) * rpab);
282 tim 1826
283 tim 1884 dx = rab[0]*
284     gab;
285 tim 1826
286 tim 1884 dy = rab[1]*
287     gab;
288 tim 1826
289 tim 1884 dz = rab[2]*
290     gab;
291 tim 1826
292 tim 1884 posA[0] += rma *dx;
293 tim 1826
294 tim 1884 posA[1] += rma *dy;
295 tim 1826
296 tim 1884 posA[2] += rma *dz;
297 tim 1826
298 tim 1884 atoms[a]->setPos(posA);
299 tim 1826
300 tim 1884 posB[0] -= rmb *dx;
301 tim 1826
302 tim 1884 posB[1] -= rmb *dy;
303 tim 1826
304 tim 1884 posB[2] -= rmb *dz;
305 tim 1826
306 tim 1884 atoms[b]->setPos(posB);
307 tim 1826
308 tim 1884 moving[a] = 1;
309 tim 1826
310 tim 1884 moving[b] = 1;
311 tim 1826
312 tim 1884 done = 0;
313     }
314     }
315     }
316 tim 1826
317 tim 1884 for(i = 0; i < nAtoms; i++) {
318     moved[i] = moving[i];
319 tim 1826
320 tim 1884 moving[i] = 0;
321 tim 1826 }
322    
323 tim 1884 iteration++;
324 tim 1826 }
325    
326 tim 1884 if (!done) {
327     std::cerr << "Waring: can not constraint within maxIteration"
328     << std::endl;
329 tim 1826
330 tim 1884 return -1;
331     } else
332     return 1;
333 tim 1826 }
334    
335     //remove constraint force along the bond direction
336    
337    
338 tim 1884 int OOPSEMinimizer::shakeF() {
339     int i, j;
340 tim 1826
341 tim 1884 int done;
342 tim 1826
343 tim 1884 double posA[3], posB[3];
344 tim 1826
345 tim 1884 double frcA[3], frcB[3];
346 tim 1826
347 tim 1884 double rab[3], fpab[3];
348 tim 1826
349 tim 1884 int a, b,
350     ax, ay,
351     az, bx,
352     by, bz;
353 tim 1826
354 tim 1884 double rma, rmb;
355 tim 1826
356 tim 1884 double rvab;
357 tim 1826
358 tim 1884 double gab;
359 tim 1826
360 tim 1884 double rabsq;
361 tim 1826
362 tim 1884 double rfab;
363 tim 1826
364 tim 1884 int iteration;
365 tim 1826
366 tim 1884 for(i = 0; i < nAtoms; i++) {
367     moving[i] = 0;
368 tim 1826
369 tim 1884 moved[i] = 1;
370     }
371 tim 1826
372 tim 1884 done = 0;
373 tim 1826
374 tim 1884 iteration = 0;
375 tim 1826
376 tim 1884 while (!done && (iteration < maxIteration)) {
377     done = 1;
378 tim 1826
379 tim 1884 for(i = 0; i < nConstrained; i++) {
380     a = constrainedA[i];
381 tim 1826
382 tim 1884 b = constrainedB[i];
383 tim 1826
384 tim 1884 ax = (a * 3) + 0;
385 tim 1826
386 tim 1884 ay = (a * 3) + 1;
387 tim 1826
388 tim 1884 az = (a * 3) + 2;
389 tim 1826
390 tim 1884 bx = (b * 3) + 0;
391 tim 1826
392 tim 1884 by = (b * 3) + 1;
393 tim 1826
394 tim 1884 bz = (b * 3) + 2;
395 tim 1826
396 tim 1884 if (moved[a] || moved[b]) {
397     posA = atoms[a]->getPos();
398 tim 1826
399 tim 1884 posB = atoms[b]->getPos();
400 tim 1826
401 tim 1884 for(j = 0; j < 3; j++)
402     rab[j] = posA[j] - posB[j];
403 tim 1826
404 tim 1884 info->wrapVector(rab);
405 tim 1826
406 tim 1884 atoms[a]->getFrc(frcA);
407 tim 1826
408 tim 1884 atoms[b]->getFrc(frcB);
409 tim 1826
410 tim 1884 //rma = 1.0 / atoms[a]->getMass();
411 tim 1826
412 tim 1884 //rmb = 1.0 / atoms[b]->getMass();
413 tim 1826
414 tim 1884 rma = 1.0;
415 tim 1826
416 tim 1884 rmb = 1.0;
417 tim 1826
418 tim 1884 fpab[0] = frcA[0] * rma - frcB[0] * rmb;
419 tim 1826
420 tim 1884 fpab[1] = frcA[1] * rma - frcB[1] * rmb;
421 tim 1826
422 tim 1884 fpab[2] = frcA[2] * rma - frcB[2] * rmb;
423 tim 1826
424 tim 1884 gab = fpab[0] * fpab[0] + fpab[1] * fpab[1] + fpab[2] * fpab[2];
425 tim 1826
426 tim 1884 if (gab < 1.0)
427     gab = 1.0;
428 tim 1826
429 tim 1884 rabsq = rab[0] * rab[0] + rab[1] * rab[1] + rab[2] * rab[2];
430 tim 1826
431 tim 1884 rfab = rab[0] * fpab[0] + rab[1] * fpab[1] + rab[2] * fpab[2];
432 tim 1826
433 tim 1884 if (fabs(rfab) > sqrt(rabsq*gab) * 0.00001) {
434     gab = -rfab / (rabsq * (rma + rmb));
435 tim 1826
436 tim 1884 frcA[0] = rab[0]*
437     gab;
438 tim 1826
439 tim 1884 frcA[1] = rab[1]*
440     gab;
441 tim 1826
442 tim 1884 frcA[2] = rab[2]*
443     gab;
444 tim 1826
445 tim 1884 atoms[a]->addFrc(frcA);
446 tim 1826
447 tim 1884 frcB[0] = -rab[0]*gab;
448 tim 1826
449 tim 1884 frcB[1] = -rab[1]*gab;
450 tim 1826
451 tim 1884 frcB[2] = -rab[2]*gab;
452 tim 1826
453 tim 1884 atoms[b]->addFrc(frcB);
454 tim 1826
455 tim 1884 moving[a] = 1;
456 tim 1826
457 tim 1884 moving[b] = 1;
458 tim 1826
459 tim 1884 done = 0;
460     }
461     }
462     }
463 tim 1826
464 tim 1884 for(i = 0; i < nAtoms; i++) {
465     moved[i] = moving[i];
466 tim 1826
467 tim 1884 moving[i] = 0;
468     }
469 tim 1826
470 tim 1884 iteration++;
471 tim 1826 }
472    
473 tim 1884 if (!done) {
474     std::cerr << "Waring: can not constraint within maxIteration"
475     << std::endl;
476 tim 1826
477 tim 1884 return -1;
478     } else
479     return 1;
480 tim 1826 }
481    
482 tim 1884 */
483    
484 tim 1826 //calculate the value of object function
485    
486 tim 1884 void OOPSEMinimizer::calcF() {
487     calcEnergyGradient(curX, curG, curF, egEvalStatus);
488 tim 1826 }
489    
490 tim 1884 void OOPSEMinimizer::calcF(std::vector < double > &x, double&f, int&status) {
491     std::vector < double > tempG;
492 tim 1826
493 tim 1884 tempG.resize(x.size());
494 tim 1826
495 tim 1884 calcEnergyGradient(x, tempG, f, status);
496 tim 1826 }
497    
498     //calculate the gradient
499    
500 tim 1884 void OOPSEMinimizer::calcG() {
501     calcEnergyGradient(curX, curG, curF, egEvalStatus);
502 tim 1826 }
503    
504 tim 1884 void OOPSEMinimizer::calcG(std::vector<double>& x, std::vector<double>& g, double&f, int&status) {
505     calcEnergyGradient(x, g, f, status);
506 tim 1826 }
507    
508 tim 1884 void OOPSEMinimizer::calcDim() {
509 tim 1826
510 tim 1884 SimInfo::MoleculeIterator i;
511     Molecule::IntegrableObjectIterator j;
512     Molecule* mol;
513     StuntDouble* integrableObject;
514     int ndim = 0;
515 tim 1826
516 tim 1884 for (mol = info->beginMolecule(i); mol != NULL; mol = info->nextMolecule(i)) {
517     for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
518     integrableObject = mol->nextIntegrableObject(j)) {
519 tim 1826
520 tim 1884 ndim += 3;
521 tim 1826
522 tim 1884 if (integrableObject->isDirectional()) {
523     ndim += 3;
524     }
525     }
526 tim 1826
527    
528     }
529    
530 tim 1884 void OOPSEMinimizer::setX(std::vector < double > &x) {
531     if (x.size() != ndim) {
532     sprintf(painCave.errMsg, "OOPSEMinimizer Error: dimesion of x and curX does not match\n");
533     painCave.isFatal = 1;
534     simError();
535 tim 1826 }
536    
537     curX = x;
538     }
539    
540 tim 1884 void OOPSEMinimizer::setG(std::vector < double > &g) {
541     if (g.size() != ndim) {
542     sprintf(painCave.errMsg, "OOPSEMinimizer Error: dimesion of g and curG does not match\n");
543     painCave.isFatal = 1;
544     simError();
545 tim 1826 }
546    
547     curG = g;
548     }
549    
550 tim 1884 void OOPSEMinimizer::writeOut(std::vector < double > &x, double iter) {
551     setX(x);
552 tim 1826
553 tim 1884 calcG();
554 tim 1826
555 tim 1884 dumpOut->writeDump(iter);
556 tim 1826
557 tim 1884 statOut->writeStat(iter);
558 tim 1826 }
559    
560 tim 1884 void OOPSEMinimizer::printMinimizerInfo() {
561     cout
562     << "--------------------------------------------------------------------"
563     << std::endl;
564 tim 1826
565 tim 1884 cout << minimizerName << std::endl;
566 tim 1826
567 tim 1884 cout << "minimization parameter set" << std::endl;
568 tim 1826
569 tim 1884 cout << "function tolerance = " << paramSet->getFTol() << std::endl;
570 tim 1826
571 tim 1884 cout << "gradient tolerance = " << paramSet->getGTol() << std::endl;
572 tim 1826
573 tim 1884 cout << "step tolerance = " << paramSet->getFTol() << std::endl;
574 tim 1826
575 tim 1884 cout << "absolute gradient tolerance = " << std::endl;
576 tim 1826
577 tim 1884 cout << "max iteration = " << paramSet->getMaxIteration() << std::endl;
578 tim 1826
579 tim 1884 cout << "max line search iteration = "
580     << paramSet->getLineSearchMaxIteration() << std::endl;
581 tim 1826
582 tim 1884 cout << "shake algorithm = " << bShake << std::endl;
583 tim 1826
584 tim 1884 cout
585     << "--------------------------------------------------------------------"
586     << std::endl;
587 tim 1826 }
588    
589     /**
590    
591     * In thoery, we need to find the minimum along the search direction
592     * However, function evaluation is too expensive.
593     * At the very begining of the problem, we check the search direction and make sure
594     * it is a descent direction
595     * we will compare the energy of two end points,
596     * if the right end point has lower energy, we just take it
597     */
598    
599 tim 1884 int OOPSEMinimizer::doLineSearch(std::vector<double> &direction,
600     double stepSize) {
601 tim 1826
602 tim 1884 std::vector<double> xa;
603     std::vector<double> xb;
604     std::vector<double> xc;
605     std::vector<double> ga;
606     std::vector<double> gb;
607     std::vector<double> gc;
608     double fa;
609     double fb;
610     double fc;
611     double a;
612     double b;
613     double c;
614     int status;
615     double initSlope;
616     double slopeA;
617     double slopeB;
618     double slopeC;
619     bool foundLower;
620     int iter;
621     int maxLSIter;
622     double mu;
623     double eta;
624     double ftol;
625     double lsTol;
626 tim 1826
627 tim 1884 xa.resize(ndim);
628     xb.resize(ndim);
629     xc.resize(ndim);
630     ga.resize(ndim);
631     gb.resize(ndim);
632     gc.resize(ndim);
633 tim 1826
634 tim 1884 a = 0.0;
635 tim 1826
636 tim 1884 fa = curF;
637 tim 1826
638 tim 1884 xa = curX;
639 tim 1826
640 tim 1884 ga = curG;
641 tim 1826
642 tim 1884 c = a + stepSize;
643 tim 1826
644 tim 1884 ftol = paramSet->getFTol();
645 tim 1826
646 tim 1884 lsTol = paramSet->getLineSearchTol();
647 tim 1826
648 tim 1884 //calculate the derivative at a = 0
649 tim 1826
650 tim 1884 slopeA = 0;
651 tim 1826
652 tim 1884 for(size_t i = 0; i < ndim; i++) {
653     slopeA += curG[i] * direction[i];
654     }
655    
656     initSlope = slopeA;
657 tim 1826
658 tim 1884 // if going uphill, use negative gradient as searching direction
659 tim 1826
660 tim 1884 if (slopeA > 0) {
661     if (bVerbose) {
662     cout
663     << "LineSearch Warning: initial searching direction is not a descent searching direction, " << " use negative gradient instead. Therefore, finding a smaller vaule of function " << " is guaranteed"
664     << std::endl;
665     }
666 tim 1826
667 tim 1884 for(size_t i = 0; i < ndim; i++) {
668     direction[i] = -curG[i];
669     }
670 tim 1826
671 tim 1884 for(size_t i = 0; i < ndim; i++) {
672     slopeA += curG[i] * direction[i];
673     }
674    
675     initSlope = slopeA;
676     }
677 tim 1826
678 tim 1884 // Take a trial step
679 tim 1826
680 tim 1884 for(size_t i = 0; i < ndim; i++) {
681     xc[i] = curX[i] + direction[i]* c;
682     }
683 tim 1826
684 tim 1884 calcG(xc, gc, fc, status);
685 tim 1826
686 tim 1884 if (status < 0) {
687 tim 1826 if (bVerbose)
688 tim 1884 std::cerr << "Function Evaluation Error" << std::endl;
689 tim 1826 }
690    
691 tim 1884 //calculate the derivative at c
692 tim 1826
693 tim 1884 slopeC = 0;
694 tim 1826
695 tim 1884 for(size_t i = 0; i < ndim; i++) {
696     slopeC += gc[i] * direction[i];
697 tim 1826 }
698 tim 1884 // found a lower point
699 tim 1826
700 tim 1884 if (fc < fa) {
701     curX = xc;
702 tim 1826
703 tim 1884 curG = gc;
704 tim 1826
705 tim 1884 curF = fc;
706 tim 1826
707 tim 1884 return LS_SUCCEED;
708     } else {
709     if (slopeC > 0)
710     stepSize *= 0.618034;
711 tim 1826 }
712    
713 tim 1884 maxLSIter = paramSet->getLineSearchMaxIteration();
714 tim 1826
715 tim 1884 iter = 0;
716 tim 1826
717 tim 1884 do {
718 tim 1826
719 tim 1884 // Select a new trial point.
720 tim 1826
721 tim 1884 // If the derivatives at points a & c have different sign we use cubic interpolate
722 tim 1826
723 tim 1884 //if (slopeC > 0){
724 tim 1826
725 tim 1884 eta = 3 * (fa - fc) / (c - a) + slopeA + slopeC;
726 tim 1826
727 tim 1884 mu = sqrt(eta * eta - slopeA * slopeC);
728 tim 1826
729 tim 1884 b = a + (c - a)
730     * (1 - (slopeC + mu - eta) / (slopeC - slopeA + 2 * mu));
731 tim 1826
732 tim 1884 if (b < lsTol) {
733     if (bVerbose)
734     cout << "stepSize is less than line search tolerance"
735     << std::endl;
736 tim 1826
737 tim 1884 break;
738     }
739 tim 1826
740 tim 1884 //}
741 tim 1826
742 tim 1884 // Take a trial step to this new point - new coords in xb
743 tim 1826
744 tim 1884 for(size_t i = 0; i < ndim; i++) {
745     xb[i] = curX[i] + direction[i]* b;
746     }
747    
748     //function evaluation
749 tim 1826
750 tim 1884 calcG(xb, gb, fb, status);
751 tim 1826
752 tim 1884 if (status < 0) {
753     if (bVerbose)
754     std::cerr << "Function Evaluation Error" << std::endl;
755     }
756 tim 1826
757 tim 1884 //calculate the derivative at c
758 tim 1826
759 tim 1884 slopeB = 0;
760 tim 1826
761 tim 1884 for(size_t i = 0; i < ndim; i++) {
762     slopeB += gb[i] * direction[i];
763     }
764    
765     //Amijo Rule to stop the line search
766 tim 1826
767 tim 1884 if (fb <= curF + initSlope * ftol * b) {
768     curF = fb;
769 tim 1826
770 tim 1884 curX = xb;
771 tim 1826
772 tim 1884 curG = gb;
773 tim 1826
774 tim 1884 return LS_SUCCEED;
775     }
776 tim 1826
777 tim 1884 if (slopeB < 0 && fb < fa) {
778 tim 1826
779 tim 1884 //replace a by b
780 tim 1826
781 tim 1884 fa = fb;
782 tim 1826
783 tim 1884 a = b;
784 tim 1826
785 tim 1884 slopeA = slopeB;
786 tim 1826
787 tim 1884 // swap coord a/b
788 tim 1826
789 tim 1884 std::swap(xa, xb);
790 tim 1826
791 tim 1884 std::swap(ga, gb);
792     } else {
793 tim 1826
794 tim 1884 //replace c by b
795 tim 1826
796 tim 1884 fc = fb;
797 tim 1826
798 tim 1884 c = b;
799 tim 1826
800 tim 1884 slopeC = slopeB;
801 tim 1826
802 tim 1884 // swap coord b/c
803 tim 1826
804 tim 1884 std::swap(gb, gc);
805 tim 1826
806 tim 1884 std::swap(xb, xc);
807     }
808 tim 1826
809 tim 1884 iter++;
810     } while ((fb > fa || fb > fc) && (iter < maxLSIter));
811 tim 1826
812 tim 1884 if (fb < curF || iter >= maxLSIter) {
813 tim 1826
814 tim 1884 //could not find a lower value, we might just go uphill.
815 tim 1826
816 tim 1884 return LS_ERROR;
817     }
818 tim 1826
819 tim 1884 //select the end point
820 tim 1826
821 tim 1884 if (fa <= fc) {
822     curX = xa;
823 tim 1826
824 tim 1884 curG = ga;
825 tim 1826
826 tim 1884 curF = fa;
827     } else {
828     curX = xc;
829 tim 1826
830 tim 1884 curG = gc;
831 tim 1826
832 tim 1884 curF = fc;
833     }
834 tim 1826
835 tim 1884 return LS_SUCCEED;
836     }
837 tim 1826
838 tim 1884 void OOPSEMinimizer::minimize() {
839     int convgStatus;
840 tim 1826
841 tim 1884 int stepStatus;
842 tim 1826
843 tim 1884 int maxIter;
844 tim 1826
845 tim 1884 int writeFrq;
846 tim 1826
847 tim 1884 int nextWriteIter;
848 tim 1826
849 tim 1884 if (bVerbose)
850     printMinimizerInfo();
851 tim 1826
852 tim 1884 dumpOut = new DumpWriter(info);
853 tim 1826
854 tim 1884 statOut = new StatWriter(info);
855 tim 1826
856 tim 1884 init();
857 tim 1826
858 tim 1884 writeFrq = paramSet->getWriteFrq();
859 tim 1826
860 tim 1884 nextWriteIter = writeFrq;
861 tim 1826
862 tim 1884 maxIter = paramSet->getMaxIteration();
863 tim 1826
864 tim 1884 for(curIter = 1; curIter <= maxIter; curIter++) {
865     stepStatus = step();
866 tim 1826
867 tim 1884 if (nConstrained && bShake)
868     preMove();
869 tim 1826
870 tim 1884 if (stepStatus < 0) {
871     saveResult();
872 tim 1826
873 tim 1884 minStatus = MIN_LSERROR;
874 tim 1826
875 tim 1884 std::cerr
876     << "OOPSEMinimizer Error: line search error, please try a small stepsize"
877     << std::endl;
878 tim 1826
879 tim 1884 return;
880     }
881 tim 1826
882 tim 1884 if (curIter == nextWriteIter) {
883     nextWriteIter += writeFrq;
884 tim 1826
885 tim 1884 writeOut(curX, curIter);
886     }
887 tim 1826
888 tim 1884 convgStatus = checkConvg();
889 tim 1826
890 tim 1884 if (convgStatus > 0) {
891     saveResult();
892 tim 1826
893 tim 1884 minStatus = MIN_CONVERGE;
894 tim 1826
895 tim 1884 return;
896     }
897 tim 1826
898 tim 1884 prepareStep();
899 tim 1826 }
900    
901 tim 1884 if (bVerbose) {
902     cout << "OOPSEMinimizer Warning: " << minimizerName
903     << " algorithm did not converge within " << maxIter << " iteration"
904     << std::endl;
905 tim 1826 }
906    
907 tim 1884 minStatus = MIN_MAXITER;
908 tim 1826
909 tim 1884 saveResult();
910     }
911 tim 1826
912     }

Properties

Name Value
svn:executable *