Line data Source code
1 : !!****m* ABINIT/m_fit_data
2 : !!
3 : !! NAME
4 : !! m_fit_data
5 : !!
6 : !! FUNCTION
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2010-2026 ABINIT group (AM)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public Licence, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
14 : !!
15 : !! SOURCE
16 :
17 :
18 : #if defined HAVE_CONFIG_H
19 : #include "config.h"
20 : #endif
21 :
22 : #include "abi_common.h"
23 :
24 : module m_fit_data
25 :
26 : use defs_basis
27 : use m_errors
28 : use m_abicore
29 :
30 : use m_geometry, only : metric
31 :
32 : implicit none
33 : !!***
34 :
35 : !!****t* m_fit_data/training_set_type
36 : !! NAME
37 : !! training_set_type
38 : !!
39 : !! FUNCTION
40 : !! datatype for with all the information for the fit process
41 : !! This structure contains all the information of the training set:
42 : !! - ntime
43 : !! - displacement
44 : !! - du_delta
45 : !! - strain
46 : !! - sqomega
47 : !! - ucvol
48 : !!
49 : !! SOURCE
50 :
51 : type, public :: training_set_type
52 :
53 : integer :: ntime
54 : ! Number of time in the training set
55 :
56 : integer :: natom
57 : ! Number of atoms in the training set
58 :
59 : real(dp), allocatable :: displacement(:,:,:)
60 : ! displacement(3,natom,ntime)
61 : ! displacement array, difference of the position in cartisian coordinates
62 : ! between training set and reference
63 :
64 : real(dp), allocatable :: du_delta(:,:,:,:)
65 : ! du_delta(6,3,natom,ntime)
66 : ! du_delta array, variation of displacement wrt to the strain
67 :
68 : real(dp), allocatable :: strain(:,:)
69 : ! strain(6,ntime)
70 : ! strain array, strain in the training set
71 :
72 : real(dp), allocatable :: sqomega(:)
73 : ! sqomega(ntime)
74 : ! sqomega(itime) = (((ucvol(itime)**(-2.))* ((natom_sc)**(0.5)))**(-1.0/3.0))**2
75 :
76 : real(dp), allocatable :: ucvol(:)
77 : ! ucvol(ntime)
78 : ! ucvol array, volume of the cell in the training set
79 :
80 : end type training_set_type
81 :
82 : !routine for training_set
83 : public :: training_set_init
84 : public :: training_set_free
85 : !!***
86 :
87 : !----------------------------------------------------------------------
88 :
89 : !!****t* m_fit_data/fit_data_type
90 : !! NAME
91 : !! fit_data_type
92 : !!
93 : !! FUNCTION
94 : !!
95 : !! SOURCE
96 :
97 : type, public :: fit_data_type
98 :
99 : integer :: ntime
100 : ! Number of time in the training set
101 :
102 : integer :: natom
103 : ! Number of atoms in the training set
104 :
105 : real(dp),allocatable :: energy_diff(:)
106 : ! energy(ntime)
107 : ! Array with the diffence between energy from training set and energy from initial model.
108 : ! The model constains only harmonic part
109 :
110 : real(dp),allocatable :: fcart_diff(:,:,:)
111 : ! fcart_diff(3,natom,ntime)
112 : ! Array with the diffence between cartesian forces from training set and forces from initial model.
113 : ! The model constains only harmonic part
114 :
115 : real(dp),allocatable :: strten_diff(:,:)
116 : ! strten_diff(6,ntime)
117 : ! Array with the diffence between strain from training set and strain from initial model.
118 : ! The model constains only harmonic part
119 :
120 : type(training_set_type) :: training_set
121 : ! datatype with the information of the training set
122 :
123 : end type fit_data_type
124 :
125 : !routine for fit_data
126 : public :: fit_data_compute
127 : public :: fit_data_init
128 : public :: fit_data_free
129 : !!***
130 :
131 : CONTAINS !===========================================================================================
132 :
133 : !!****f* m_fit_data/fit_data_init
134 : !!
135 : !! NAME
136 : !! fit_data_init
137 : !!
138 : !! FUNCTION
139 : !! Initialize fit_data datatype
140 : !!
141 : !! INPUTS
142 : !! energy_diff(3,natom,ntime) = Difference of energy between DFT calculation and
143 : !! fixed part of the model (more often harmonic part)
144 : !! fcart_diff(3,natom,ntime) = Difference of cartesian forces between DFT calculation and
145 : !! fixed part of the model (more often harmonic part)
146 : !! natom = Number of atoms
147 : !! ntime = Number of time (number of snapshot, number of md step...)
148 : !! strten_diff(6,natom) = Difference of stress tensor between DFT calculation and
149 : !! fixed part of the model (more often harmonic part)
150 : !! sqomega(ntime) = Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]]
151 : !! ucvol(ntime) = Volume of the system for each time
152 : !! ts<training_set_type> = datatype with the information about the training set
153 : !!
154 : !! OUTPUT
155 : !! fit_data<fit_data_type> = fit_data datatype to be initialized
156 : !!
157 : !! SOURCE
158 :
159 42 : subroutine fit_data_init(fit_data,energy_diff,fcart_diff,natom,ntime,strten_diff,ts)
160 :
161 : !Arguments ------------------------------------
162 : !scalars
163 : integer,intent(in) :: natom,ntime
164 : !arrays
165 : real(dp),intent(in) :: energy_diff(ntime),fcart_diff(3,natom,ntime)
166 : real(dp),intent(in) :: strten_diff(6,ntime)
167 : type(training_set_type),intent(in) :: ts
168 : type(fit_data_type),intent(inout) :: fit_data
169 : !Local variables-------------------------------
170 : !scalar
171 : !arrays
172 : character(len=500) :: message
173 : ! *************************************************************************
174 :
175 42 : if(natom /= ts%natom)then
176 : write(message, '(a)')&
177 0 : & ' The number of atoms does not correspond to the training set'
178 0 : ABI_BUG(message)
179 : end if
180 :
181 42 : if(ntime /= ts%ntime)then
182 : write(message, '(a)')&
183 0 : & ' The number of time does not correspond to the training set'
184 0 : ABI_BUG(message)
185 : end if
186 :
187 : !Free the output
188 42 : call fit_data_free(fit_data)
189 :
190 : !Set integer values
191 42 : fit_data%ntime = ntime
192 42 : fit_data%natom = natom
193 :
194 : !allocate arrays
195 168 : ABI_MALLOC(fit_data%fcart_diff,(3,natom,ntime))
196 154763 : fit_data%fcart_diff(:,:,:) = fcart_diff(:,:,:)
197 :
198 126 : ABI_MALLOC(fit_data%strten_diff,(6,ntime))
199 6769 : fit_data%strten_diff(:,:) = strten_diff(:,:)
200 :
201 126 : ABI_MALLOC(fit_data%energy_diff,(ntime))
202 1003 : fit_data%energy_diff(:) = energy_diff
203 :
204 : call training_set_init(fit_data%training_set,ts%displacement,ts%du_delta,&
205 42 : & natom,ntime,ts%strain,ts%sqomega,ts%ucvol)
206 :
207 42 : end subroutine fit_data_init
208 : !!***
209 :
210 : !!****f* m_fit_data/fit_data_free
211 : !!
212 : !! NAME
213 : !! fit_data_free
214 : !!
215 : !! FUNCTION
216 : !! Free the fit_data datatype
217 : !!
218 : !! INPUTS
219 : !! fit_data<fit_data_type> = fit_data to be free
220 : !! OUTPUT
221 : !!
222 : !! SOURCE
223 :
224 82 : subroutine fit_data_free(fit_data)
225 :
226 : !Arguments ------------------------------------
227 : !scalars
228 : !arrays
229 : type(fit_data_type),intent(inout) :: fit_data
230 : !Local variables-------------------------------
231 : !scalar
232 : !arrays
233 : ! *************************************************************************
234 :
235 : ! Reset integer values
236 82 : fit_data%ntime = 0
237 82 : fit_data%natom = 0
238 :
239 : ! Deallocate arrays
240 82 : if(allocated(fit_data%energy_diff)) then
241 42 : ABI_FREE(fit_data%energy_diff)
242 : end if
243 82 : if(allocated(fit_data%fcart_diff)) then
244 42 : ABI_FREE(fit_data%fcart_diff)
245 : end if
246 82 : if(allocated(fit_data%strten_diff)) then
247 42 : ABI_FREE(fit_data%strten_diff)
248 : end if
249 82 : call training_set_free(fit_data%training_set)
250 :
251 82 : end subroutine fit_data_free
252 : !!***
253 :
254 : !!****f* m_fit_data/fit_data_compute
255 : !!
256 : !! NAME
257 : !! fit_data_compute
258 : !!
259 : !! FUNCTION
260 : !! Conpute the strain of each configuration.
261 : !! Compute the displacmeent of each configuration.
262 : !! Compute the variation of the displacement due to strain of each configuration.
263 : !! Compute fixed forces and stresse and get the standard deviation.
264 : !! Compute Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]]
265 : !!
266 : !! INPUTS
267 : !! eff_pot<type(effective_potential)> = effective potential
268 : !! hist<type(abihist)> = The history of the MD (or snapshot of DFT
269 : !! comm = MPI communicator
270 : !! verbose = optional, flag for the verbose mode
271 : !!
272 : !! OUTPUT
273 : !! fit_data<fit_data_type> = fit_data is now filled
274 : !!
275 : !! SOURCE
276 :
277 42 : subroutine fit_data_compute(fit_data,eff_pot,hist,comm,verbose)
278 :
279 : use m_strain,only : strain_type,strain_get
280 : use m_effective_potential,only : effective_potential_type,effective_potential_evaluate
281 : use m_effective_potential,only : effective_potential_getDisp
282 : use m_abihist, only : abihist
283 : use m_strain,only : strain_type,strain_get
284 :
285 : !Arguments ------------------------------------
286 : !scalars
287 : integer,intent(in) :: comm
288 : logical,optional,intent(in) :: verbose
289 : !arrays
290 : type(fit_data_type),intent(inout) :: fit_data
291 : type(effective_potential_type),intent(in) :: eff_pot
292 : type(abihist),intent(in) :: hist
293 : !Local variables-------------------------------
294 : !scalar
295 : integer :: ii,itime,natom,ntime
296 : real(dp):: energy
297 : logical :: need_verbose
298 : !arrays
299 : character(len=500) :: message
300 : real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
301 42 : real(dp),allocatable :: energy_diff(:)
302 42 : real(dp),allocatable :: du_delta(:,:,:,:),displacement(:,:,:),strain(:,:)
303 42 : real(dp),allocatable :: fcart_diff(:,:,:),gred_fixed(:,:,:),fcart_fixed(:,:,:)
304 42 : real(dp),allocatable :: strten_diff(:,:),strten_fixed(:,:),sqomega(:),ucvol(:)
305 : type(strain_type) :: strain_t
306 42 : type(training_set_type) :: ts
307 : ! *************************************************************************
308 :
309 : !Initialisation of optional arguments
310 42 : need_verbose = .TRUE.
311 : if(present(verbose)) need_verbose = verbose
312 :
313 : !Checks
314 42 : natom = eff_pot%supercell%natom
315 42 : ntime = hist%mxhist
316 42 : if(natom /= size(hist%xred,2))then
317 : write(message, '(5a)' )&
318 0 : & 'The number of atoms in the hist file does not correspond to the supercell.',ch10,&
319 0 : & 'You should call the routine fit_polynomial_coeff_mapHistToRef before',ch10,&
320 0 : & 'Action: Contact abinit group'
321 0 : ABI_BUG(message)
322 : end if
323 :
324 : !Allocation of temporary arrays
325 168 : ABI_MALLOC(displacement,(3,natom,ntime))
326 168 : ABI_MALLOC(du_delta,(6,3,natom,ntime))
327 126 : ABI_MALLOC(energy_diff,(ntime))
328 126 : ABI_MALLOC(fcart_fixed,(3,natom,ntime))
329 126 : ABI_MALLOC(fcart_diff,(3,natom,ntime))
330 126 : ABI_MALLOC(gred_fixed,(3,natom,ntime))
331 126 : ABI_MALLOC(strain,(6,ntime))
332 84 : ABI_MALLOC(strten_fixed,(6,ntime))
333 84 : ABI_MALLOC(strten_diff,(6,ntime))
334 84 : ABI_MALLOC(sqomega,(ntime))
335 84 : ABI_MALLOC(ucvol,(ntime))
336 :
337 154763 : displacement = zero
338 846683 : du_delta = zero
339 6769 : strain = zero;
340 154763 : fcart_fixed = zero
341 154763 : gred_fixed = zero
342 6769 : strain = zero
343 6769 : strten_fixed = zero
344 6769 : strten_diff = zero
345 1003 : sqomega = zero
346 1003 : ucvol = zero
347 :
348 1003 : do itime=1,ntime
349 : ! Get strain
350 : call strain_get(strain_t,rprim=eff_pot%supercell%rprimd,&
351 961 : & rprim_def=hist%rprimd(:,:,itime),symmetrized=.FALSE.)
352 961 : if (strain_t%name /= "reference") then
353 3844 : do ii=1,3
354 3844 : strain(ii,itime) = strain_t%strain(ii,ii)
355 : end do
356 961 : strain(4,itime) = (strain_t%strain(2,3) + strain_t%strain(3,2))
357 961 : strain(5,itime) = (strain_t%strain(3,1) + strain_t%strain(1,3))
358 961 : strain(6,itime) = (strain_t%strain(2,1) + strain_t%strain(1,2))
359 : else
360 0 : strain(:,itime) = zero
361 : end if
362 :
363 : ! Get displacement and du_delta
364 : call effective_potential_getDisp(displacement(:,:,itime),du_delta(:,:,:,itime),natom,&
365 : & hist%rprimd(:,:,itime),eff_pot%supercell%rprimd,comm,&
366 : & xred_hist=hist%xred(:,:,itime),xcart_ref=eff_pot%supercell%xcart,&
367 961 : & compute_displacement=.TRUE.,compute_duDelta=.TRUE.)
368 :
369 : ! Get forces and stresses from harmonic part (fixed part)
370 : call effective_potential_evaluate(eff_pot,energy,fcart_fixed(:,:,itime),gred_fixed(:,:,itime),&
371 : & strten_fixed(:,itime),natom,hist%rprimd(:,:,itime),&
372 : & displacement=displacement(:,:,itime),&
373 : & du_delta=du_delta(:,:,:,itime),strain=strain(:,itime),&
374 961 : & compute_anharmonic=.true.,verbose=.FALSE.)
375 :
376 : ! Compute \Omega^{2} and ucvol for each time
377 961 : call metric(gmet,gprimd,-1,rmet,hist%rprimd(:,:,itime),ucvol(itime))
378 : ! Formula: sqomega(itime) = (((ucvol(itime)**(-2.))* ((natom)**(0.5)))**(-1.0/3.0))**2
379 : ! Compact form:
380 961 : sqomega(itime) = ((ucvol(itime)**(4.0/3.0)) / ((natom)**(1/3.0)))
381 :
382 : ! Compute the difference between History and model (fixed part)
383 154721 : fcart_diff(:,:,itime) = hist%fcart(:,:,itime) - fcart_fixed(:,:,itime)
384 961 : energy_diff(itime) = hist%etot(itime) - energy
385 6769 : strten_diff(:,itime) = hist%strten(:,itime) - strten_fixed(:,itime)
386 : end do ! End Loop itime
387 :
388 : !Set the training set
389 42 : call training_set_init(ts,displacement,du_delta,natom,ntime,strain,sqomega,ucvol)
390 : !Set the fit_data
391 42 : call fit_data_init(fit_data,energy_diff,fcart_diff,natom,ntime,strten_diff,ts)
392 :
393 : !Free space
394 42 : call training_set_free(ts)
395 42 : ABI_FREE(displacement)
396 42 : ABI_FREE(du_delta)
397 42 : ABI_FREE(energy_diff)
398 42 : ABI_FREE(fcart_fixed)
399 42 : ABI_FREE(fcart_diff)
400 42 : ABI_FREE(gred_fixed)
401 42 : ABI_FREE(strain)
402 42 : ABI_FREE(strten_fixed)
403 42 : ABI_FREE(strten_diff)
404 42 : ABI_FREE(sqomega)
405 42 : ABI_FREE(ucvol)
406 :
407 42 : end subroutine fit_data_compute
408 : !!***
409 :
410 :
411 :
412 :
413 : !!****f* m_fit_data/training_set_init
414 : !!
415 : !! NAME
416 : !! training_set_init
417 : !!
418 : !! FUNCTION
419 : !! Initialize training_set datatype
420 : !!
421 : !! INPUTS
422 : !! du_delta(6,3,natom,ntime) = Variation to displacements wrt to the strain (Bohr)
423 : !! displacement(3,natom,ntime)= Atomic displacement wrt to the reference (Bohr)
424 : !! natom = number of atoms
425 : !! ntime = number of time step
426 : !! strain(6,ntime) = Strain
427 : !! sqomega = Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]]
428 : !! ucvol(ntime) = Volume of the supercell for each time (Bohr^3)
429 : !!
430 : !! OUTPUT
431 : !! ts<training_set_type> = training set to be initialized
432 : !!
433 : !! SOURCE
434 :
435 84 : subroutine training_set_init(ts,displacement,du_delta,natom,ntime,strain,sqomega,ucvol)
436 :
437 : !Arguments ------------------------------------
438 : !scalars
439 : integer,intent(in) :: natom,ntime
440 : !arrays
441 : real(dp),intent(in) :: displacement(3,natom,ntime),du_delta(6,3,natom,ntime)
442 : real(dp),intent(in) :: strain(6,ntime),sqomega(ntime),ucvol(ntime)
443 : type(training_set_type),intent(inout) :: ts
444 : !Local variables-------------------------------
445 : !scalar
446 : !arrays
447 : ! *************************************************************************
448 :
449 : !Free the output
450 84 : call training_set_free(ts)
451 :
452 : !Set integer values
453 84 : ts%ntime = ntime
454 84 : ts%natom = natom
455 :
456 : !allocate arrays
457 336 : ABI_MALLOC(ts%displacement,(3,natom,ntime))
458 309526 : ts%displacement(:,:,:) = displacement(:,:,:)
459 :
460 336 : ABI_MALLOC(ts%du_delta,(6,3,natom,ntime))
461 1693366 : ts%du_delta(:,:,:,:) = du_delta(:,:,:,:)
462 :
463 252 : ABI_MALLOC(ts%strain,(6,ntime))
464 13538 : ts%strain(:,:) = strain(:,:)
465 :
466 252 : ABI_MALLOC(ts%sqomega,(ntime))
467 2006 : ts%sqomega(:) = sqomega(:)
468 :
469 168 : ABI_MALLOC(ts%ucvol,(ntime))
470 2006 : ts%ucvol(:) = ucvol(:)
471 :
472 42 : end subroutine training_set_init
473 : !!***
474 :
475 : !!****f* m_fit_data/training_set_free
476 : !!
477 : !! NAME
478 : !! training_set_free
479 : !!
480 : !! FUNCTION
481 : !! Free the training_set datatype
482 : !!
483 : !! INPUTS
484 : !! training_set<training_set_type> = training_set to be free
485 : !! OUTPUT
486 : !!
487 : !! SOURCE
488 :
489 208 : subroutine training_set_free(ts)
490 :
491 : !Arguments ------------------------------------
492 : !scalars
493 : !arrays
494 : type(training_set_type),intent(inout) :: ts
495 : !Local variables-------------------------------
496 : !scalar
497 : !arrays
498 : ! *************************************************************************
499 :
500 : ! Reset integer values
501 208 : ts%ntime = 0
502 208 : ts%natom = 0
503 :
504 : ! Deallocate arrays
505 208 : if(allocated(ts%displacement)) then
506 84 : ABI_FREE(ts%displacement)
507 : end if
508 208 : if(allocated(ts%du_delta)) then
509 84 : ABI_FREE(ts%du_delta)
510 : end if
511 208 : if(allocated(ts%strain)) then
512 84 : ABI_FREE(ts%strain)
513 : end if
514 208 : if(allocated(ts%sqomega))then
515 84 : ABI_FREE(ts%sqomega)
516 : end if
517 208 : if(allocated(ts%ucvol)) then
518 84 : ABI_FREE(ts%ucvol)
519 : end if
520 :
521 208 : end subroutine training_set_free
522 : !!***
523 :
524 0 : end module m_fit_data
525 : !!***
|