Changes in src/Dynamics/ForceAnnealing.hpp [4b2adf:0682c2]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Dynamics/ForceAnnealing.hpp
r4b2adf r0682c2 17 17 #include <functional> 18 18 #include <iterator> 19 #include <math.h> 19 20 20 21 #include <boost/bind.hpp> … … 167 168 { 168 169 double stepwidth = 0.; 169 if (_GradientDifference.Norm Squared() > MYEPSILON)170 if (_GradientDifference.Norm() > MYEPSILON) 170 171 stepwidth = fabs(_PositionDifference.ScalarProduct(_GradientDifference))/ 171 172 _GradientDifference.NormSquared(); … … 176 177 stepwidth = currentDeltat; 177 178 } 178 return st epwidth;179 return std::min(1., stepwidth); 179 180 } 180 181 … … 200 201 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 201 202 // atom's force vector gives steepest descent direction 202 const Vector currentPosition = (*iter)->getPositionAtStep(CurrentTimeStep);203 const Vector currentGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep);203 const Vector ¤tPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 204 const Vector ¤tGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 204 205 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition); 205 206 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient); … … 248 249 } 249 250 251 /** Performs Gradient optimization on a single atom using BarzilaiBorwein step width. 252 * 253 * \param _atom atom to anneal 254 * \param OldTimeStep old time step 255 * \param CurrentTimeStep current time step whose gradient we've just calculated 256 * \param TimeStepToSet time step to update (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet) 257 */ 258 void annealAtom_BarzilaiBorwein( 259 atom * const _atom, 260 const int &OldTimeStep, 261 const int &CurrentTimeStep, 262 const int &TimeStepToSet 263 ) 264 { 265 // atom's force vector gives steepest descent direction 266 const Vector &oldPosition = _atom->getPositionAtStep(OldTimeStep); 267 const Vector ¤tPosition = _atom->getPositionAtStep(CurrentTimeStep); 268 const Vector &oldGradient = _atom->getAtomicForceAtStep(OldTimeStep); 269 const Vector ¤tGradient = _atom->getAtomicForceAtStep(CurrentTimeStep); 270 LOG(4, "DEBUG: oldPosition for atom #" << _atom->getId() << " is " << oldPosition); 271 LOG(4, "DEBUG: currentPosition for atom #" << _atom->getId() << " is " << currentPosition); 272 LOG(4, "DEBUG: oldGradient for atom #" << _atom->getId() << " is " << oldGradient); 273 LOG(4, "DEBUG: currentGradient for atom #" << _atom->getId() << " is " << currentGradient); 274 // LOG(4, "DEBUG: Force for atom #" << _atom->getId() << " is " << currentGradient); 275 276 // we use Barzilai-Borwein update with position reversed to get descent 277 const Vector PositionDifference = currentPosition - oldPosition; 278 const Vector GradientDifference = (currentGradient - oldGradient); 279 double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference); 280 Vector PositionUpdate = stepwidth * currentGradient; 281 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); 282 283 // finally set new values 284 _atom->setPositionAtStep(TimeStepToSet, currentPosition + PositionUpdate); 285 } 286 250 287 /** Performs Gradient optimization on the atoms using BarzilaiBorwein step width. 251 288 * 252 289 * \note this can only be called when there are at least two optimization 253 * time steps present, i.e. this must be prece eded by a simple anneal().290 * time steps present, i.e. this must be preceded by a simple anneal(). 254 291 * 255 292 * We assume that forces have just been calculated. … … 271 308 272 309 Vector maxComponents; 273 bool deltat_decreased = false;274 310 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); 275 311 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { 276 // atom's force vector gives steepest descent direction 277 const Vector &oldPosition = (*iter)->getPositionAtStep(OldTimeStep);278 const Vector ¤tPosition = (*iter)->getPositionAtStep(CurrentTimeStep); 279 const Vector &oldGradient = (*iter)->getAtomicForceAtStep(OldTimeStep);312 313 annealAtom_BarzilaiBorwein(*iter, OldTimeStep, CurrentTimeStep, _TimeStep); 314 315 // extract largest components for showing progress of annealing 280 316 const Vector ¤tGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep); 281 LOG(4, "DEBUG: oldPosition for atom #" << (*iter)->getId() << " is " << oldPosition);282 LOG(4, "DEBUG: currentPosition for atom #" << (*iter)->getId() << " is " << currentPosition);283 LOG(4, "DEBUG: oldGradient for atom #" << (*iter)->getId() << " is " << oldGradient);284 LOG(4, "DEBUG: currentGradient for atom #" << (*iter)->getId() << " is " << currentGradient);285 // LOG(4, "DEBUG: Force for atom #" << (*iter)->getId() << " is " << currentGradient);286 287 // we use Barzilai-Borwein update with position reversed to get descent288 const Vector PositionDifference = currentPosition - oldPosition;289 const Vector GradientDifference = (currentGradient - oldGradient);290 double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference);291 Vector PositionUpdate = stepwidth * currentGradient;292 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);293 294 // extract largest components for showing progress of annealing295 317 for(size_t i=0;i<NDIM;++i) 296 318 maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i])); 297 298 // // steps may go back and forth again (updates are of same magnitude but299 // // have different sign: Check whether this is the case and one step with300 // // deltat to interrupt this sequence301 // if (!PositionDifference.IsZero())302 // if ((PositionUpdate.ScalarProduct(PositionDifference) < 0)303 // && (fabs(PositionUpdate.NormSquared()-PositionDifference.NormSquared()) < 1e-3)) {304 // // for convergence we want a null sequence here, too305 // if (!deltat_decreased) {306 // deltat_decreased = true;307 // currentDeltat = .5*currentDeltat;308 // }309 // LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate310 // << " > " << PositionDifference311 // << ", using deltat: " << currentDeltat);312 // PositionUpdate = currentDeltat * currentGradient;313 // }314 315 // finally set new values316 (*iter)->setPositionAtStep(_TimeStep, currentPosition + PositionUpdate);317 319 } 318 320 319 321 return maxComponents; 320 322 } 323 324 /** Helper function to insert \a PositionUpdate into a map for every atom. 325 * 326 * \param _GatheredUpdates map of updates per atom 327 * \param _LargestUpdate_per_Atom map with the largest update per atom for checking 328 * \param _atomno key for map 329 * \param _PositionUpdate update to add 330 * \param _factor optional dampening factor 331 */ 332 void updateInserter( 333 std::map<atomId_t, Vector> &_GatheredUpdates, 334 std::map<atomId_t, double> &_LargestUpdate_per_Atom, 335 const atomId_t _atomno, 336 const Vector &_PositionUpdate, 337 const double _factor = 1. 338 ) 339 { 340 if (_GatheredUpdates.count(_atomno)) { 341 _GatheredUpdates[_atomno] += _factor*_PositionUpdate; 342 _LargestUpdate_per_Atom[_atomno] = 343 std::max(_LargestUpdate_per_Atom[_atomno], _factor*_PositionUpdate.Norm()); 344 } else { 345 _GatheredUpdates.insert( 346 std::make_pair( 347 _atomno, 348 _factor*_PositionUpdate) ); 349 _LargestUpdate_per_Atom.insert( 350 std::make_pair( 351 _atomno, 352 _PositionUpdate.Norm()) ); 353 } 354 } 321 355 322 356 /** Performs Gradient optimization on the bonds with BarzilaiBorwein stepwdith. … … 416 450 417 451 std::map<atomId_t, Vector> GatheredUpdates; //!< gathers all updates which are applied at the end 452 std::map<atomId_t, double> LargestUpdate_per_Atom; //!< check whether updates cancelled each other 418 453 for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin(); 419 454 iter != AtomicForceManipulator<T>::atoms.end(); ++iter) { … … 434 469 const Vector PositionDifference = currentPosition - oldPosition; 435 470 const Vector GradientDifference = (currentGradient - oldGradient); 436 double stepwidth = 0.; 437 if (GradientDifference.Norm() > MYEPSILON) 438 stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/ 439 GradientDifference.NormSquared(); 440 if (fabs(stepwidth) < 1e-10) { 441 // dont' warn in first step, deltat usage normal 442 if (currentStep != 1) 443 ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead."); 444 stepwidth = currentDeltat; 445 } 471 double stepwidth = getBarzilaiBorweinStepwidth(PositionDifference, GradientDifference); 446 472 Vector PositionUpdate = stepwidth * currentGradient; 473 // cap updates (if non-zero) at 0.2 angstroem. BB tends to overshoot. 474 for (size_t i=0;i<NDIM;++i) 475 if (fabs(PositionUpdate[i]) > MYEPSILON) 476 PositionUpdate[i] = std::min(0.2, fabs(PositionUpdate[i]))*PositionUpdate[i]/fabs(PositionUpdate[i]); 447 477 LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate); 448 478 449 /** for each atom, we imagine a plane at the position of the atom with 450 * its atomic gradient as the normal vector. We go through all its bonds 451 * and check on which side of the plane the bond is. This defines whether 452 * the bond is contracting (+) or expanding (-) with respect to this atom. 453 * 454 * A bond has two atoms, however. Hence, we do this for either atom and 455 * look at the combination: Is it in sum contracting or expanding given 456 * both projected_forces? 457 */ 458 459 /** go through all bonds and check projected_forces and side of plane 460 * the idea is that if all bonds on one side are contracting ones or expanding, 461 * respectively, then we may shift not only the atom with respect to its 462 * gradient but also its neighbors (towards contraction or towards 463 * expansion depending on direction of gradient). 464 * if they are mixed on both sides of the plane, then we simply shift 465 * only the atom itself. 466 * if they are not mixed on either side, then we also only shift the 467 * atom, namely away from expanding and towards contracting bonds. 468 * 469 * We may get this information right away by looking at the projected_forces. 470 * They give the atomic gradient of either atom projected onto the BondVector 471 * with an additional weight in [0,1]. 472 */ 473 474 // sign encodes side of plane and also encodes contracting(-) or expanding(+) 475 typedef std::vector<int> sides_t; 476 typedef std::vector<int> types_t; 477 sides_t sides; 478 types_t types; 479 const BondList& ListOfBonds = walker.getListOfBonds(); 480 for(BondList::const_iterator bonditer = ListOfBonds.begin(); 481 bonditer != ListOfBonds.end(); ++bonditer) { 482 const bond::ptr ¤t_bond = *bonditer; 483 484 // BondVector goes from bond::rightatom to bond::leftatom 485 const size_t index = bv.getIndexForBond(current_bond); 486 std::vector<double> &forcelist = (&walker == current_bond->leftatom) ? 487 projected_forces[BondVectors::leftside] : projected_forces[BondVectors::rightside]; 488 // note that projected_forces has sign such as to indicate whether 489 // atomic gradient wants bond to contract (-) or expand (+). 490 // This goes into sides: Minus side points away from gradient, plus side point 491 // towards gradient. 492 // 493 // the sum of both bond sides goes into types, depending on which is 494 // stronger if either wants a different thing 495 const double &temp = forcelist[index]; 496 sides.push_back( -1.*temp/fabs(temp) ); // BondVectors has exactly opposite sign for sides decision 497 const double sum = 498 projected_forces[BondVectors::leftside][index]+projected_forces[BondVectors::rightside][index]; 499 types.push_back( sum/fabs(sum) ); 500 LOG(4, "DEBUG: Bond " << *current_bond << " is on side " << sides.back() 501 << " and has type " << types.back()); 502 } 503 // /// check whether both conditions are compatible: 504 // // i.e. either we have ++/-- for all entries in sides and types 505 // // or we have +-/-+ for all entries 506 // // hence, multiplying and taking the sum and its absolute value 507 // // should be equal to the maximum number of entries 508 // sides_t results; 509 // std::transform( 510 // sides.begin(), sides.end(), 511 // types.begin(), 512 // std::back_inserter(results), 513 // std::multiplies<int>); 514 // int result = abs(std::accumulate(results.begin(), results.end(), 0, std::plus<int>)); 515 516 std::vector<size_t> first_per_side(2, (size_t)-1); //!< mark down one representative from either side 517 std::vector< std::vector<int> > types_per_side(2); //!< gather all types on each side 518 types_t::const_iterator typesiter = types.begin(); 519 for (sides_t::const_iterator sidesiter = sides.begin(); 520 sidesiter != sides.end(); ++sidesiter, ++typesiter) { 521 const size_t index = (*sidesiter+1)/2; 522 types_per_side[index].push_back(*typesiter); 523 if (first_per_side[index] == (size_t)-1) 524 first_per_side[index] = std::distance(const_cast<const sides_t &>(sides).begin(), sidesiter); 525 } 526 LOG(4, "DEBUG: First on side minus is " << first_per_side[0] << ", and first on side plus is " 527 << first_per_side[1]); 528 //!> enumerate types per side with a little witching with the numbers to allow easy setting from types 529 enum whichtypes_t { 530 contracting=0, 531 unset=1, 532 expanding=2, 533 mixed 534 }; 535 std::vector<int> typeside(2, unset); 536 for(size_t i=0;i<2;++i) { 537 for (std::vector<int>::const_iterator tpsiter = types_per_side[i].begin(); 538 tpsiter != types_per_side[i].end(); ++tpsiter) { 539 if (typeside[i] == unset) { 540 typeside[i] = *tpsiter+1; //contracting(0) or expanding(2) 541 } else { 542 if (typeside[i] != (*tpsiter+1)) // no longer he same type 543 typeside[i] = mixed; 479 if (walker.getElementNo() != 1) { 480 /** for each atom, we imagine a plane at the position of the atom with 481 * its atomic gradient as the normal vector. We go through all its bonds 482 * and check on which side of the plane the bond is. This defines whether 483 * the bond is contracting (+) or expanding (-) with respect to this atom. 484 * 485 * A bond has two atoms, however. Hence, we do this for either atom and 486 * look at the combination: Is it in sum contracting or expanding given 487 * both projected_forces? 488 */ 489 490 /** go through all bonds and check projected_forces and side of plane 491 * the idea is that if all bonds on one side are contracting ones or expanding, 492 * respectively, then we may shift not only the atom with respect to its 493 * gradient but also its neighbors (towards contraction or towards 494 * expansion depending on direction of gradient). 495 * if they are mixed on both sides of the plane, then we simply shift 496 * only the atom itself. 497 * if they are not mixed on either side, then we also only shift the 498 * atom, namely away from expanding and towards contracting bonds. 499 * 500 * We may get this information right away by looking at the projected_forces. 501 * They give the atomic gradient of either atom projected onto the BondVector 502 * with an additional weight in [0,1]. 503 */ 504 505 // sign encodes side of plane and also encodes contracting(-) or expanding(+) 506 typedef std::vector<int> sides_t; 507 typedef std::vector<int> types_t; 508 sides_t sides; 509 types_t types; 510 const BondList& ListOfBonds = walker.getListOfBonds(); 511 for(BondList::const_iterator bonditer = ListOfBonds.begin(); 512 bonditer != ListOfBonds.end(); ++bonditer) { 513 const bond::ptr ¤t_bond = *bonditer; 514 515 // BondVector goes from bond::rightatom to bond::leftatom 516 const size_t index = bv.getIndexForBond(current_bond); 517 std::vector<double> &forcelist = (&walker == current_bond->leftatom) ? 518 projected_forces[BondVectors::leftside] : projected_forces[BondVectors::rightside]; 519 // note that projected_forces has sign such as to indicate whether 520 // atomic gradient wants bond to contract (-) or expand (+). 521 // This goes into sides: Minus side points away from gradient, plus side point 522 // towards gradient. 523 // 524 // the sum of both bond sides goes into types, depending on which is 525 // stronger if either wants a different thing 526 const double &temp = forcelist[index]; 527 if (fabs(temp) < MYEPSILON) 528 sides.push_back(1); 529 else 530 sides.push_back( -1.*temp/fabs(temp) ); // BondVectors has exactly opposite sign for sides decision 531 ASSERT( (sides.back() == 1) || (sides.back() == -1), 532 "ForceAnnealing() - sides is not in {-1,1}."); 533 const double sum = 534 projected_forces[BondVectors::leftside][index]+projected_forces[BondVectors::rightside][index]; 535 types.push_back( sum/fabs(sum) ); 536 LOG(4, "DEBUG: Bond " << *current_bond << " is on side " << sides.back() 537 << " and has type " << types.back()); 538 } 539 // /// check whether both conditions are compatible: 540 // // i.e. either we have ++/-- for all entries in sides and types 541 // // or we have +-/-+ for all entries 542 // // hence, multiplying and taking the sum and its absolute value 543 // // should be equal to the maximum number of entries 544 // sides_t results; 545 // std::transform( 546 // sides.begin(), sides.end(), 547 // types.begin(), 548 // std::back_inserter(results), 549 // std::multiplies<int>); 550 // int result = abs(std::accumulate(results.begin(), results.end(), 0, std::plus<int>)); 551 552 std::vector<size_t> first_per_side(2, (size_t)-1); //!< mark down one representative from either side 553 std::vector< std::vector<int> > types_per_side(2); //!< gather all types on each side 554 types_t::const_iterator typesiter = types.begin(); 555 for (sides_t::const_iterator sidesiter = sides.begin(); 556 sidesiter != sides.end(); ++sidesiter, ++typesiter) { 557 const size_t index = (*sidesiter+1)/2; 558 types_per_side[index].push_back(*typesiter); 559 if (first_per_side[index] == (size_t)-1) 560 first_per_side[index] = std::distance(const_cast<const sides_t &>(sides).begin(), sidesiter); 561 } 562 LOG(4, "DEBUG: First on side minus is " << first_per_side[0] << ", and first on side plus is " 563 << first_per_side[1]); 564 //!> enumerate types per side with a little witching with the numbers to allow easy setting from types 565 enum whichtypes_t { 566 contracting=0, 567 unset=1, 568 expanding=2, 569 mixed 570 }; 571 std::vector<int> typeside(2, unset); 572 for(size_t i=0;i<2;++i) { 573 for (std::vector<int>::const_iterator tpsiter = types_per_side[i].begin(); 574 tpsiter != types_per_side[i].end(); ++tpsiter) { 575 if (typeside[i] == unset) { 576 typeside[i] = *tpsiter+1; //contracting(0) or expanding(2) 577 } else { 578 if (typeside[i] != (*tpsiter+1)) // no longer he same type 579 typeside[i] = mixed; 580 } 544 581 } 545 582 } 546 } 547 LOG(4, "DEBUG: Minus side is " << typeside[0] << " and plus side is " << typeside[1]); 548 549 typedef std::vector< std::pair<atomId_t, atomId_t> > RemovedEdges_t; 550 if ((typeside[0] != mixed) || (typeside[1] != mixed)) { 551 const size_t sideno = ((typeside[0] != mixed) && (typeside[0] != unset)) ? 0 : 1; 552 LOG(4, "DEBUG: Chosen side is " << sideno << " with type " << typeside[sideno]); 553 ASSERT( (typeside[sideno] == contracting) || (typeside[sideno] == expanding), 554 "annealWithBondGraph_BB() - chosen side is neither expanding nor contracting."); 555 // one side is not mixed, all bonds on one side are of same type 556 // hence, find out which bonds to exclude 557 const BondList& ListOfBonds = walker.getListOfBonds(); 558 559 // sideno is away (0) or in direction (1) of gradient 560 // tpyes[first_per_side[sideno]] is either contracting (-1) or expanding (+1) 561 // : side (i), where (i) means which bonds we keep for the BFS, bonds 562 // on side (-i) are removed 563 // If all bonds on side away (0) want expansion (+1), move towards side with atom: side 1 564 // if all bonds side towards (1) want contraction (-1), move away side with atom : side -1 565 566 // unsure whether this or do nothing in the remaining cases: 567 // If all bonds on side toward (1) want expansion (+1), move away side with atom : side -1 568 // (the reasoning is that the bond's other atom must have a stronger 569 // gradient in the same direction and they push along atoms in 570 // gradient direction: we don't want to interface with those. 571 // Hence, move atoms along on away side 572 // if all bonds side away (0) want contraction (-1), move towards side with atom: side 1 573 // (the reasoning is the same, don't interfere with update from 574 // stronger gradient) 575 // hence, the decision is only based on sides once we have picked a side 576 // depending on all bonds associated with have same good type. 577 const double sign = sides[first_per_side[sideno]]; 578 LOG(4, "DEBUG: Removing edges from side with sign " << sign); 579 BondList::const_iterator bonditer = ListOfBonds.begin(); 580 RemovedEdges_t RemovedEdges; 581 for (sides_t::const_iterator sidesiter = sides.begin(); 582 sidesiter != sides.end(); ++sidesiter, ++bonditer) { 583 if (*sidesiter == sign) { 584 // remove the edge 585 const bond::ptr ¤t_bond = *bonditer; 586 LOG(5, "DEBUG: Removing edge " << *current_bond); 587 RemovedEdges.push_back( std::make_pair( 588 current_bond->leftatom->getId(), 589 current_bond->rightatom->getId()) 590 ); 591 #ifndef NDEBUG 592 const bool status = 593 #endif 594 BGcreator.removeEdge(RemovedEdges.back()); 595 ASSERT( status, "ForceAnnealing() - edge to found bond is not present?"); 583 LOG(4, "DEBUG: Minus side is " << typeside[0] << " and plus side is " << typeside[1]); 584 585 typedef std::vector< std::pair<atomId_t, atomId_t> > RemovedEdges_t; 586 if ((typeside[0] != mixed) || (typeside[1] != mixed)) { 587 const size_t sideno = ((typeside[0] != mixed) && (typeside[0] != unset)) ? 0 : 1; 588 LOG(4, "DEBUG: Chosen side is " << sideno << " with type " << typeside[sideno]); 589 ASSERT( (typeside[sideno] == contracting) || (typeside[sideno] == expanding), 590 "annealWithBondGraph_BB() - chosen side is neither expanding nor contracting."); 591 // one side is not mixed, all bonds on one side are of same type 592 // hence, find out which bonds to exclude 593 const BondList& ListOfBonds = walker.getListOfBonds(); 594 595 // sideno is away (0) or in direction (1) of gradient 596 // tpyes[first_per_side[sideno]] is either contracting (-1) or expanding (+1) 597 // : side (i), where (i) means which bonds we keep for the BFS, bonds 598 // on side (-i) are removed 599 // If all bonds on side away (0) want expansion (+1), move towards side with atom: side 1 600 // if all bonds side towards (1) want contraction (-1), move away side with atom : side -1 601 602 // unsure whether this or do nothing in the remaining cases: 603 // If all bonds on side toward (1) want expansion (+1), move away side with atom : side -1 604 // (the reasoning is that the bond's other atom must have a stronger 605 // gradient in the same direction and they push along atoms in 606 // gradient direction: we don't want to interface with those. 607 // Hence, move atoms along on away side 608 // if all bonds side away (0) want contraction (-1), move towards side with atom: side 1 609 // (the reasoning is the same, don't interfere with update from 610 // stronger gradient) 611 // hence, the decision is only based on sides once we have picked a side 612 // depending on all bonds associated with have same good type. 613 614 // away from gradient (minus) and contracting 615 // or towards gradient (plus) and expanding 616 // gather all on same side and remove 617 const double sign = 618 (sides[first_per_side[sideno]] == types[first_per_side[sideno]]) 619 ? sides[first_per_side[sideno]] : -1.*sides[first_per_side[sideno]]; 620 621 LOG(4, "DEBUG: Removing edges from side with sign " << sign); 622 BondList::const_iterator bonditer = ListOfBonds.begin(); 623 RemovedEdges_t RemovedEdges; 624 for (sides_t::const_iterator sidesiter = sides.begin(); 625 sidesiter != sides.end(); ++sidesiter, ++bonditer) { 626 if (*sidesiter == sign) { 627 // remove the edge 628 const bond::ptr ¤t_bond = *bonditer; 629 LOG(5, "DEBUG: Removing edge " << *current_bond); 630 RemovedEdges.push_back( std::make_pair( 631 current_bond->leftatom->getId(), 632 current_bond->rightatom->getId()) 633 ); 634 #ifndef NDEBUG 635 const bool status = 636 #endif 637 BGcreator.removeEdge(RemovedEdges.back()); 638 ASSERT( status, "ForceAnnealing() - edge to found bond is not present?"); 639 } 596 640 } 597 } 598 // perform limited-horizon BFS 599 BoostGraphHelpers::Nodeset_t bondside_set; 600 BreadthFirstSearchGatherer::distance_map_t distance_map; 601 bondside_set = NodeGatherer(walker.getId(), max_distance); 602 distance_map = NodeGatherer.getDistances(); 603 std::sort(bondside_set.begin(), bondside_set.end()); 604 605 // re-add edge 606 for (RemovedEdges_t::const_iterator edgeiter = RemovedEdges.begin(); 607 edgeiter != RemovedEdges.end(); ++edgeiter) 608 BGcreator.addEdge(edgeiter->first, edgeiter->second); 609 610 // update position with dampening factor on the discovered bonds 611 for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin(); 612 setiter != bondside_set.end(); ++setiter) { 613 const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter 614 = distance_map.find(*setiter); 615 ASSERT( diter != distance_map.end(), 616 "ForceAnnealing() - could not find distance to an atom."); 617 const double factor = pow(damping_factor, diter->second+1); 618 LOG(3, "DEBUG: Update for atom #" << *setiter << " will be " 619 << factor << "*" << PositionUpdate); 620 if (GatheredUpdates.count((*setiter))) { 621 GatheredUpdates[(*setiter)] += factor*PositionUpdate; 622 } else { 623 GatheredUpdates.insert( 624 std::make_pair( 625 (*setiter), 626 factor*PositionUpdate) ); 641 // perform limited-horizon BFS 642 BoostGraphHelpers::Nodeset_t bondside_set; 643 BreadthFirstSearchGatherer::distance_map_t distance_map; 644 bondside_set = NodeGatherer(walker.getId(), max_distance); 645 distance_map = NodeGatherer.getDistances(); 646 std::sort(bondside_set.begin(), bondside_set.end()); 647 648 // re-add edge 649 for (RemovedEdges_t::const_iterator edgeiter = RemovedEdges.begin(); 650 edgeiter != RemovedEdges.end(); ++edgeiter) 651 BGcreator.addEdge(edgeiter->first, edgeiter->second); 652 653 // update position with dampening factor on the discovered bonds 654 for (BoostGraphHelpers::Nodeset_t::const_iterator setiter = bondside_set.begin(); 655 setiter != bondside_set.end(); ++setiter) { 656 const BreadthFirstSearchGatherer::distance_map_t::const_iterator diter 657 = distance_map.find(*setiter); 658 ASSERT( diter != distance_map.end(), 659 "ForceAnnealing() - could not find distance to an atom."); 660 const double factor = pow(damping_factor, diter->second+1); 661 LOG(3, "DEBUG: Update for atom #" << *setiter << " will be " 662 << factor << "*" << PositionUpdate); 663 updateInserter(GatheredUpdates, LargestUpdate_per_Atom, *setiter, PositionUpdate, factor); 627 664 } 665 } else { 666 // simple atomic annealing, i.e. damping factor of 1 667 updateInserter(GatheredUpdates, LargestUpdate_per_Atom, walker.getId(), PositionUpdate); 628 668 } 629 669 } else { 630 // simple atomic annealing, i.e. damping factor of 1 631 LOG(3, "DEBUG: Update for atom #" << walker.getId() << " will be " << PositionUpdate); 632 GatheredUpdates.insert( 633 std::make_pair( 634 walker.getId(), 635 PositionUpdate) ); 670 // hydrogens (are light-weighted and therefore) are always updated normally 671 LOG(3, "DEBUG: Update for hydrogen #" << walker.getId() << " will be " << PositionUpdate); 672 updateInserter(GatheredUpdates, LargestUpdate_per_Atom, walker.getId(), PositionUpdate); 636 673 } 637 674 } … … 641 678 atom &walker = *(*iter); 642 679 // extract largest components for showing progress of annealing 643 const Vector currentGradient = walker.getAtomicForceAtStep(CurrentTimeStep);680 const Vector ¤tGradient = walker.getAtomicForceAtStep(CurrentTimeStep); 644 681 for(size_t i=0;i<NDIM;++i) 645 682 maxComponents[i] = std::max(maxComponents[i], fabs(currentGradient[i])); … … 670 707 for (size_t i=0;i<NDIM;++i) 671 708 LargestUpdate[i] = std::max(LargestUpdate[i], fabs(update[i])); 672 walker->setPositionAtStep(_TimeStep, 673 walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation); 709 710 std::map<atomId_t, double>::const_iterator largestiter = LargestUpdate_per_Atom.find(atomid); 711 ASSERT( largestiter != LargestUpdate_per_Atom.end(), 712 "ForceAnnealing() - walker with id "+toString(atomid)+" not in LargestUpdates."); 713 // if we had large updates but their sum is very small 714 if (update.Norm()/largestiter->second > MYEPSILON) { 715 walker->setPositionAtStep(_TimeStep, 716 walker->getPositionAtStep(CurrentTimeStep) + update); // - CommonTranslation); 717 } else { 718 // then recalc update with simple anneal 719 LOG(2, "WARNING: Updates on atom " << *iter << " cancel themselves, performing simple anneal step."); 720 annealAtom_BarzilaiBorwein(walker, OldTimeStep, CurrentTimeStep, _TimeStep); 721 } 674 722 } 675 723 LOG(1, "STATUS: Largest absolute update components are " << LargestUpdate);
Note:
See TracChangeset
for help on using the changeset viewer.