ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/minimizers/Minimizer.cpp
Revision: 1627
Committed: Tue Sep 13 22:05:04 2011 UTC (13 years, 7 months ago) by gezelter
File size: 18470 byte(s)
Log Message:
Splitting out ifstrstream into a header and an implementation.  This
means that much of the code that depends on it can be compiled only
once and the parallel I/O is concentrated into a few files.  To do
this, a number of files that relied on basic_ifstrstream to load the
mpi header had to be modified to manage their own headers.


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

Properties

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