ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/minimizers/Minimizer.cpp
Revision: 1902
Committed: Wed Jan 5 17:35:19 2005 UTC (19 years, 7 months ago) by tim
File size: 18984 byte(s)
Log Message:
minimizer in progress

File Contents

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

Properties

Name Value
svn:executable *