LCOV - code coverage report
Current view: top level - src/78_effpot - m_lattice_langevin_mover.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 52 52
Test Date: 2026-09-20 18:56:22 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !!****m* ABINIT/m_lattice_langevin_mover
       2              : !! NAME
       3              : !! m_lattice_langevin_mover
       4              : !!
       5              : !! FUNCTION
       6              : !! This module contains the langevin  (NVT) lattice mover.
       7              : !! It is a translation from the ASE (GPL licenced) Langevin mover python code to fortran.
       8              : !! The original code can be found at
       9              : !! https://gitlab.com/ase/ase/blob/master/ase/md/langevin.py
      10              : !! The method is described in
      11              : !! E. V.-Eijnden, and G. Ciccotti, Chem. Phys. Lett. 429, 310 (2006)
      12              : !!  https://doi.org/10.1016/j.cplett.2006.07.086
      13              : !!
      14              : !!
      15              : !! Datatypes:
      16              : !!
      17              : !! * lattice_langevin_mover_t: defines the lattice movers
      18              : !!
      19              : !! Subroutines:
      20              : !! TODO: add this when F2003 doc style is determined.
      21              : !!
      22              : !!
      23              : !! COPYRIGHT
      24              : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      25              : !! This file is distributed under the terms of the
      26              : !! GNU General Public License, see ~abinit/COPYING
      27              : !! or http://www.gnu.org/copyleft/gpl.txt .
      28              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      29              : !!
      30              : !! SOURCE
      31              : 
      32              : 
      33              : 
      34              : #if defined HAVE_CONFIG_H
      35              : #include "config.h"
      36              : #endif
      37              : 
      38              : #include "abi_common.h"
      39              : 
      40              : module m_lattice_langevin_mover
      41              :   use defs_basis
      42              :   use m_abicore
      43              :   use m_errors
      44              : 
      45              :   use m_multibinit_dataset, only: multibinit_dtset_type
      46              :   use m_abstract_potential, only: abstract_potential_t
      47              :   use m_abstract_mover, only: abstract_mover_t
      48              :   use m_lattice_mover, only: lattice_mover_t
      49              :   use m_multibinit_cell, only: mbcell_t, mbsupercell_t
      50              :   use m_random_xoroshiro128plus, only:  rng_t
      51              :   use m_hashtable_strval, only: hash_table_t
      52              : !!***
      53              : 
      54              :   implicit none
      55              : 
      56              :   private
      57              : 
      58              :   !-------------------------------------------------------------------!
      59              :   ! Lattice_langevin_mover_t
      60              :   !
      61              :   !-------------------------------------------------------------------!
      62              :   type, public, extends(lattice_mover_t) :: lattice_langevin_mover_t
      63              :      ! c1 to c5 are a constants (temperature and mass dependent)
      64              :      ! c3 c4 c5 has dimension of natom.
      65              :      real(dp) :: c1, c2
      66              :      real(dp), allocatable :: c3(:), c4(:), c5(:)
      67              :      real(dp) :: fr =1e-4 ! friction, usually 1e-2~1e-4
      68              :      ! xi and eta: random numbers of dimension (3, natom)
      69              :      real(dp), allocatable :: xi(:,:), eta(:,:)
      70              :    contains
      71              :      procedure :: initialize
      72              :      procedure :: finalize
      73              :      procedure :: run_one_step
      74              :      procedure :: update_vars
      75              :   end type lattice_langevin_mover_t
      76              : 
      77              : contains
      78              : 
      79              :   !-------------------------------------------------------------------!
      80              :   ! Initialize:
      81              :   !  read parameters
      82              :   !  allocate memory and call update_vars()
      83              :   !-------------------------------------------------------------------!
      84            1 :   subroutine initialize(self,params, supercell, rng)
      85              :     class(lattice_langevin_mover_t), intent(inout) :: self
      86              :     type(multibinit_dtset_type), target, intent(in):: params
      87              :     type(mbsupercell_t), target, intent(in) :: supercell
      88              :     type(rng_t), target, intent(in) :: rng
      89            1 :     call self%lattice_mover_t%initialize(params, supercell, rng)
      90              : 
      91              :     ! TODO: add friction
      92            1 :     self%fr = params%latt_friction
      93              : 
      94            3 :     ABI_MALLOC(self%c3, (self%natom))
      95            3 :     ABI_MALLOC(self%c4, (self%natom))
      96            3 :     ABI_MALLOC(self%c5, (self%natom))
      97            3 :     ABI_MALLOC(self%xi, (3,self%natom))
      98            3 :     ABI_MALLOC(self%eta, (3,self%natom))
      99              : 
     100            1 :     call self%update_vars()
     101            1 :   end subroutine initialize
     102              : 
     103              : 
     104              :   !-------------------------------------------------------------------!
     105              :   ! Finalize
     106              :   !-------------------------------------------------------------------!
     107            1 :   subroutine finalize(self)
     108              :     class(lattice_langevin_mover_t), intent(inout) :: self
     109            1 :     ABI_FREE(self%c3)
     110            1 :     ABI_FREE(self%c4)
     111            1 :     ABI_FREE(self%c5)
     112            1 :     ABI_FREE(self%xi)
     113            1 :     ABI_FREE(self%eta)
     114            1 :     call self%lattice_mover_t%finalize()
     115            1 :   end subroutine finalize
     116              : 
     117              :   !-------------------------------------------------------------------!
     118              :   ! update_vars:
     119              :   !  calculate c1 to c5 from dt, masses and temperature
     120              :   !  It is called by the initialization function.
     121              :   !-------------------------------------------------------------------!
     122            1 :   subroutine update_vars(self)
     123              :     class(lattice_langevin_mover_t), intent(inout) :: self
     124            2 :     real(dp) :: dt, T, fr, sigma(self%natom)
     125              : 
     126            1 :     dt=self%dt
     127            1 :     T= self%temperature
     128            1 :     fr=self%fr
     129          321 :     sigma(:) = sqrt(2.0*T*fr/self%masses(:))
     130            1 :     self%c1 = dt / 2.0 - dt * dt * fr / 8.0
     131            1 :     self%c2 = dt * fr / 2.0 - dt * dt * fr * fr / 8.0
     132          322 :     self%c3 = sqrt(dt) * sigma / 2.0 - dt**1.5 * fr * sigma / 8.0
     133          322 :     self%c5 = dt**1.5 * sigma / (2.0 * sqrt(3.0))
     134          322 :     self%c4 = fr / 2. * self%c5
     135            1 :   end subroutine update_vars
     136              : 
     137              :   !-------------------------------------------------------------------!
     138              :   !> @brief: Run_one_step using a Langevin heat bath.
     139              :   !>   effpot: the potential (which do the calculation of E and dE/dvar)
     140              :   !> param[in]: effpot
     141              :   !> param[in]: (optional) displacement
     142              :   !> param[in]: (optional) strain
     143              :   !> param[in]: (optional) spin
     144              :   !> param[in]: (optional) lwf
     145              :   ! NOTE: No need to pass the variable already saved in the mover.
     146              :   !     e.g. For spin mover, do NOT pass the spin to it.
     147              :   !    The other variables are only required if there is coupling with
     148              :   !    the mover variable.
     149              :   !-------------------------------------------------------------------!
     150           10 :   subroutine run_one_step(self, effpot,displacement, strain, spin, lwf , energy_table)
     151              :     class(lattice_langevin_mover_t), intent(inout) :: self
     152              :     class(abstract_potential_t), intent(inout) :: effpot
     153              :     real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
     154              :     type(hash_table_t), optional, intent(inout) :: energy_table
     155              :     integer :: i
     156              :     character(len=40) :: key
     157              : 
     158              :     ! do not use displacement and strain because they are stored in the mover.
     159           10 :     ABI_UNUSED_A(displacement)
     160           10 :     ABI_UNUSED_A(strain)
     161              : 
     162           10 :     self%energy = 0.0
     163        12810 :     self%forces(:,:) =0.0
     164              :     call effpot%calculate( displacement=self%displacement, strain=self%strain, &
     165              :          & spin=spin, lwf=lwf, force=self%forces, stress=self%stress, &
     166           30 :          & energy=self%energy, energy_table=energy_table)
     167           10 :     call self%rng%rand_normal_array(self%xi, 3*self%natom)
     168           10 :     call self%rng%rand_normal_array(self%eta, 3*self%natom)
     169              : 
     170              : 
     171              : 
     172              :     ! First half of velocity update
     173         3210 :     do i =1, self%natom
     174              :        self%current_vcart(:,i) = self%current_vcart(:,i) + &
     175              :             & self%c1 * self%forces(:,i) / self%masses(i) - &
     176              :             & self%c2 * self%current_vcart(:,i) + &
     177        12800 :             & self%c3(i) * self%xi(:, i) - self%c4(i) * self%eta(:,i)
     178              : 
     179              :        self%displacement(:, i) = self%displacement(:, i) &
     180        12810 :             & + self%dt * self%current_vcart(:, i) + self%c5( i) *self%eta(:,i)
     181              :     end do
     182              : 
     183              :     ! second half, update the velocity but not the displacement.
     184           10 :     self%energy=0.0
     185        12810 :     self%forces=0.0
     186              :     call effpot%calculate( displacement=self%displacement, strain=self%strain, &
     187              :          & spin=spin, lwf=lwf, force=self%forces, stress=self%stress, &
     188           30 :          & energy=self%energy, energy_table=energy_table)
     189         3210 :     do i =1, self%natom
     190              :        self%current_vcart(:,i) = self%current_vcart(:,i) + &
     191              :             &self%c1 * self%forces(:,i) / self%masses(i) - &
     192              :             & self%c2 * self%current_vcart(:,i) + &
     193        12810 :             & self%c3(i) * self%xi(:, i) - self%c4(i) * self%eta(:,i)
     194              :     end do
     195              : 
     196           10 :     call self%get_T_and_Ek()
     197           10 :     if (present(energy_table)) then
     198           10 :       key = 'Lattice kinetic energy'
     199           10 :        call energy_table%put(key, self%Ek)
     200              :     end if
     201              : 
     202           10 :   end subroutine run_one_step
     203              : 
     204            4 : end module m_lattice_langevin_mover
     205              : 
        

Generated by: LCOV version 2.3-1