Ignore:
Timestamp:
Jul 20, 2017, 9:38:38 AM (8 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
ForceAnnealing_with_BondGraph_continued
Children:
9d3846
Parents:
4cd46b
git-author:
Frederik Heber <frederik.heber@…> (06/20/17 20:26:12)
git-committer:
Frederik Heber <frederik.heber@…> (07/20/17 09:38:38)
Message:

ForceAnnealing can now be used either atom- or bond-centered.

  • new keyword "use-bondgraph" to use either case.
  • atom is old annealing method, bond graph is new annealing method where the bond neighborhood is shifted as well to anneal to force projected onto the BondVector.
  • In the first step we always use atom-centered annealing where we use the given deltat step width. Afterwards Barzilai-Borwein may then proceed.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Dynamics/ForceAnnealing.hpp

    r4cd46b r6d360a  
    9090   *
    9191   *
    92    * \param NextStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
     92   * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
    9393   * \param offset offset in matrix file to the first force component
    9494   * \todo This is not yet checked if it is correctly working with DoConstrainedMD set >0.
    9595   */
    96   void operator()(const int CurrentTimeStep, const size_t offset)
     96  void operator()(
     97      const int _CurrentTimeStep,
     98      const size_t _offset,
     99      const bool _UseBondgraph)
    97100  {
    98101    // make sum of forces equal zero
    99     AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(offset,CurrentTimeStep);
     102    AtomicForceManipulator<T>::correctForceMatrixForFixedCenterOfMass(_offset, _CurrentTimeStep);
    100103
    101104    // are we in initial step? Then set static entities
     105    Vector maxComponents(zeroVec);
    102106    if (currentStep == 0) {
    103107      currentDeltat = AtomicForceManipulator<T>::Deltat;
    104108      currentStep = 1;
    105109      LOG(2, "DEBUG: Initial step, setting values, current step is #" << currentStep);
     110
     111      // always use atomic annealing on first step
     112      anneal(_CurrentTimeStep, _offset, maxComponents);
    106113    } else {
    107114      ++currentStep;
    108115      LOG(2, "DEBUG: current step is #" << currentStep);
    109     }
    110 
     116
     117      if (_UseBondgraph)
     118        annealWithBondGraph(_CurrentTimeStep, _offset, maxComponents);
     119      else
     120        anneal(_CurrentTimeStep, _offset, maxComponents);
     121    }
     122
     123
     124    LOG(1, "STATUS: Largest remaining force components at step #"
     125        << currentStep << " are " << maxComponents);
     126
     127    // are we in final step? Remember to reset static entities
     128    if (currentStep == maxSteps) {
     129      LOG(2, "DEBUG: Final step, resetting values");
     130      reset();
     131    }
     132  }
     133
     134  /** Performs Gradient optimization on the atoms.
     135   *
     136   * We assume that forces have just been calculated.
     137   *
     138   * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
     139   * \param offset offset in matrix file to the first force component
     140   * \param maxComponents to be filled with maximum force component over all atoms
     141   */
     142  void anneal(
     143      const int CurrentTimeStep,
     144      const size_t offset,
     145      Vector &maxComponents)
     146  {
     147                for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
     148                    iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
     149                        // atom's force vector gives steepest descent direction
     150                        const Vector oldPosition = (*iter)->getPositionAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
     151                        const Vector currentPosition = (*iter)->getPosition();
     152                        const Vector oldGradient = (*iter)->getAtomicForceAtStep(CurrentTimeStep-2 >= 0 ? CurrentTimeStep - 2 : 0);
     153                        const Vector currentGradient = (*iter)->getAtomicForce();
     154      LOG(4, "DEBUG: oldPosition for atom " << **iter << " is " << oldPosition);
     155      LOG(4, "DEBUG: currentPosition for atom " << **iter << " is " << currentPosition);
     156      LOG(4, "DEBUG: oldGradient for atom " << **iter << " is " << oldGradient);
     157      LOG(4, "DEBUG: currentGradient for atom " << **iter << " is " << currentGradient);
     158//                      LOG(4, "DEBUG: Force for atom " << **iter << " is " << currentGradient);
     159
     160      // we use Barzilai-Borwein update with position reversed to get descent
     161      const Vector PositionDifference = currentPosition - oldPosition;
     162                        const Vector GradientDifference = (currentGradient - oldGradient);
     163                        double stepwidth = 0.;
     164                        if (GradientDifference.Norm() > MYEPSILON)
     165        stepwidth = fabs(PositionDifference.ScalarProduct(GradientDifference))/
     166            GradientDifference.NormSquared();
     167                        if (fabs(stepwidth) < 1e-10) {
     168                          // dont' warn in first step, deltat usage normal
     169                          if (currentStep != 1)
     170          ELOG(1, "INFO: Barzilai-Borwein stepwidth is zero, using deltat " << currentDeltat << " instead.");
     171                          stepwidth = currentDeltat;
     172                        }
     173      Vector PositionUpdate = stepwidth * currentGradient;
     174                        LOG(3, "DEBUG: Update would be " << stepwidth << "*" << currentGradient << " = " << PositionUpdate);
     175
     176                        // extract largest components for showing progress of annealing
     177                        for(size_t i=0;i<NDIM;++i)
     178                          if (currentGradient[i] > maxComponents[i])
     179                            maxComponents[i] = currentGradient[i];
     180
     181                        // are we in initial step? Then don't check against velocity
     182                        if ((currentStep > 1) && (!(*iter)->getAtomicVelocity().IsZero()))
     183                                // update with currentDelta tells us how the current gradient relates to
     184                                // the last one: If it has become larger, reduce currentDelta
     185                                if ((PositionUpdate.ScalarProduct((*iter)->getAtomicVelocity()) < 0)
     186                                    && (currentDeltat > MinimumDeltat)) {
     187                                  currentDeltat = .5*currentDeltat;
     188                                  LOG(2, "DEBUG: Upgrade in other direction: " << PositionUpdate.NormSquared()
     189                                      << " > " << (*iter)->getAtomicVelocity().NormSquared()
     190                                      << ", decreasing deltat: " << currentDeltat);
     191                                  PositionUpdate = currentDeltat * currentGradient;
     192                        }
     193                        // finally set new values
     194                        (*iter)->setPosition(currentPosition + PositionUpdate);
     195                        (*iter)->setAtomicVelocity(PositionUpdate);
     196                        //std::cout << "Id of atom is " << (*iter)->getId() << std::endl;
     197//        (*iter)->VelocityVerletUpdateU((*iter)->getId(), CurrentTimeStep-1, Deltat, IsAngstroem);
     198
     199                        // reset force vector for next step except on final one
     200                        if (currentStep != maxSteps)
     201                          (*iter)->setAtomicForce(zeroVec);
     202                }
     203
     204                LOG(1, "STATUS: Largest remaining force components at step #"
     205                    << currentStep << " are " << maxComponents);
     206
     207                // are we in final step? Remember to reset static entities
     208                if (currentStep == maxSteps) {
     209                  LOG(2, "DEBUG: Final step, resetting values");
     210                  reset();
     211                }
     212  }
     213
     214  /** Performs Gradient optimization on the bonds.
     215   *
     216   * We assume that forces have just been calculated. These forces are projected
     217   * onto the bonds and these are annealed subsequently by moving atoms in the
     218   * bond neighborhood on either side conjunctively.
     219   *
     220   *
     221   * \param CurrentTimeStep current time step (i.e. \f$ t + \Delta t \f$ in the sense of the velocity verlet)
     222   * \param offset offset in matrix file to the first force component
     223   * \param maxComponents to be filled with maximum force component over all atoms
     224   */
     225  void annealWithBondGraph(
     226      const int CurrentTimeStep,
     227      const size_t offset,
     228      Vector &maxComponents)
     229  {
    111230    // get nodes on either side of selected bond via BFS discovery
    112231    BoostGraphCreator BGcreator;
     
    375494    }
    376495
    377     Vector maxComponents(zeroVec);
    378496    for(typename AtomSetMixin<T>::iterator iter = AtomicForceManipulator<T>::atoms.begin();
    379497        iter != AtomicForceManipulator<T>::atoms.end(); ++iter) {
     
    401519      walker->setAtomicVelocity(update);
    402520      LOG(3, "DEBUG: Applying update " << update << " to atom " << *walker);
    403     }
    404 
    405     LOG(1, "STATUS: Largest remaining force components at step #"
    406         << currentStep << " are " << maxComponents);
    407 
    408     // are we in final step? Remember to reset static entities
    409     if (currentStep == maxSteps) {
    410       LOG(2, "DEBUG: Final step, resetting values");
    411       reset();
    412521    }
    413522  }
Note: See TracChangeset for help on using the changeset viewer.