Line data Source code
1 : !!****m* ABINIT/m_tdep_model
2 : !! NAME
3 : !! m_tdep_model
4 : !!
5 : !! FUNCTION
6 : !! This module contains the TDEP Model data type
7 : !! which holds the IFC at all orders and derived quantities.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2011-2026 ABINIT group (GA,FB,JB)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : module m_tdep_model
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_xmpi
29 : use m_io_tools
30 : use m_tdep_dataset, only : atdep_dataset_type, MPI_enreg_type
31 : use m_tdep_sampling, only : tdep_Sampling_type
32 : use m_tdep_shell, only : Shell_type
33 :
34 : implicit none
35 :
36 : !----------------------------------------------------------------------
37 :
38 : !!***
39 : !!****t* m_tdep_model/Phi2_type
40 : !! NAME
41 : !! Phi2_type
42 : !!
43 : !! FUNCTION
44 : !! Second-order IFC
45 : !!
46 : !! SOURCE
47 :
48 : type Phi2_type
49 :
50 : double precision, allocatable :: SR(:,:)
51 : ! SR(3*natom, 3*natom)
52 : ! Short-range part of the second-order IFC
53 :
54 : double precision, allocatable :: LR(:,:)
55 : ! LR(3*natom, 3*natom)
56 : ! Long-range part of the second-order IFC
57 :
58 : double precision, allocatable :: Tot(:,:)
59 : ! Tot(3*natom, 3*natom)
60 : ! Second-order IFC (SR + LR)
61 :
62 :
63 : end type Phi2_type
64 :
65 :
66 : !----------------------------------------------------------------------
67 :
68 : !!***
69 : !!****t* m_tdep_model/tdep_Model_type
70 : !! NAME
71 : !! tdep_Model_type
72 : !!
73 : !! FUNCTION
74 : !! Holds the result of the TDEP fit, that is, the IFCs and resulting forces
75 : !! and energy contributions.
76 : !!
77 : !! SOURCE
78 :
79 : type,public :: tdep_Model_type
80 :
81 : integer :: order
82 : ! Maximum IFC order (2, 3, or 4)
83 :
84 : integer :: natom
85 : ! Number of atoms
86 :
87 : integer :: natom_unitcell
88 : ! Number of atoms in the unitcell
89 :
90 : integer :: my_nstep
91 : ! Number of MD steps held locally
92 :
93 : integer :: nshell3rd
94 : ! Number of shells for 3rd order IFC
95 :
96 : integer :: nshell4th
97 : ! Number of shells for 4th order IFC
98 :
99 : double precision :: U0
100 : ! Constant term contribution to energy
101 :
102 : double precision, allocatable :: Forces(:)
103 : ! Forces(3*natom*my_nstep)
104 : ! Forces computed from the fitted IFC and the displacements
105 :
106 : double precision, allocatable :: Phi1(:)
107 : ! Phi1(3*natom)
108 : ! First-order IFC
109 :
110 : type(Phi2_type) :: Phi2
111 : ! Second-order IFC
112 :
113 : double precision, allocatable :: Phi3(:,:,:,:)
114 : ! Phi3(3,3,3,Shell3at%nshell)
115 : ! Third-order IFC
116 :
117 : double precision, allocatable :: Phi4(:,:,:,:,:)
118 : ! Phi3(3,3,3,3,Shell4at%nshell)
119 : ! Fourth-order IFC
120 :
121 : double precision, allocatable :: Phi1Ui(:)
122 : ! Phi1Ui(my_nstep)
123 : ! First-order IFC contribution to energy
124 :
125 : double precision, allocatable :: Phi2UiUj(:)
126 : ! Phi2UiUj(my_nstep)
127 : ! Second-order IFC contribution to energy
128 :
129 : double precision, allocatable :: Phi3UiUjUk(:)
130 : ! Phi3UiUjUk(my_nstep)
131 : ! Third-order IFC contribution to energy
132 :
133 : double precision, allocatable :: Phi4UiUjUkUl(:)
134 : ! Phi4UiUjUkUl(my_nstep)
135 : ! Fourth-order IFC contribution to energy
136 :
137 : end type tdep_Model_type
138 :
139 : public :: tdep_init_phi2
140 : public :: tdep_destroy_phi2
141 : public :: tdep_model_init
142 : public :: tdep_model_free
143 : public :: tdep_calc_model
144 :
145 : contains
146 :
147 : !=====================================================================================================
148 :
149 46 : subroutine tdep_init_phi2(Phi2,dipdip,natom)
150 :
151 : type(Phi2_type),intent(out) :: Phi2
152 : logical, intent(in) :: dipdip
153 : integer, intent(in) :: natom
154 :
155 13524742 : ABI_CALLOC(Phi2%SR ,(3*natom,3*natom))
156 46 : if (dipdip) then
157 923727 : ABI_CALLOC(Phi2%Tot,(3*natom,3*natom))
158 923727 : ABI_CALLOC(Phi2%LR ,(3*natom,3*natom))
159 : end if
160 :
161 46 : end subroutine tdep_init_phi2
162 :
163 : !=====================================================================================================
164 :
165 46 : subroutine tdep_destroy_phi2(Phi2)
166 :
167 : type(Phi2_type),intent(inout) :: Phi2
168 :
169 46 : ABI_FREE(Phi2%SR)
170 46 : ABI_SFREE(Phi2%Tot)
171 46 : ABI_SFREE(Phi2%LR)
172 :
173 46 : end subroutine tdep_destroy_phi2
174 :
175 : !=====================================================================================================
176 :
177 44 : subroutine tdep_model_init(Model, Invar, Shell3at, Shell4at)
178 :
179 : type(tdep_Model_type),intent(out) :: Model
180 : type(atdep_dataset_type),intent(in) :: Invar
181 : type(Shell_type),intent(in) :: Shell3at, Shell4at
182 :
183 44 : Model%order = Invar%order
184 44 : Model%natom = Invar%natom
185 44 : Model%natom_unitcell = Invar%natom_unitcell
186 44 : Model%my_nstep = Invar%my_nstep
187 44 : Model%nshell3rd = 1
188 44 : Model%nshell4th = 1
189 :
190 44 : Model%U0 = zero
191 :
192 417588 : ABI_CALLOC(Model%Forces, (3*Model%natom*Model%my_nstep))
193 1084 : ABI_CALLOC(Model%Phi1Ui ,(Model%my_nstep))
194 1040 : ABI_CALLOC(Model%Phi2UiUj ,(Model%my_nstep))
195 1040 : ABI_CALLOC(Model%Phi3UiUjUk ,(Model%my_nstep))
196 1040 : ABI_CALLOC(Model%Phi4UiUjUkUl,(Model%my_nstep))
197 :
198 20778 : ABI_CALLOC(Model%Phi1,(3*Model%natom))
199 :
200 44 : call tdep_init_phi2(Model%Phi2,Invar%loto,Invar%natom)
201 :
202 44 : if (Model%order.ge.3) then
203 14 : Model%nshell3rd = Shell3at%nshell
204 2002 : ABI_CALLOC(Model%Phi3,(3,3,3,Model%nshell3rd))
205 : end if
206 :
207 44 : if (Model%order.eq.4) then
208 8 : Model%nshell4th = Shell4at%nshell
209 5590 : ABI_CALLOC(Model%Phi4,(3,3,3,3,Model%nshell4th))
210 : end if
211 :
212 44 : end subroutine tdep_model_init
213 :
214 : !=====================================================================================================
215 :
216 44 : subroutine tdep_model_free(Model)
217 :
218 : type(tdep_Model_type),intent(inout) :: Model
219 :
220 44 : ABI_FREE(Model%Forces)
221 44 : ABI_FREE(Model%Phi1Ui)
222 44 : ABI_FREE(Model%Phi2UiUj)
223 44 : ABI_FREE(Model%Phi3UiUjUk)
224 44 : ABI_FREE(Model%Phi4UiUjUkUl)
225 :
226 44 : ABI_FREE(Model%Phi1)
227 :
228 44 : call tdep_destroy_phi2(Model%Phi2)
229 :
230 44 : if (Model%order.ge.3) then
231 14 : ABI_FREE(Model%Phi3)
232 : end if
233 :
234 44 : if (Model%order.eq.4) then
235 8 : ABI_FREE(Model%Phi4)
236 : end if
237 :
238 44 : end subroutine tdep_model_free
239 :
240 : !====================================================================================================
241 :
242 44 : subroutine tdep_calc_model(Model,MD,Invar,MPIdata)
243 :
244 : type(tdep_Model_type),intent(inout) :: Model
245 : type(tdep_Sampling_type),intent(in) :: MD
246 : type(atdep_dataset_type),intent(in) :: Invar
247 : type(MPI_enreg_type), intent(in) :: MPIdata
248 :
249 : integer :: ii,jj,istep,iatom
250 : double precision :: Delta_F2,Delta_U,Delta_U2
251 : double precision :: sigma,U_1,U_2,U_3,U_4,UMD
252 44 : double precision, allocatable :: tmp(:),Phi_tot(:)
253 44 : double precision, allocatable :: U_MD(:),U_TDEP(:),weights_tot(:)
254 : integer :: ierr
255 :
256 : ! Compute the different contributions to total energy from the model
257 :
258 44 : write(Invar%stdout,*)' '
259 44 : write(Invar%stdout,*) '#############################################################################'
260 44 : write(Invar%stdout,*) '######################### Energies, errors,... #############################'
261 44 : write(Invar%stdout,*) '#############################################################################'
262 :
263 : ! Compute U0, U_TDEP, Delta_U and write them in the output file
264 44 : write(Invar%stdout,'(a)') ' Thermodynamic quantities and convergence parameters of THE MODEL,'
265 44 : write(Invar%stdout,'(a)') ' as a function of the step number (energies in eV/atom and forces in Ha/bohr) :'
266 44 : if (Invar%order.eq.4) then
267 8 : write(Invar%stdout,'(a)') ' <U_TDEP> = U_0 + U_1 + U_2 + U_3 + U_4'
268 8 : write(Invar%stdout,'(2a)') ' with U_0 = < U_MD - sum_i Phi1 ui - 1/2 sum_ij Phi2 ui uj ',&
269 16 : & '- 1/6 sum_ijk Phi3 ui uj uk - 1/24 sum_ijkl Phi4 ui uj uk ul >'
270 8 : write(Invar%stdout,'(a)') ' and U_1 = < sum_i Phi1 ui >'
271 8 : write(Invar%stdout,'(a)') ' and U_2 = < 1/2 sum_ij Phi2 ui uj >'
272 8 : write(Invar%stdout,'(a)') ' and U_3 = < 1/6 sum_ijk Phi3 ui uj uk >'
273 8 : write(Invar%stdout,'(a)') ' and U_4 = < 1/24 sum_ijkl Phi4 ui uj uk ul >'
274 36 : else if (Invar%order.eq.3) then
275 6 : write(Invar%stdout,'(a)') ' <U_TDEP> = U_0 + U_1 + U_2 + U_3'
276 6 : write(Invar%stdout,'(a)') ' with U_0 = < U_MD - sum_i Phi1 ui - 1/2 sum_ij Phi2 ui uj - 1/6 sum_ijk Phi3 ui uj uk >'
277 6 : write(Invar%stdout,'(a)') ' and U_1 = < sum_i Phi1 ui >'
278 6 : write(Invar%stdout,'(a)') ' and U_2 = < 1/2 sum_ij Phi2 ui uj >'
279 6 : write(Invar%stdout,'(a)') ' and U_3 = < 1/6 sum_ijk Phi3 ui uj uk >'
280 : else
281 30 : write(Invar%stdout,'(a)') ' <U_TDEP> = U_0 + U_1 + U_2'
282 30 : write(Invar%stdout,'(a)') ' with U_0 = < U_MD - sum_i Phi1 ui - 1/2 sum_ij Phi2 ui uj >'
283 30 : write(Invar%stdout,'(a)') ' and U_1 = < sum_i Phi1 ui >'
284 30 : write(Invar%stdout,'(a)') ' and U_2 = < 1/2 sum_ij Phi2 ui uj >'
285 : end if
286 44 : write(Invar%stdout,'(a)') ' Delta_U = < U_MD - U_TDEP > '
287 44 : write(Invar%stdout,'(a)') ' Delta_U2= (< (U_MD - U_TDEP)^2 >)**0.5 '
288 44 : write(Invar%stdout,'(a)') ' Delta_F2= (< (F_MD - F_TDEP)^2 >)**0.5 '
289 44 : write(Invar%stdout,'(a)') ' Sigma = (< (F_MD - F_TDEP)^2 >/<F_MD**2>)**0.5 '
290 44 : if (Invar%order.eq.4) then
291 8 : write(Invar%stdout,'(2a)') ' <U_MD> U_0 U_1 U_2 ',&
292 16 : & ' U_3 U_4 Delta_U Delta_U2 Delta_F2 Sigma'
293 36 : else if (Invar%order.eq.3) then
294 6 : write(Invar%stdout,'(2a)') ' <U_MD> U_0 U_1 U_2 ',&
295 12 : & ' U_3 Delta_U Delta_U2 Delta_F2 Sigma'
296 : else
297 30 : write(Invar%stdout,'(2a)') ' <U_MD> U_0 U_1 U_2 ',&
298 60 : & ' Delta_U Delta_U2 Delta_F2 Sigma'
299 : end if
300 :
301 : ! Compute eucledian distance for forces
302 528 : ABI_MALLOC(tmp,(11)) ; tmp(:) =0.d0
303 996 : do istep=1,MD%my_nstep
304 140148 : do iatom=1,MD%natom
305 557560 : do ii=1,3
306 417456 : jj = ii + 3*(iatom-1) + 3*MD%natom*(istep-1)
307 417456 : tmp(4)=tmp(4)+(MD%Forces(jj)-Model%Forces(jj))**2*MD%weights(istep)
308 556608 : tmp(5)=tmp(5)+MD%Forces(jj)**2*MD%weights(istep)
309 : end do
310 : end do
311 : end do
312 : ! Compute energies
313 1084 : ABI_MALLOC(U_TDEP, (MD%nstep_tot)) ; U_TDEP(:)=0.d0
314 1040 : ABI_MALLOC(U_MD, (MD%nstep_tot)) ; U_MD(:) =0.d0
315 1040 : ABI_MALLOC(weights_tot,(MD%nstep_tot)) ; weights_tot(:)=0.d0
316 1084 : ABI_MALLOC(Phi_tot, (MPIdata%my_nstep)); Phi_tot(:)=0.d0
317 996 : do istep=1,MD%my_nstep
318 952 : tmp(7) =tmp(7) +MD%etot(istep)*MD%weights(istep)
319 952 : tmp(10)=tmp(10)+Model%Phi1Ui(istep)*MD%weights(istep)
320 952 : tmp(6) =tmp(6) +Model%Phi2UiUj(istep)*MD%weights(istep)
321 952 : tmp(8) =tmp(8) +Model%Phi3UiUjUk(istep)*MD%weights(istep)
322 996 : tmp(11)=tmp(11)+Model%Phi4UiUjUkUl(istep)*MD%weights(istep)
323 : end do
324 44 : call xmpi_sum(tmp,MPIdata%comm_step,ierr)
325 44 : tmp(1) = tmp(7)-tmp(10)-tmp(6)-tmp(8)-tmp(11)
326 996 : Phi_tot(:)=tmp(1)+Model%Phi1Ui(:)+Model%Phi2UiUj(:)+Model%Phi3UiUjUk(:)+Model%Phi4UiUjUkUl(:)
327 : call xmpi_gatherv(Phi_tot,MD%my_nstep,U_TDEP,MPIdata%nstep_all,MPIdata%shft_step,&
328 44 : & MPIdata%master,MPIdata%comm_step,ierr)
329 : call xmpi_gatherv(MD%etot,MD%my_nstep,U_MD,MPIdata%nstep_all,MPIdata%shft_step,&
330 44 : & MPIdata%master,MPIdata%comm_step,ierr)
331 : call xmpi_gatherv(MD%weights,MD%my_nstep,weights_tot,MPIdata%nstep_all,MPIdata%shft_step,&
332 44 : & MPIdata%master,MPIdata%comm_step,ierr)
333 996 : do istep=1,MD%nstep_tot
334 952 : tmp(2) =tmp(2) + (U_MD(istep)-U_TDEP(istep)) * weights_tot(istep)
335 996 : tmp(9) =tmp(9) + (U_MD(istep)-U_TDEP(istep))**2 * weights_tot(istep)
336 : end do
337 44 : Model%U0 =tmp(1) /real(MD%natom)
338 44 : UMD =tmp(7) /real(MD%natom)
339 44 : U_1 =tmp(10)/real(MD%natom)
340 44 : U_2 =tmp(6) /real(MD%natom)
341 44 : U_3 =tmp(8) /real(MD%natom)
342 44 : U_4 =tmp(11)/real(MD%natom)
343 44 : Delta_U =tmp(2) /real(MD%natom)
344 44 : Delta_U2 =tmp(9) /real(MD%natom)
345 44 : Delta_F2 =tmp(4) /real(MD%natom*3)
346 44 : if (tmp(5).eq.0.d0) then
347 1 : sigma = 0.d0
348 : else
349 43 : sigma = dsqrt(tmp(4)/tmp(5))
350 : end if
351 44 : if (Invar%order.eq.4) then
352 8 : write(Invar%stdout,'(10(f12.5,5x))') UMD*Ha_eV,Model%U0*Ha_eV,U_1*Ha_eV,U_2*Ha_eV,U_3*Ha_eV,U_4*Ha_eV,&
353 16 : & Delta_U*Ha_eV,Delta_U2**0.5*Ha_eV,Delta_F2**0.5,sigma
354 36 : else if (Invar%order.eq.3) then
355 6 : write(Invar%stdout,'(9(f12.5,5x))') UMD*Ha_eV,Model%U0*Ha_eV,U_1*Ha_eV,U_2*Ha_eV,U_3*Ha_eV,&
356 12 : & Delta_U*Ha_eV,Delta_U2**0.5*Ha_eV,Delta_F2**0.5,sigma
357 : else
358 30 : write(Invar%stdout,'(8(f12.5,5x))') UMD*Ha_eV,Model%U0*Ha_eV,U_1*Ha_eV,U_2*Ha_eV,&
359 60 : & Delta_U*Ha_eV,Delta_U2**0.5*Ha_eV,Delta_F2**0.5,sigma
360 : endif
361 44 : ABI_FREE(tmp)
362 44 : write(Invar%stdout,'(a,1x,f12.5)') ' NOTE : in the harmonic and classical limit (T>>T_Debye), U_2=3/2*kB*T=',&
363 88 : & 3.d0/2.d0*kb_HaK*Ha_eV*Invar%temperature
364 :
365 : ! Write : i) (U_TDEP vs U_MD) in etotMDvsTDEP.dat
366 : ! ii) (Model%Forces vs MD%Forces) in fcartMDvsTDEP.dat
367 44 : write(Invar%stdout,'(a)') ' '
368 44 : write(Invar%stdout,'(a)') ' See the etotMDvsTDEP.dat & fcartMDvsTDEP.dat files'
369 44 : if (MPIdata%iam_master) then
370 44 : open(unit=32,file=trim(Invar%output_prefix)//'_etotMDvsTDEP.dat')
371 44 : open(unit=33,file=trim(Invar%output_prefix)//'_fcartMDvsTDEP.dat')
372 44 : write(32,'(a)') '# Istep U_MD(Ha) U_TDEP(Ha)'
373 44 : write(33,'(a)') '# Forces_MD(Ha/bohr) Forces_TDEP(Ha/bohr)'
374 996 : do istep=1,MD%nstep_tot
375 996 : write(32,'(i6,1x,2(f17.6,1x))') istep,U_MD(istep),U_TDEP(istep)
376 : end do
377 996 : do istep=1,MD%my_nstep
378 140148 : do iatom=1,MD%natom
379 557560 : do ii=1,3
380 417456 : write(33,'(2(f17.10,1x))') MD%Forces (ii+3*(iatom-1)+3*MD%natom*(istep-1)),&
381 974064 : & Model%Forces(ii+3*(iatom-1)+3*MD%natom*(istep-1))
382 : end do
383 : end do
384 : end do
385 44 : close(32)
386 44 : close(33)
387 : end if
388 44 : ABI_FREE(U_MD)
389 44 : ABI_FREE(U_TDEP)
390 44 : ABI_FREE(Phi_tot)
391 44 : ABI_FREE(weights_tot)
392 :
393 88 : end subroutine tdep_calc_model
394 :
395 : !====================================================================================================
396 :
397 0 : end module m_tdep_model
398 : !!***
|