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
# # # # #
# # # ]
|