LCOV - code coverage report
Current view: top level - src/78_effpot - m_potential_list.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.8 % 69 53
Test Date: 2026-09-21 19:39:32 Functions: 54.5 % 11 6

            Line data    Source code
       1              : !!****m* ABINIT/m_potential_list
       2              : !! NAME
       3              : !! m_potential_list
       4              : !!
       5              : !! FUNCTION
       6              : !! This module contains the potential_list potential. It is made of list of pointers to potentials,
       7              : !! and has all the functionality of a potential
       8              : !! It is to represent the equation H=\sum_i H_i
       9              : !! with dH/dx = \sum_i dH_i/dx
      10              : !!
      11              : !! Datatypes:
      12              : !!
      13              : !! * potential_list_t: list of abstract_potential_t, which is essentially a list of pointer to abstract_potential_t
      14              : !!    itself is also a effpot type, and its energy, 1st derivative to energy are the sum of all items.
      15              : !! Subroutines:
      16              : !! TODO: add this when F2003 doc style is determined.
      17              : !!
      18              : !!
      19              : !! COPYRIGHT
      20              : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      21              : !! This file is distributed under the terms of the
      22              : !! GNU General Public License, see ~abinit/COPYING
      23              : !! or http://www.gnu.org/copyleft/gpl.txt .
      24              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      25              : !!
      26              : !! SOURCE
      27              : 
      28              : 
      29              : #if defined HAVE_CONFIG_H
      30              : #include "config.h"
      31              : #endif
      32              : 
      33              : #include "abi_common.h"
      34              : 
      35              : module m_potential_list
      36              :   use defs_basis
      37              :   use m_abicore
      38              :   use m_errors
      39              :   use m_xmpi
      40              :   use m_mpi_scheduler, only: init_mpi_info
      41              :   use m_multibinit_dataset, only: multibinit_dtset_type
      42              :   use m_abstract_potential, only: abstract_potential_t
      43              :   use m_multibinit_cell, only: mbcell_t, mbsupercell_t
      44              :   use m_hashtable_strval, only: hash_table_t
      45              : 
      46              :   implicit none
      47              :   !!***
      48              : 
      49              :   !!****t* defs_abitypes/effpot_pointer_t
      50              :   !! NAME
      51              :   !! effpot_pointer_t
      52              :   !!
      53              :   !! FUNCTION
      54              :   !! class pointer to abstract potentials. Only here because
      55              :   !! Fortran does not allow array of pointers! So we must put
      56              :   !! pointer to an type and make an array of this type.
      57              :   !! It should only be used in potential_list_t.
      58              :   !!
      59              :   !! SOURCE
      60              :   type, private:: effpot_pointer_t ! pointer to effpot
      61              :      class(abstract_potential_t) , pointer :: ptr=>null()
      62              :   end type effpot_pointer_t
      63              :   !!***
      64              : 
      65              :   !!****t* defs_abitypes/potential_list_t
      66              :   !! NAME
      67              :   !! potential_list_t
      68              :   !!
      69              :   !! FUNCTION
      70              :   !! A potential which is made of a list of potentials.
      71              :   !! H=\sum_i H_i
      72              :   !!
      73              :   !! SOURCE
      74              :   type, public, extends(abstract_potential_t) :: potential_list_t
      75              :      integer :: size=0  ! size is the USED number of potentials in the list
      76              :      integer :: capacity=0  ! capacity is the number of places allocated for potentials
      77              :      type(effpot_pointer_t), allocatable :: list(:) ! A list of pointer type to potentials
      78              :    contains
      79              :      procedure :: initialize ! make an empty list
      80              :      procedure :: ipot       ! return the i'th potential
      81              :      procedure :: set_supercell ! pointer to supercell and set_supercell for all pot in list
      82              :      procedure :: set_params
      83              :      procedure :: finalize
      84              :      procedure :: append  ! add a potential to the list
      85              :      procedure :: calculate ! each potential in list do calculate and then sum.
      86              :      procedure :: get_delta_E ! currently only used in spin potential,
      87              :                               ! to calculate energy difference when one spin changes.
      88              : 
      89              :      procedure :: get_delta_E_lwf ! currently only used in lwf potential,
      90              :   end type potential_list_t
      91              :   !!***
      92              : 
      93              : contains
      94              : 
      95              :   !----------------------------------------------------------------------
      96              :   !> @brief initialize
      97              :   !>
      98              :   !----------------------------------------------------------------------
      99            6 :   subroutine initialize(self)
     100              :     class (potential_list_t), intent(inout) :: self
     101            6 :     self%size=0
     102            6 :     self%capacity=0
     103            6 :     self%label="ListPotential"
     104            6 :   end subroutine initialize
     105              : 
     106              :   !----------------------------------------------------------------------
     107              :   !> @brief    return the i'th potential in the list
     108              :   !>
     109              :   !> @param[in]  i: the index of the spin potentails
     110              :   ! Unfortunately, fortran does not allow things  call potlist%ipot(i)%method...
     111              :   !----------------------------------------------------------------------
     112            0 :   function ipot(self, i)
     113              :     class (potential_list_t), target, intent(in) :: self
     114              :     integer, intent(in) :: i
     115              :     class(abstract_potential_t), pointer :: ipot
     116            0 :     ipot=>self%list(i)%ptr
     117            0 :   end function ipot
     118              : 
     119              :   !----------------------------------------------------------------------
     120              :   !> @brief  set_supercell for every member of the potential list
     121              :   !> @param[in]  supercell
     122              :   !----------------------------------------------------------------------
     123           12 :   subroutine set_supercell(self, supercell)
     124              :     class (potential_list_t), intent(inout) :: self
     125              :     type (mbsupercell_t), target, intent(inout) :: supercell
     126              :     integer :: i
     127           12 :     self%supercell => supercell
     128           22 :     do i=1, self%size
     129           22 :        call self%list(i)%ptr%set_supercell(supercell)
     130              :     end do
     131           12 :   end subroutine set_supercell
     132              : 
     133              :   !----------------------------------------------------------------------
     134              :   !> @brief finalize
     135              :   !----------------------------------------------------------------------
     136            6 :   subroutine finalize(self)
     137              :     class (potential_list_t) ,intent(inout) :: self
     138              :     integer :: i
     139           16 :     do i=1, self%size
     140           10 :        call self%list(i)%ptr%finalize()
     141              :        ! Intel compiler complains
     142           10 :        if(associated(self%list(i)%ptr)) then
     143           20 :           ABI_FREE(self%list(i)%ptr)
     144              :        endif
     145              : 
     146           16 :        nullify(self%list(i)%ptr)
     147              :     end do
     148            6 :     if (allocated(self%list)) then
     149            6 :        ABI_FREE(self%list)
     150              :     end if
     151            6 :     self%size=0
     152            6 :     self%capacity=0
     153            6 :     self%is_null=.True.
     154            6 :     self%has_displacement=.False.
     155            6 :     self%has_strain=.False.
     156            6 :     self%has_spin=.False.
     157            6 :   end subroutine finalize
     158              : 
     159              : 
     160              :   !----------------------------------------------------------------------
     161              :   !> @brief append a potential to the list
     162              :   !> It also update the has_* according to the added effpot.
     163              :   !> @param[in]  effpot: the effective potential to be added.
     164              :   !----------------------------------------------------------------------
     165           10 :   subroutine append(self, effpot)
     166              :     ! Add a pointer to an effpot term to list.
     167              :     class (potential_list_t) :: self
     168              :     class (abstract_potential_t), target :: effpot
     169           10 :     type(effpot_pointer_t), allocatable :: temp(:)
     170           10 :     self%size=self%size + 1
     171           10 :     if(self%size==1) then
     172            6 :        self%capacity=8
     173           54 :        ABI_MALLOC(self%list, (self%capacity))
     174            4 :     else if ( self%size>self%capacity ) then
     175              :        ! fancy increasing equation to allocate new array.
     176            0 :        self%capacity = self%size + self%size / 4 + 8
     177            0 :        ABI_MALLOC(temp, (self%capacity))
     178            0 :        temp(:self%size-1) = self%list(:)
     179            0 :        ABI_MOVE_ALLOC(temp, self%list) !temp gets deallocated
     180              :     end if
     181           10 :     self%list(self%size)%ptr=>effpot
     182           10 :     self%is_null= (self%is_null .and. effpot%is_null)
     183           10 :     self%has_spin= (self%has_spin .or. effpot%has_spin)
     184           10 :     self%has_displacement= (self%has_displacement .or. effpot%has_displacement)
     185           10 :     self%has_strain= (self%has_strain.or. effpot%has_strain)
     186           10 :     self%has_lwf =(self%has_lwf.or. effpot%has_lwf)
     187           10 :   end subroutine append
     188              : 
     189            6 :   subroutine set_params(self, params)
     190              :     class(potential_list_t), intent(inout) :: self  ! the effpot may save the states.
     191              :     type(multibinit_dtset_type), intent(inout) :: params
     192              :     integer :: i
     193           16 :     do i=1, self%size
     194           16 :        call self%list(i)%ptr%set_params(params)
     195              :     end do
     196            6 :   end subroutine set_params
     197              : 
     198              : 
     199              : 
     200              :   !----------------------------------------------------------------------
     201              :   !> @brief calculate energy and 1st derivatives
     202              :   !>  The list will add the sum of all the results from its components.
     203              :   !>  If one optional variable is passed to a subroutine, its "presence" will be kept.
     204              :   !> @param[in] (optional) displacement, strain, spin, lwf
     205              :   !> @param[out](optional) force, stress, bfield, lwf_force, energy
     206              :   !----------------------------------------------------------------------
     207       108056 :   subroutine calculate(self, displacement, strain, spin, lwf,  force, stress, bfield, &
     208        54028 :        & lwf_force, energy, energy_table)
     209              :     ! calculate energy and its first derivatives.
     210              :     class(potential_list_t), intent(inout) :: self  ! the effpot may save the states.
     211              :     ! inputs
     212              :     real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
     213              :     ! outputs
     214              :     real(dp), optional, intent(inout) :: force(:,:), stress(:,:), bfield(:,:), lwf_force(:), energy
     215              :     type(hash_table_t),optional, intent(inout) :: energy_table
     216              :     integer :: i
     217              :     ! Note
     218              :     ! calculate force and strain if asked to
     219     34664932 :     if(present(force)) force(:,:)=0.0d0
     220       158340 :     if(present(stress)) stress(:,:)=0.0d0
     221      3517488 :     if(present(bfield)) bfield(:,:)=0.0d0
     222     43104028 :     if(present(lwf_force)) lwf_force(:)=0.0d0
     223        54028 :     if(present(energy)) energy =0.0
     224       124072 :     do i=1, self%size
     225              :        call self%list(i)%ptr%calculate(displacement=displacement, strain=strain, &
     226              :             & spin=spin, lwf=lwf, force=force, stress=stress, bfield=bfield, &
     227       488248 :             lwf_force=lwf_force, energy=energy, energy_table=energy_table)
     228              :     end do
     229        54028 :   end subroutine calculate
     230              : 
     231              :   !----------------------------------------------------------------------
     232              :   !> @brief get_delta_E: calculate the energy difference when a given spin
     233              :   !> is changed. This is to be used for spin Monte Carlo. Currently the
     234              :   !> only supported is the spin model.
     235              :   !>
     236              :   !> @param[in]  S: spin of full structure. array of (3, nspin)
     237              :   !> @param[in]  ispin: the index of spin changed. integer
     238              :   !> @param[in]  snew: the new value of the changed spin.
     239              :   !> @param[out] deltaE: the energy difference
     240              :   !----------------------------------------------------------------------
     241            0 :   subroutine get_delta_E(self, S, ispin, Snew, deltaE)
     242              :     class(potential_list_t), intent(inout) :: self  ! the effpot may save the states.
     243              :     real(dp), intent(inout) :: S(:,:),  Snew(:)
     244              :     integer, intent(in) :: ispin
     245              :     real(dp), intent(inout) :: deltaE
     246              :     integer :: i
     247            0 :     do i=1, self%size
     248            0 :        call self%list(i)%ptr%get_delta_E(S=S, ispin=ispin, Snew=Snew, deltaE=deltaE)
     249              :     end do
     250            0 :     end subroutine get_delta_E
     251              : 
     252              :     !----------------------------------------------------------------------
     253              :     !> @brief get_delta_E_lwf: calculate the energy difference when a given lwf
     254              :     !> is changed. This is to be used for spin Monte Carlo. Currently the
     255              :     !> only supported is the spin model.
     256              :     !>
     257              :     !> @param[in]  lwf: lwf of full structure. array of (nlwf)
     258              :     !> @param[in]  ilwf: the index of spin changed. integer
     259              :     !> @param[in]  lwf_new: the new value of the changed spin.
     260              :     !> @param[out] deltaE: the energy difference
     261              :     !----------------------------------------------------------------------
     262            0 :     subroutine get_delta_E_lwf(self, lwf, ilwf, lwf_new, deltaE)
     263              :       ! for spin monte carlo
     264              :       ! calculate energy difference if one spin is moved.
     265              :       class(potential_list_t), intent(inout) :: self  ! the effpot may save the states.
     266              :       real(dp),  intent(inout) :: lwf(:),  lwf_new
     267              :       integer,  intent(in) :: ilwf
     268              :       real(dp), intent(inout) :: deltaE
     269              :       integer :: i
     270            0 :       do i=1, self%size
     271            0 :          call self%list(i)%ptr%get_delta_E_lwf(lwf=lwf, ilwf=ilwf, lwf_new=lwf_new, deltaE=deltaE)
     272              :       end do
     273            0 :     end subroutine get_delta_E_lwf
     274              : 
     275              : 
     276              : 
     277            0 : end module m_potential_list
        

Generated by: LCOV version 2.3-1