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-11-10 16:57:26 Functions: 54.5 % 11 6
Branches: 61.0 % 172 105

             Branch data     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