Program Listing for File fire.cpp#

Return to documentation for file (pymembrane/cppmodule/src/minimizer/fire.cpp)

/*
* @Author: siyu
* @Date:   2020-07-26 11:06:58
* @Last Modified by:   siyu
* @Last Modified time: 2020-08-11 22:55:44
*/
#include "fire.hpp"

void MinimizerMeshFIRE::reset(void)
{
  m_converged = false;
  m_n_since_negative = m_nmin + 1;
  m_n_since_start = 0;
  m_alpha = m_alpha_start;
  m_energy_total = 0.0;
  m_old_energy = 0.0;
  m_dE = 0.0;
  m_fnorm = 0.0;
  m_dt = 0.005;
  this->update_time_step_parameters();
  for (int id = 0; id < _system.Numvertices; id++)
  {
    _system.vertices[id].v.x = 0.0;
    _system.vertices[id].v.y = 0.0;
    _system.vertices[id].v.z = 0.0;
  }
}

void MinimizerMeshFIRE::poststep1(void)
{
  // NVT, velocity verlet
  for (int id = 0; id < _system.Numvertices; id++)
  {
    Xvec3(_system.vertices[id].r,
          1., _system.vertices[id].r,
          m_dt, _system.vertices[id].v,
          0.5 * m_dt * m_dt, _system.vertices[id].forceC);
    Xvec2(_system.vertices[id].v,
          1., _system.vertices[id].v,
          0.5 * m_dt, _system.vertices[id].forceC);
  }
}
void MinimizerMeshFIRE::poststep2(void)
{
  for (int id = 0; id < _system.Numvertices; id++)
  {
    Xvec2(_system.vertices[id].v,
          1., _system.vertices[id].v,
          0.5 * m_dt, _system.vertices[id].forceC);
  }
}
void MinimizerMeshFIRE::poststep3(void)
{
  //FIRE
  double P = 0.;
  double vnorm = 0.;
  double fnorm = 0.;
  double tnorm = 0.;
  double energy = 0.;

  for (int id = 0; id < _system.Numvertices; id++)
  {
    P += vdot(_system.vertices[id].forceC, _system.vertices[id].v);
    fnorm += vdot(_system.vertices[id].forceC, _system.vertices[id].forceC);
    vnorm += vdot(_system.vertices[id].v, _system.vertices[id].v);
    energy += _system.vertices[id].energy;
  }

  for (int id = 0; id < _system.Numedges; id++)
    energy += _system.edges[id].energy;
  for (int id = 0; id < _system.Numfaces; id++)
    energy += _system.faces[id].energy;

  fnorm = sqrt(fnorm);
  vnorm = sqrt(vnorm);
  m_fnorm = fnorm;
  m_energy_total = energy;
  m_dE = m_energy_total - m_old_energy;
  // energy = energy/(_system.Numvertices);

  // if ((fnorm/sqrt(3.)/(_system.Numvertices) < m_ftol && fabs(energy-m_old_energy) < m_etol) && m_n_since_start >= m_run_minsteps)
  if (fnorm < m_ftol && fabs(energy - m_old_energy) < m_etol && m_n_since_start >= m_run_minsteps)
  {
    pybind11::print(m_name, " converged, ftol:" , m_ftol , " m_etol:" , m_etol);
    m_converged = true;
    return;
  }

  // double factor_t;
  // if (fabs(fnorm) > EPSILON)
  //     factor_t = m_alpha*vnorm/fnorm;
  // else
  //     factor_t = 1.0;

  for (int id = 0; id < _system.Numvertices; id++)
  {
    Xvec2(_system.vertices[id].v,
          1.0 - m_alpha, _system.vertices[id].v,
          m_alpha * vnorm / fnorm, _system.vertices[id].forceC);
  }

  if (P > 0.0)
  {
    m_n_since_negative++;
    if (m_n_since_negative > m_nmin)
    {
      m_dt = std::min(m_dt, m_dT_max);
      m_alpha *= m_falpha;
    }
  }
  else if (P <= 0.0)
  {
    m_dt = m_dt * m_fdec;
    m_alpha = m_alpha_start;
    m_n_since_negative = 0;

    //pybind11::print( this->name, " zero velocities");
    //pybind11::print("P:" , P , " fnorm:" , fnorm , " vnorm:" , vnorm , " delta energy:" , fabs(energy - m_old_energy) , " energy/N:" , energy / (_system.Numvertices) , "alpha:" , m_alpha);

    for (int id = 0; id < _system.Numvertices; id++)
    {
      _system.vertices[id].v.x = 0.0;
      _system.vertices[id].v.y = 0.0;
      _system.vertices[id].v.z = 0.0;
    }
  }

  m_n_since_start++;
  m_old_energy = energy;
}

void MinimizerMeshFIRE::minimize(void)
{
  for (auto step = 0; step < m_max_iter; step++)
  {
    _evolver.reset_mesh_forces();
    _evolver.compute_mesh_forces();
    poststep1();
    _system.enforce_periodic_boundary_conditions();

    _evolver.reset_mesh_forces();
    _evolver.compute_mesh_forces();
    poststep2();

    //enforce the constraints before calculate the energy
    _evolver.enforce_mesh_constraints();

    _evolver.reset_mesh_energy();
    _evolver.compute_mesh_energy();
    poststep3();

    if (m_converged == true)
      break;
  }
  //pybind11::print(" Minimizer ", this->get_info());
}