ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/minimizers/Minimizer.cpp
Revision: 1744
Committed: Tue Jun 5 18:07:08 2012 UTC (12 years, 10 months ago) by gezelter
File size: 19081 byte(s)
Log Message:
Fixes for minimization

File Contents

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

Properties

Name Value
svn:executable *
svn:keywords Author Id Revision Date