Line data Source code
1 : !!****m* ABINIT/m_abstract_potential
2 : !! NAME
3 : !! m_abstract_potential
4 : !!
5 : !! FUNCTION
6 : !! This module contains the base type for all effective potentials.
7 : !!
8 : !!
9 : !! Datatypes:
10 : !!
11 : !! * abstract_potential_t: defines the base api of effective potentials.
12 : !! * potential_list_t: list of abstract_potential_t, which is essentially a list of pointer to abstract_potential_t
13 : !! itself is also a effpot type, and its energy, 1st derivative to energy are the sum of all items.
14 : !! Subroutines:
15 : !! TODO: add this when F2003 doc style is determined.
16 : !!
17 : !!
18 : !! COPYRIGHT
19 : !! Copyright (C) 2001-2026 ABINIT group (hexu)
20 : !! This file is distributed under the terms of the
21 : !! GNU General Public License, see ~abinit/COPYING
22 : !! or http://www.gnu.org/copyleft/gpl.txt .
23 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
24 : !!
25 : !! SOURCE
26 :
27 :
28 : #if defined HAVE_CONFIG_H
29 : #include "config.h"
30 : #endif
31 :
32 : #include "abi_common.h"
33 :
34 : module m_abstract_potential
35 : use defs_basis
36 : use m_abicore
37 : use m_errors
38 : use m_xmpi
39 :
40 : use m_multibinit_dataset, only: multibinit_dtset_type
41 : use m_multibinit_cell, only: mbcell_t, mbsupercell_t
42 : use m_hashtable_strval, only: hash_table_t
43 :
44 : implicit none
45 : !!***
46 : private
47 :
48 :
49 : type ,public :: abstract_potential_t
50 : ! This is the abstract class of effective potential.
51 : ! It do the following things:
52 : ! calculate 0th, 1st,... derivative of energy related, e.g. Force for lattice model
53 : ! labels for variables. If a new degree of freedom is to be added, a label
54 : ! should be added here.
55 : logical :: has_displacement=.False.
56 : logical :: has_strain=.False.
57 : logical :: has_spin=.False.
58 : logical :: has_lwf = .False.
59 : logical :: is_null=.True. ! if is_null, this term does not exist.
60 : ! it is important to set it to True before initialization.
61 : ! Because it is used as the tag for deallocatign memory.
62 : type(mbsupercell_t) ,pointer :: supercell => null()
63 : ! every supercell potential has a pointer to the supercell,
64 : ! which could be used for like reference structure.
65 : character (len=200) :: label="Abstract Potential" !
66 : ! the label is used for printing information.
67 : contains
68 : procedure :: set_supercell ! set_supercell
69 : procedure :: finalize ! finalize
70 : procedure :: set_params ! parameters from input file
71 : procedure :: calculate ! get energy and 1st derivative from input state
72 : procedure :: get_delta_E ! calculate energy diffence if one component is changed for Monte carlo algorithm
73 : procedure :: get_delta_E_lwf ! calculate energy diffence if one component is changed for Monte carlo algorithm
74 : end type abstract_potential_t
75 :
76 : contains
77 :
78 : !----------------------------------------------------------------------
79 : !> @brief link a supercell to the potential
80 : !>
81 : !> @param[in] supercell: supercell object
82 : !----------------------------------------------------------------------
83 0 : subroutine set_supercell(self, supercell)
84 : class(abstract_potential_t), intent(inout) :: self
85 : type(mbsupercell_t), target, intent(inout) :: supercell
86 0 : ABI_UNUSED_A(self)
87 0 : ABI_UNUSED_A(supercell)
88 0 : ABI_ERROR("Every potential should override this set_supercell method to avoid mistake.")
89 0 : end subroutine set_supercell
90 :
91 : !----------------------------------------------------------------------
92 : !> @brief finalize
93 : !>
94 : !----------------------------------------------------------------------
95 6 : subroutine finalize(self)
96 : class(abstract_potential_t), intent(inout) :: self
97 6 : self%is_null=.True.
98 6 : nullify(self%supercell)
99 6 : self%label="Destroyed potential"
100 6 : end subroutine finalize
101 :
102 : !----------------------------------------------------------------------
103 : !> @brief set_params: set the parameters from input file parameters
104 : !>
105 : !> @param[in] params: multibinit_dtset_type: from input file
106 : !----------------------------------------------------------------------
107 5 : subroutine set_params(self, params)
108 : class(abstract_potential_t), intent(inout) :: self
109 : type(multibinit_dtset_type), intent(inout) :: params
110 5 : ABI_UNUSED_A(self)
111 5 : ABI_UNUSED_A(params)
112 : ! The default behavior is do nothing
113 5 : end subroutine set_params
114 :
115 : ! hexu comment : which one is better, more general variables,
116 : ! or one function for each type of var?
117 : !subroutine set_variables(self, displacements, strain, spin)
118 : ! class(lattice_api_t), intent(inout) :: self
119 : ! real(dp), optional, intent(in) :: displacements(:,:), strain(:,:), spin(:,:)
120 : !end subroutine set_variables
121 :
122 : !subroutine get_1st_deriv(self, force, stress, bfield)
123 : ! class(lattice_api_t), intent(inout) :: self
124 : ! real(dp), optional, intent(out) :: force(:,:), stress(:,:), bfield(:,:)
125 : !end subroutine get_1st_deriv
126 :
127 : ! subroutine set_distortion(self, displacement, strain)
128 : ! class(abstract_potential_t), intent(inout) :: self
129 : ! real(dp), optional, intent(in) :: displacement(:,:), strain(:,:)
130 : ! ABI_ERROR("set_distortion not implemented.")
131 : ! end subroutine set_distortion
132 :
133 : ! subroutine set_spin(self, spin)
134 : ! class(abstract_potential_t), intent(inout) :: self
135 : ! real(dp), optional, intent(in) :: spin
136 : ! ABI_ERROR("set_spin not implemented.")
137 : ! end subroutine set_spin
138 :
139 : !----------------------------------------------------------------------
140 : !> @brief calculate energy and derivatives with given state.
141 : !> This function calculate the energy and its first derivative
142 : !> the inputs and outputs are optional so that each effpot can adapt to its
143 : !> own.
144 : !> In principle, the 1st derivatives are only calculated if
145 : !> asked to (present).
146 : !> However, they can be computed if it is simply convinient to do.
147 : !> @param[in] displacement (optional)
148 : !> @param[in] strain (optional)
149 : !> @param[in] spin (optional)
150 : !> @param[in] lwf (optional)
151 : !> @param[out] force (optional)
152 : !> @param[out] stress (optional)
153 : !> @param[out] bfield (optional)
154 : !> @param[out] energy_table (optional)
155 : !----------------------------------------------------------------------
156 0 : subroutine calculate(self, displacement, strain, spin, lwf, force, stress, bfield, lwf_force, &
157 : & energy, energy_table)
158 : class(abstract_potential_t), intent(inout) :: self ! the effpot may save the states.
159 :
160 : real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
161 : real(dp), optional, intent(inout) :: force(:,:), stress(:,:), bfield(:,:), lwf_force(:), energy
162 : type(hash_table_t),optional, intent(inout) :: energy_table
163 : ! if present in input
164 : ! calculate if required
165 0 : ABI_UNUSED_A(self)
166 0 : ABI_UNUSED_A(displacement)
167 0 : ABI_UNUSED_A(strain)
168 0 : ABI_UNUSED_A(spin)
169 0 : ABI_UNUSED_A(lwf)
170 0 : ABI_UNUSED_A(force)
171 0 : ABI_UNUSED_A(stress)
172 0 : ABI_UNUSED_A(bfield)
173 0 : ABI_UNUSED_A(lwf_force)
174 0 : ABI_UNUSED_A(energy)
175 0 : ABI_UNUSED_A(energy_table)
176 0 : ABI_ERROR("calculate not implemented for this effpot.")
177 0 : end subroutine calculate
178 :
179 : !----------------------------------------------------------------------
180 : !> @brief get_delta_E: calculate the energy difference when a given spin
181 : !> is changed. This is to be used for spin Monte Carlo. Currently the
182 : !> only supported is the spin model.
183 : !>
184 : !> @param[in] S: spin of full structure. array of (3, nspin)
185 : !> @param[in] ispin: the index of spin changed. integer
186 : !> @param[in] snew: the new value of the changed spin.
187 : !> @param[out] deltaE: the energy difference
188 : !----------------------------------------------------------------------
189 0 : subroutine get_delta_E(self, S, ispin, Snew, deltaE)
190 : ! for spin monte carlo
191 : ! calculate energy difference if one spin is moved.
192 : class(abstract_potential_t), intent(inout) :: self ! the effpot may save the states.
193 : real(dp), intent(inout) :: S(:,:), Snew(:)
194 : integer, intent(in) :: ispin
195 : real(dp), intent(inout) :: deltaE
196 0 : ABI_UNUSED_A(self)
197 0 : ABI_UNUSED_A(S)
198 0 : ABI_UNUSED_A(ispin)
199 0 : ABI_UNUSED_A(Snew)
200 0 : ABI_UNUSED_A(deltaE)
201 0 : ABI_ERROR("get_delta_E not implemented for this effpot.")
202 0 : end subroutine get_delta_E
203 :
204 : !----------------------------------------------------------------------
205 : !> @brief get_delta_E_lwf: calculate the energy difference when a given lwf
206 : !> is changed. This is to be used for spin Monte Carlo. Currently the
207 : !> only supported is the spin model.
208 : !>
209 : !> @param[in] lwf: lwf of full structure. array of (nlwf)
210 : !> @param[in] ilwf: the index of spin changed. integer
211 : !> @param[in] lwf_new: the new value of the changed spin.
212 : !> @param[out] deltaE: the energy difference
213 : !----------------------------------------------------------------------
214 0 : subroutine get_delta_E_lwf(self, lwf, ilwf, lwf_new, deltaE)
215 : ! for spin monte carlo
216 : ! calculate energy difference if one spin is moved.
217 : class(abstract_potential_t), intent(inout) :: self ! the effpot may save the states.
218 : real(dp), intent(inout) :: lwf(:), lwf_new
219 : integer, intent(in) :: ilwf
220 : real(dp), intent(inout) :: deltaE
221 0 : ABI_UNUSED_A(self)
222 0 : ABI_UNUSED_A(lwf)
223 0 : ABI_UNUSED_A(ilwf)
224 0 : ABI_UNUSED_A(lwf_new)
225 0 : ABI_UNUSED_A(deltaE)
226 0 : ABI_ERROR("get_delta_E_lwf not implemented for this effpot."//self%label)
227 0 : end subroutine get_delta_E_lwf
228 :
229 :
230 :
231 : ! subroutine get_energy(self, energy)
232 : ! class(abstract_potential_t), intent(inout) :: self
233 : ! real(dp) , intent(inout) :: energy
234 : ! end subroutine get_energy
235 :
236 :
237 : ! subroutine get_force(self, force)
238 : ! class(abstract_potential_t), intent(inout) :: self
239 : ! real(dp), intent(out) :: force(:,:)
240 : ! end subroutine get_force
241 :
242 : ! subroutine get_stress(self, stress)
243 : ! class(abstract_potential_t), intent(inout) :: self
244 : ! real(dp), intent(out) :: stress(:,:)
245 : ! end subroutine get_stress
246 :
247 : ! subroutine get_effective_Bfield(self, spin,bfield)
248 : ! class(abstract_potential_t), intent(in) :: self
249 : ! real(dp), intent(in) :: spin(:,:)
250 : ! real(dp), intent(inout) :: bfield(:,:)
251 : ! end subroutine get_effective_Bfield
252 :
253 0 : end module m_abstract_potential
|