Line data Source code
1 : !!****m* ABINIT/m_tdep_sampling
2 : !! NAME
3 : !! m_tdep_sampling
4 : !!
5 : !! FUNCTION
6 : !! This module contains the TDEP Sampling data type
7 : !! which holds the set of configurations from which the IFC will be fit.
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_sampling
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_abihist, only : abihist
31 : use m_tdep_dataset, only : atdep_dataset_type, MPI_enreg_type
32 : use m_tdep_latt, only : Lattice_type, tdep_make_inbox
33 : use m_tdep_sym, only : Symmetries_type, tdep_SearchS_1at
34 :
35 : implicit none
36 :
37 : type tdep_Sampling_type
38 :
39 : integer :: natom
40 : ! Number of atoms in the supercell
41 :
42 : integer :: natom_unitcell
43 : ! Number of atoms in the unitcell
44 :
45 : integer :: my_nstep
46 : ! Number of MD steps held locally
47 :
48 : integer :: nstep_tot
49 : ! Total of MD steps
50 :
51 : integer, allocatable :: typat_unitcell(:)
52 : ! typat_unitcell(natom_unitcell)
53 : ! Atom type in the unitcell.
54 :
55 : integer, allocatable :: typat(:)
56 : ! typat(natom)
57 : ! Atom type in the supercell.
58 :
59 : double precision, allocatable :: xred_unitcell(:,:)
60 : ! xred_unitcell(3, natom_unitcell)
61 : ! Reduced equilibrium position of the atoms in the unitcell.
62 :
63 : double precision, allocatable :: xred_ideal(:,:)
64 : ! xred_ideal(3, natom)
65 : ! Reduced equilibrium position of the atoms in the supercell.
66 :
67 : double precision, allocatable :: xred(:,:,:)
68 : ! xred(3, natom, my_nstep)
69 : ! Reduced position of the atom at each step.
70 :
71 : double precision, allocatable :: fcart(:,:,:)
72 : ! fcart(3, natom, my_nstep)
73 : ! Cartesian forces at each step.
74 :
75 : double precision, allocatable :: etot(:)
76 : ! etot(my_nstep)
77 : ! Total energy at each step.
78 :
79 : double precision, allocatable :: weights(:)
80 : ! weights(my_nstep)
81 : ! The weight of each configuration for the fitting.
82 : ! By default, these will be 1 / nstep_tot.
83 :
84 : double precision, allocatable :: Rlatt_cart(:,:,:)
85 : ! Rlatt_cart(3, natom_unitcell, natom)
86 : ! Cartesian coordinate of the lattice vectors of the unitcell
87 : ! within the supercell, for each atom.
88 :
89 : double precision, allocatable :: Rlatt_scaled(:,:,:)
90 : ! Rlatt_scaled(3, natom_unitcell, natom)
91 : ! Rlatt_cart divided by acell_unitcell.
92 :
93 : double precision, allocatable :: ucart(:,:,:)
94 : ! ucart(3, natom, my_nstep)
95 : ! Cartesian displacements of the atoms with respect to their equilibrium
96 : ! positions at each time step.
97 :
98 : double precision, allocatable :: distance(:,:,:)
99 : ! distance(natom, natom, 4)
100 : ! Distance between the ideal positions of the atoms in the supercell,
101 : ! (norm, and cartesian components).
102 :
103 : double precision, allocatable :: Forces(:)
104 : ! Forces(3*natom*my_nstep)
105 : ! The cartesian forces for all configurations, as a flat array.
106 :
107 : end type tdep_Sampling_type
108 :
109 : public :: tdep_sampling_init_read
110 : public :: tdep_sampling_free
111 : public :: tdep_sampling_shift_xred
112 : public :: tdep_sampling_rotate
113 : public :: tdep_MatchIdeal2Average
114 : public :: tdep_write_xred_average
115 :
116 : contains
117 :
118 : !=====================================================================================================
119 :
120 44 : subroutine tdep_sampling_init_read(MD,Invar,MPIdata,Hist)
121 :
122 : type(tdep_Sampling_type), intent(inout) :: MD
123 : type(atdep_dataset_type), intent(in) :: Invar
124 : type(MPI_enreg_type), intent(in) :: MPIdata
125 : type(abihist), intent(in) :: Hist
126 :
127 : integer :: this_istep,istep,iatom,jstep
128 : double precision :: tmp1,tmp2,tmp3
129 :
130 44 : MD%natom = Invar%natom
131 44 : MD%natom_unitcell = Invar%natom_unitcell
132 44 : MD%my_nstep = Invar%my_nstep
133 44 : MD%nstep_tot = Invar%nstep_tot
134 :
135 238 : ABI_CALLOC(MD%typat_unitcell, (MD%natom_unitcell))
136 7014 : ABI_CALLOC(MD%typat, (MD%natom))
137 556 : ABI_CALLOC(MD%xred_unitcell, (3,MD%natom_unitcell))
138 27660 : ABI_CALLOC(MD%xred_ideal, (3,MD%natom))
139 557736 : ABI_CALLOC(MD%xred, (3,MD%natom,MD%my_nstep))
140 557692 : ABI_CALLOC(MD%fcart, (3,MD%natom,MD%my_nstep))
141 1084 : ABI_CALLOC(MD%etot, (MD%my_nstep))
142 1040 : ABI_CALLOC(MD%weights, (MD%my_nstep))
143 5917156 : ABI_CALLOC(MD%distance, (MD%natom,MD%natom,4))
144 66602 : ABI_CALLOC(MD%Rlatt_scaled, (3,MD%natom_unitcell,MD%natom))
145 66558 : ABI_CALLOC(MD%Rlatt_cart, (3,MD%natom_unitcell,MD%natom))
146 557692 : ABI_CALLOC(MD%ucart, (3,MD%natom,MD%my_nstep))
147 417588 : ABI_CALLOC(MD%Forces, (3*MD%natom*MD%my_nstep))
148 :
149 150 : MD%typat_unitcell(:) = Invar%typat_unitcell(:)
150 468 : MD%xred_unitcell(:,:) = Invar%xred_unitcell(:,:)
151 6926 : MD%typat(:) = Invar%typat(:)
152 :
153 : ! Read xred.dat, fcart.dat and etot.dat ASCII files or extract them from the HIST.nc netcdf file.
154 44 : write(Invar%stdout,'(a)') ' '
155 44 : this_istep=0
156 44 : jstep=0
157 44 : if (Invar%use_weights.eq.1) then
158 1 : open(unit=30,file=trim(Invar%input_prefix)//'_weights.dat')
159 43 : else if (Invar%use_weights.eq.0) then
160 975 : MD%weights=1.0d0/real(MD%nstep_tot)
161 : endif
162 44 : if (Invar%netcdf) then
163 217 : do istep=Invar%nstep_min,Invar%nstep_max
164 217 : if (mod(istep-Invar%nstep_min,Invar%slice).ne.0) then
165 : cycle
166 : else
167 201 : jstep=jstep+1
168 201 : if (.not.MPIdata%my_step(jstep)) cycle
169 201 : this_istep=this_istep+1
170 62441 : MD%xred(:,:,this_istep) =Hist%xred (:,:,istep)
171 62441 : MD%fcart(:,:,this_istep)=Hist%fcart(:,:,istep)
172 211 : MD%etot(this_istep) =Hist%etot (istep)
173 : end if
174 : end do !istep
175 6 : write(Invar%stdout,'(a)') ' The positions, forces and energies are extracted from the NetCDF file: HIST.nc'
176 : else
177 38 : open(unit=60,file=trim(Invar%input_prefix)//'_fcart.dat')
178 38 : open(unit=50,file=trim(Invar%input_prefix)//'_xred.dat')
179 38 : open(unit=40,file=trim(Invar%input_prefix)//'_etot.dat')
180 38 : do istep=1,Invar%nstep_min-1
181 0 : if (Invar%use_weights.eq.1) then
182 0 : read(30,*) tmp1
183 : endif
184 0 : read(40,*) tmp1
185 38 : do iatom=1,MD%natom
186 0 : read(50,*) tmp1,tmp2,tmp3
187 0 : read(60,*) tmp1,tmp2,tmp3
188 : end do
189 : end do
190 799 : do istep=Invar%nstep_min,Invar%nstep_max
191 799 : if (mod(istep-Invar%nstep_min,Invar%slice).ne.0) then
192 10 : if (Invar%use_weights.eq.1) then
193 0 : read(30,*) tmp1
194 : endif
195 10 : read(40,*) tmp1
196 1290 : do iatom=1,Invar%natom
197 1280 : read(50,*) tmp1,tmp2,tmp3
198 1290 : read(60,*) tmp1,tmp2,tmp3
199 : end do
200 : else
201 751 : jstep=jstep+1
202 751 : if (.not.MPIdata%my_step(jstep)) then
203 0 : if (Invar%use_weights.eq.1) then
204 0 : read(30,*) tmp1
205 : endif
206 0 : read(40,*) tmp1
207 0 : do iatom=1,Invar%natom
208 0 : read(50,*) tmp1,tmp2,tmp3
209 0 : read(60,*) tmp1,tmp2,tmp3
210 : end do
211 : else
212 751 : this_istep=this_istep+1
213 751 : if (Invar%use_weights.eq.1) then
214 20 : read(30,*) MD%weights(this_istep)
215 : endif
216 751 : read(40,*) MD%etot(this_istep)
217 124343 : do iatom=1,MD%natom
218 123592 : read(50,*) MD%xred (1,iatom,this_istep),MD%xred (2,iatom,this_istep),MD%xred (3,iatom,this_istep)
219 124343 : read(60,*) MD%fcart(1,iatom,this_istep),MD%fcart(2,iatom,this_istep),MD%fcart(3,iatom,this_istep)
220 : end do
221 : end if !my_step
222 : end if !slice
223 : end do !istep
224 38 : close(40)
225 38 : close(50)
226 38 : close(60)
227 38 : write(Invar%stdout,'(2a)') ' The positions, forces and energies are extracted from the ASCII files:',&
228 76 : & ' xred.dat, fcart.dat & etot.dat'
229 : end if !netcdf
230 44 : if (Invar%use_weights.eq.1) then
231 1 : close(30)
232 : end if
233 :
234 44 : end subroutine tdep_sampling_init_read
235 :
236 : !=====================================================================================================
237 :
238 44 : subroutine tdep_sampling_free(MD)
239 :
240 : type(tdep_Sampling_type), intent(inout) :: MD
241 :
242 44 : ABI_FREE(MD%typat_unitcell)
243 44 : ABI_FREE(MD%typat)
244 44 : ABI_FREE(MD%xred_unitcell)
245 44 : ABI_FREE(MD%xred_ideal)
246 44 : ABI_FREE(MD%xred)
247 44 : ABI_FREE(MD%fcart)
248 44 : ABI_FREE(MD%etot)
249 44 : ABI_FREE(MD%weights)
250 44 : ABI_FREE(MD%distance)
251 44 : ABI_FREE(MD%Rlatt_scaled)
252 44 : ABI_FREE(MD%Rlatt_cart)
253 44 : ABI_FREE(MD%ucart)
254 44 : ABI_FREE(MD%Forces)
255 :
256 44 : end subroutine tdep_sampling_free
257 :
258 : !=====================================================================================================
259 :
260 : ! Shift xred to keep atoms in the same unit cell at each step.
261 44 : subroutine tdep_sampling_shift_xred(MD,MPIdata)
262 :
263 : type(tdep_Sampling_type), intent(inout) :: MD
264 : type(MPI_enreg_type), intent(in) :: MPIdata
265 : integer :: natom,ii,iatom,istep,ierr
266 : integer :: shift,shift_max,shift_best
267 : double precision :: xi, dist, best_dist
268 44 : double precision, allocatable :: x0(:,:)
269 :
270 44 : natom = MD%natom
271 132 : ABI_MALLOC(x0,(3,natom))
272 :
273 : ! Communicate xred at the first step
274 27572 : x0(:,:) = zero
275 44 : if (MPIdata%my_step(1)) then
276 27572 : x0(:,:) = MD%xred(:,:,1)
277 : end if
278 44 : call xmpi_sum(x0,MPIdata%comm_step,ierr)
279 :
280 : ! Shift xred from all steps in the same unitcell as the first step
281 44 : shift_max = 1
282 996 : do istep=1, MD%my_nstep
283 140148 : do iatom=1,natom
284 557560 : do ii=1,3
285 417456 : best_dist = abs(MD%xred(ii,iatom,istep) - x0(ii,iatom))
286 417456 : shift_best = 0
287 1669824 : do shift=-shift_max,shift_max
288 1252368 : xi = MD%xred(ii,iatom,istep) + shift
289 1252368 : dist = abs(xi - x0(ii,iatom))
290 1669824 : if (dist < best_dist) then
291 366 : best_dist = dist
292 366 : shift_best = shift
293 : end if
294 : end do
295 556608 : MD%xred(ii,iatom,istep) = MD%xred(ii,iatom,istep) + shift_best
296 : end do
297 : end do
298 : end do
299 :
300 44 : ABI_FREE(x0)
301 :
302 44 : end subroutine tdep_sampling_shift_xred
303 :
304 : !=====================================================================================================
305 :
306 44 : subroutine tdep_sampling_rotate(MD,rotation_cart)
307 :
308 : type(tdep_Sampling_type), intent(inout) :: MD
309 : integer :: iatom,istep
310 : double precision :: rotation_cart(3,3)
311 :
312 : ! Apply rotation to fcart
313 996 : do istep=1,MD%my_nstep
314 140148 : do iatom=1,MD%natom
315 2783992 : MD%fcart(:,iatom,istep) = MATMUL(rotation_cart, MD%fcart(:,iatom,istep))
316 : end do
317 : end do
318 :
319 44 : end subroutine tdep_sampling_rotate
320 :
321 : !=====================================================================================================
322 :
323 : !!***
324 : !!****f* ABINIT/m_tdep_sampling/tdep_MatchIdeal2Average
325 : !! NAME
326 : !! tdep_MatchIdeal2Average
327 : !!
328 : !! FUNCTION
329 : !! Find the mapping between the atoms in the ideal (equilibrium) supercell,
330 : !! and the atoms of the input moledular dynamics using their average positions.
331 : !! Then compute the atom displacements with respect to the equilibrium positions
332 : !! at each time step of the MD.
333 : !!
334 : !! INPUTS
335 : !! MD = TDEP Sampling object containing the input positions and forces.
336 : !! Invar = Input object containing the input variables.
337 : !! Lattice = Lattice object describing the ideal structure.
338 : !! Sym = Symetries object describing all the symmetry operations of the crystal.
339 : !! MPIdata = Info on MPI parallelism.
340 : !!
341 : !! OUTPUT
342 : !!
343 : !! SIDE EFFECTS
344 : !! The following quantities in MD are computed:
345 : !!
346 : !! distance = Distance between the ideal positions of the atoms in the supercell,
347 : !! (norm, and cartesian components).
348 : !! Forces = Cartesian forces on the atoms at each time steps, as a flat array.
349 : !! ucart = Cartesian displacements of the atoms with respect to their equilibrium
350 : !! positions at each time step.
351 : !! Rlatt_cart = Cartesian coordinate of the lattice vectors of the unitcell
352 : !! within the supercell, for each atom.
353 : !! This array seems to have an extra dimension, for algorithmic simplicity.
354 : !! Rlatt_scaled = Rlatt_cart divided by acell_unitcell.
355 : !! These are used when reading an IFC file, to compare with the R vectors
356 : !! that are stored in the file.
357 : !!
358 : !! Some of the reduced positions of the atoms MD%xred are shifted by a supercell
359 : !! lattice vector in order to re-center the crystal.
360 : !!
361 : !! NOTES
362 : !!
363 : !! SOURCE
364 :
365 44 : subroutine tdep_MatchIdeal2Average(MD,Invar,Lattice,Sym,MPIdata)
366 :
367 : type(tdep_Sampling_type),intent(inout) :: MD
368 : type(atdep_dataset_type),intent(inout) :: Invar
369 : type(Lattice_type),intent(in) :: Lattice
370 : type(Symmetries_type),intent(inout) :: Sym
371 : type(MPI_enreg_type),intent(in) :: MPIdata
372 :
373 : integer :: ii,jj,kk,max_ijk,iatcell,jatcell,iatom,jatom,eatom,fatom,istep
374 : integer :: iatom_ref,ierr
375 : integer :: ndir_match,natom_match
376 : double precision :: tmp(3),tmp1(3),tmp2(3),Rlatt(3),xred_tmp(3),rprimd_md_tmp(3,3),distance_tmp(3)
377 44 : double precision, allocatable :: dist_unitcell(:,:,:),xcart_average(:,:)
378 44 : double precision, allocatable :: fcart_tmp(:,:,:),ucart_tmp(:,:,:)
379 44 : double precision, allocatable :: xred_average(:,:)
380 44 : double precision, allocatable :: xred_center(:,:)
381 44 : double precision, allocatable :: Rlatt_red (:,:,:)
382 44 : double precision, allocatable :: xred_ideal(:,:)
383 : ! double precision, allocatable :: distance_average(:,:,:)
384 44 : integer, allocatable :: FromIdeal2Average(:)
385 44 : double precision, allocatable :: xcart(:,:,:)
386 44 : double precision, allocatable :: xcart_ideal(:,:)
387 : logical :: ok,must_shift,discard_R
388 : character(len=500) :: msg
389 :
390 44 : write(Invar%stdout,*)' '
391 44 : write(Invar%stdout,*) '#############################################################################'
392 44 : write(Invar%stdout,*) '###### Find the matching between ideal and average positions ###############'
393 44 : write(Invar%stdout,*) '#############################################################################'
394 :
395 : !==========================================================================================
396 : !======== 1/ Determine ideal positions and distances ======================================
397 : !==========================================================================================
398 44 : write(Invar%stdout,*)' Determine ideal positions and distances...'
399 : ! Define the bigbox with ideal positions
400 66602 : ABI_CALLOC(Rlatt_red ,(3,MD%natom_unitcell,MD%natom))
401 27660 : ABI_CALLOC(xred_ideal,(3,MD%natom))
402 44 : max_ijk=20
403 44 : iatom=1
404 1848 : do ii=-max_ijk,max_ijk
405 75812 : do jj=-max_ijk,max_ijk
406 3108292 : do kk=-max_ijk,max_ijk
407 :
408 3032524 : Rlatt(1)=real(ii-1)
409 3032524 : Rlatt(2)=real(jj-1)
410 3032524 : Rlatt(3)=real(kk-1)
411 :
412 3032524 : discard_R = .false.
413 10412114 : do iatcell=1,MD%natom_unitcell
414 :
415 7305626 : if (discard_R) cycle
416 :
417 : ! Compute the reduced positions
418 12141444 : tmp(:) = Rlatt(:) + MD%xred_unitcell(:,iatcell)
419 3035361 : call DGEMV('T',3,3,1.d0,Lattice%multiplicitym1(:,:),3,tmp(:),1,0.d0,xred_tmp(:),1)
420 :
421 : ! If the first atom of the pattern is in the [0;1[ range then keep all the
422 : ! atoms of the pattern (even if the others are outside the box). Else,
423 : ! none are taken.
424 3035361 : if (iatcell==1) then
425 27292716 : if (minval(xred_tmp(:)).lt.0.d0.or.maxval(xred_tmp(:)).ge.(1.d0-tol12)) then
426 : discard_R = .true.
427 : cycle
428 : end if
429 : end if
430 :
431 : !GA: Why natom+1 ?
432 6882 : if (iatom.gt.(MD%natom+1)) then
433 0 : ABI_ERROR('The number of atoms found in the bigbox exceeds natom' )
434 : end if
435 :
436 27528 : xred_ideal(:,iatom) = xred_tmp(:)
437 6882 : call DGEMV('T',3,3,1.d0,Lattice%multiplicitym1(:,:),3,Rlatt(:),1,0.d0,Rlatt_red(:,1,iatom),1)
438 7309671 : iatom = iatom + 1
439 : end do
440 : end do
441 : end do
442 : end do
443 :
444 44 : if (iatom.lt.MD%natom+1) then
445 0 : ABI_ERROR('The number of atoms found in the big box is smaller than natom')
446 : end if
447 :
448 : ! Compute the distances between ideal positions in the SUPERcell
449 6926 : do eatom=1,MD%natom
450 1479234 : do fatom=1,MD%natom
451 5889232 : tmp(:)=xred_ideal(:,fatom)-xred_ideal(:,eatom)
452 1472308 : call tdep_make_inbox(tmp,1,1d-4)
453 19140004 : rprimd_md_tmp(:,:)=Lattice%rprimd_md(:,:)
454 5889232 : distance_tmp(:)=MD%distance(eatom,fatom,2:4)
455 1472308 : call DGEMV('T',3,3,1.d0,rprimd_md_tmp,3,tmp,1,0.d0,distance_tmp,1)
456 5889232 : MD%distance(eatom,fatom,2:4)=distance_tmp(:)
457 5889232 : do ii=1,3
458 : ! Remove the rounding errors before writing (for non regression testing purposes)
459 4416924 : if (abs(MD%distance(eatom,fatom,ii+1)).lt.tol8) MD%distance(eatom,fatom,ii+1)=zero
460 5889232 : MD%distance(eatom,fatom,1)=MD%distance(eatom,fatom,1)+(MD%distance(eatom,fatom,ii+1))**2
461 : end do
462 1472308 : MD%distance(eatom,fatom,1)=MD%distance(eatom,fatom,1)**0.5
463 1479190 : MD%distance(eatom,fatom,1)=tol12 * dint(MD%distance(eatom,fatom,1) / tol12)
464 : end do
465 : end do
466 :
467 : ! Compute the distances between ideal positions in the UNITcell
468 2212 : ABI_MALLOC(dist_unitcell,(MD%natom_unitcell,MD%natom_unitcell,3)); dist_unitcell(:,:,:)=zero
469 150 : do iatcell=1,MD%natom_unitcell
470 664 : do jatcell=1,MD%natom_unitcell
471 2056 : tmp(:) = xred_ideal(:,jatcell)-xred_ideal(:,iatcell)
472 514 : call tdep_make_inbox(tmp,1,tol8)
473 2162 : dist_unitcell(iatcell,jatcell,:) = tmp(:)
474 : end do
475 : end do
476 :
477 : !==========================================================================================
478 : !======== 2/ Find the matching between the ideal and average ==============================
479 : !======== (from the MD simulations) positions. ==========================================
480 : !==========================================================================================
481 : ! NOTE: - xred_center is used to find the matching with the ideal positions
482 : ! - xred_average is used to compute the displacements (from MD trajectories)
483 : ! The difference between those two is that xred_center will be shifted to bring
484 : ! one of the average positions at the origin, for an easier comparison with
485 : ! xred_ideal. Some shifts by a supercell lattice vector will be computed
486 : ! from the difference between xred_center and xred_ideal, and those shifts
487 : ! will be applied to xred_average and xred at all steps.
488 :
489 44 : write(Invar%stdout,*)' Compute average positions...'
490 27660 : ABI_CALLOC(xred_average,(3,MD%natom))
491 27616 : ABI_CALLOC(xred_center,(3,MD%natom))
492 : ! Average positions from MD (on nstep steps)
493 996 : do istep=1,MD%my_nstep
494 140148 : do iatom=1,MD%natom
495 557560 : xred_average(:,iatom)=xred_average(:,iatom)+MD%xred(:,iatom,istep)
496 : end do
497 : end do
498 44 : call xmpi_sum(xred_average,MPIdata%comm_step,ierr)
499 27572 : xred_average(:,:) = xred_average(:,:) / real(MD%nstep_tot)
500 :
501 : ! Search the basis of atoms in the supercell
502 : ! in order to find iatom_ref
503 44 : write(Invar%stdout,*)' Search the unitcell basis of atoms in the MD trajectory...'
504 44 : ok=.false.
505 27572 : xred_center(:,:) = xred_average(:,:)
506 44 : iatcell=1
507 51 : do iatom=1,MD%natom
508 51 : if (MD%typat(iatom).ne.MD%typat_unitcell(iatcell)) cycle
509 51 : natom_match = 0
510 7797 : do jatom=1,MD%natom
511 :
512 30984 : tmp(:)=xred_center(:,jatom)-xred_center(:,iatom)
513 7746 : call tdep_make_inbox(tmp,1,Invar%tolinbox)
514 :
515 24087 : do jatcell=1,MD%natom_unitcell
516 16403 : if (MD%typat(jatom).ne.MD%typat_unitcell(jatcell)) cycle
517 14263 : ndir_match = 0
518 57052 : do ii=1,3
519 57052 : if (abs(tmp(ii)-dist_unitcell(iatcell,jatcell,ii)).le.Invar%tolmotif) then
520 5723 : ndir_match=ndir_match+1
521 : end if
522 : end do
523 21896 : if (ndir_match==3) then
524 113 : natom_match = natom_match + 1
525 113 : exit
526 : end if
527 : end do
528 : end do
529 51 : if (natom_match.eq.MD%natom_unitcell) then
530 : iatom_ref = iatom
531 : ok=.true.
532 : exit
533 7 : else if (natom_match.gt.MD%natom_unitcell) then
534 0 : write(msg,'(5a)') 'Too many atoms match the unit cell.',ch10,&
535 0 : 'Perhaps the value of tolmotif is too large,',ch10,&
536 0 : 'or the value of tolinbox is too small.'
537 0 : ABI_ERROR(msg)
538 : endif
539 : end do
540 : if (.not.ok) then
541 0 : call tdep_write_xred_average(Invar,MPIdata,Lattice,xred_ideal,xred_center)
542 0 : write(msg,'(3a)') 'The basis of atoms written in input.in file does not appear in the MD trajectory.',ch10,&
543 0 : 'Perhaps, you can adjust the tolerance (tolmotif).'
544 0 : ABI_ERROR(msg)
545 : end if
546 44 : ABI_FREE(dist_unitcell)
547 :
548 44 : write(Invar%stdout,*)' Compare ideal and average positions using PBC...'
549 : ! Modification of xred and Rlatt tabs
550 : ! for averaged quantities: xred_center, xred_average, xred
551 : ! 1/ The "iatom_ref" atom is put in (0.0;0.0;0.0)
552 176 : tmp(:) = xred_center(:,iatom_ref)
553 6926 : do jatom=1,MD%natom
554 27572 : xred_center(:,jatom) = xred_center(:,jatom) - tmp(:)
555 : end do
556 : ! 2/ All the atoms are put in the range [-0.5;0.5[ (use of PBC)
557 6926 : do jatom=1,MD%natom
558 27528 : tmp(:)=xred_center(:,jatom)
559 6882 : call tdep_make_inbox(tmp,1,Invar%tolinbox,xred_center(:,jatom))
560 6882 : call tdep_make_inbox(tmp,1,Invar%tolinbox,xred_average(:,jatom))
561 146078 : do istep=1,MD%my_nstep
562 146034 : call tdep_make_inbox(tmp,1,Invar%tolinbox,MD%xred(:,jatom,istep))
563 : end do
564 : end do
565 : ! Modification of xred and Rlatt tabs
566 : ! for ideal quantities: Rlatt_red et xred_ideal
567 : ! 1/ The atom 1 is put in (0.0;0.0;0.0)
568 176 : tmp1(:)=xred_ideal(:,1)
569 176 : tmp2(:)=Rlatt_red(:,1,1)
570 6926 : do jatom=1,MD%natom
571 27528 : xred_ideal(:,jatom)= xred_ideal(:,jatom) -tmp1(:)
572 27572 : Rlatt_red (:,1,jatom)=Rlatt_red (:,1,jatom)-tmp2(:)
573 : end do
574 : ! 2/ All the atoms are put in the range [-0.5;0.5[ (use of PBC)
575 6926 : do jatom=1,MD%natom
576 27528 : tmp(:)=xred_ideal(:,jatom)
577 6882 : call tdep_make_inbox(tmp,1,tol8,xred_ideal(:,jatom))
578 6926 : call tdep_make_inbox(tmp,1,tol8,Rlatt_red(:,1,jatom))
579 : !FB call tdep_make_inbox(Rlatt_red(:,1,jatom),1,tol8)
580 : end do
581 :
582 : ! When the multiplicity equals 1 along one direction, there is some trouble
583 : ! To clean!!!!!!!
584 176 : do ii=1,3
585 : if ((Invar%multiplicity(ii,ii).eq.1).and.(Invar%multiplicity(ii,mod(ii ,3)+1).eq.0)&
586 176 : & .and.(Invar%multiplicity(ii,mod(ii+1,3)+1).eq.0)) then
587 65 : Rlatt_red(ii,1,:)=0.d0
588 1 : write(Invar%stdout,*) 'WARNING: multiplicity=1 for ii=',ii
589 : end if
590 : end do
591 :
592 : ! Define Rlatt for all the atoms in the basis (Rlatt_red varies as a function of iatcell)
593 44 : if (MD%natom_unitcell.gt.1) then
594 93 : do iatcell=2,MD%natom_unitcell
595 32109 : Rlatt_red(:,iatcell,:)=Rlatt_red(:,1,:)
596 : end do
597 : end if
598 6926 : do iatom=1,MD%natom
599 21812 : do iatcell=1,MD%natom_unitcell
600 59544 : tmp(:)=xred_ideal(:,iatom)-xred_ideal(:,iatcell)
601 21768 : call tdep_make_inbox(tmp,1,tol8,Rlatt_red(:,iatcell,iatom))
602 : end do
603 : end do
604 44 : if (Invar%debug) then
605 12 : do iatcell=1,MD%natom_unitcell
606 10 : write(Invar%stdout,*) 'For iatcell=',iatcell
607 1036 : do jatom=1,MD%natom
608 1034 : write(Invar%stdout,'(a,i4,a,3(f16.10,1x))') 'For jatom=',jatom,', Rlatt=',Rlatt_red(1:3,iatcell,jatom)
609 : end do
610 : end do
611 : end if
612 :
613 : ! Matching between Ideal and Average positions: xred_ideal and xred_center
614 : ! Then, write them in the xred_average.xyz file.
615 44 : write(Invar%stdout,*)' Write the xred_average.xyz file with ideal and average positions...'
616 7014 : ABI_CALLOC(FromIdeal2Average,(MD%natom))
617 6926 : do iatom=1,MD%natom
618 6882 : ok =.false.
619 739595 : do jatom=1,MD%natom
620 739595 : if (MD%typat(iatom).ne.MD%typat_unitcell(mod(jatom-1,MD%natom_unitcell)+1)) cycle
621 624459 : must_shift=.false.
622 624459 : ndir_match=0
623 2497836 : do ii=1,3
624 2497836 : if (abs(xred_center(ii,iatom)-xred_ideal(ii,jatom)).le.Invar%tolmatch) then
625 246347 : ndir_match=ndir_match+1
626 : else if ((abs(xred_center(ii,iatom)-xred_ideal(ii,jatom)-1.d0).le.Invar%tolmatch) &
627 1627030 : & .or.(abs(xred_center(ii,iatom)-xred_ideal(ii,jatom)+1.d0).le.Invar%tolmatch)) then
628 1114 : ndir_match=ndir_match+1
629 1114 : must_shift=.true.
630 : endif
631 : end do
632 624459 : if (ndir_match==3.and..not.must_shift) then
633 6882 : FromIdeal2Average(jatom)=iatom
634 : ok=.true.
635 : exit
636 617577 : else if (ndir_match==3.and.must_shift) then
637 0 : do ii=1,3
638 0 : if (abs(xred_center(ii,iatom)-xred_ideal(ii,jatom)-1.d0).le.Invar%tolmatch) then
639 0 : xred_center(ii,iatom)=xred_center(ii,iatom)-1d0
640 0 : xred_average(ii,iatom)=xred_average(ii,iatom)-1d0
641 0 : do istep=1,MD%my_nstep
642 0 : MD%xred(ii,iatom,istep)=MD%xred(ii,iatom,istep)-1d0
643 : end do
644 0 : FromIdeal2Average(jatom)=iatom
645 0 : else if (abs(xred_center(ii,iatom)-xred_ideal(ii,jatom)+1.d0).le.Invar%tolmatch) then
646 0 : xred_center(ii,iatom)=xred_center(ii,iatom)+1d0
647 0 : xred_average(ii,iatom)=xred_average(ii,iatom)+1d0
648 0 : do istep=1,MD%my_nstep
649 0 : MD%xred(ii,iatom,istep)=MD%xred(ii,iatom,istep)+1d0
650 : end do
651 0 : FromIdeal2Average(jatom)=iatom
652 : end if
653 : end do
654 : ok=.true.
655 : exit
656 : end if
657 : end do
658 44 : if (.not.ok) then
659 0 : write(Invar%stdlog,*) 'Problem to find the average position for iatom=',iatom
660 0 : write(Invar%stdlog,*) ' Reasons:'
661 0 : write(Invar%stdlog,*) ' 1/ One atom jump to another equilibrium position'
662 0 : write(Invar%stdlog,*) ' 2/ The system is no more solid'
663 0 : write(Invar%stdlog,*) ' 3/ Perhaps, you can adjust the tolerance (tolmatch)'
664 0 : write(Invar%stdlog,*) ' xred_center=',(xred_center(ii,iatom),ii=1,3)
665 0 : do eatom=1,MD%natom
666 0 : write(Invar%stdlog,'(a,1x,3(f10.6,1x))') 'I',xred_ideal (:,eatom)
667 0 : write(Invar%stdlog,'(a,1x,3(f10.6,1x))') 'C',xred_center(:,eatom)
668 : end do
669 0 : ABI_ERROR('Problem to find the average position')
670 : end if
671 : end do
672 :
673 : ! WARNING: VERY IMPORTANT: The positions are displayed/sorted
674 : ! (and used in the following) according to ideal positions xred_ideal.
675 44 : call tdep_write_xred_average(Invar,MPIdata,Lattice,xred_ideal,xred_center,FromIdeal2Average)
676 44 : ABI_FREE(xred_center)
677 :
678 : !====================================================================================
679 : !====================== END OF REDUCED COORDINATES ==================================
680 : !====================================================================================
681 : ! a/ Get cartesian coordinates from reduced ones
682 : ! b/ Compute ucart and fcart tabs
683 : ! c/ The atoms are sorted according the IDEAL arrangement
684 : ! The correspondance function is contained in: FromIdeal2Average
685 : ! WARNING : Consequently the arrangement of the xcart* tabs is not modified.
686 44 : write(Invar%stdout,*)' Compute cartesian coordinates and forces...'
687 557736 : ABI_MALLOC(xcart ,(3,MD%natom,MD%my_nstep)); xcart(:,:,:)=0.d0
688 27660 : ABI_MALLOC(xcart_ideal ,(3,MD%natom)) ; xcart_ideal(:,:)=0.d0
689 27616 : ABI_MALLOC(xcart_average,(3,MD%natom)) ; xcart_average(:,:)=0.d0
690 557692 : ABI_MALLOC(ucart_tmp ,(3,MD%natom,MD%my_nstep)); ucart_tmp(:,:,:)=0.d0
691 6926 : do iatom=1,MD%natom
692 6882 : call DGEMV('T',3,3,1.d0,Lattice%rprimd_md(:,:),3,xred_ideal (:,iatom),1,0.d0,xcart_ideal (:,iatom),1)
693 6882 : call DGEMV('T',3,3,1.d0,Lattice%rprimd_md(:,:),3,xred_average(:,iatom),1,0.d0,xcart_average(:,iatom),1)
694 21812 : do iatcell=1,MD%natom_unitcell
695 21768 : call DGEMV('T',3,3,1.d0,Lattice%rprimd_md(:,:),3,Rlatt_red(:,iatcell,iatom),1,0.d0,MD%Rlatt_cart(:,iatcell,iatom),1)
696 : end do
697 : end do
698 996 : do istep=1,MD%my_nstep
699 140148 : do iatom=1,MD%natom
700 139152 : jatom = FromIdeal2Average(iatom)
701 : call DGEMV('T',3,3,1.d0,Lattice%rprimd_md(:,:),3,MD%xred(:,jatom,istep),&
702 139152 : & 1,0.d0,xcart(:,jatom,istep),1)
703 140104 : if (Invar%use_ideal_positions.eq.0) then
704 115648 : ucart_tmp(:,iatom,istep) = xcart(:,jatom,istep) - xcart_average(:,jatom)
705 : else
706 440960 : ucart_tmp(:,iatom,istep) = xcart(:,jatom,istep) - xcart_ideal(:,iatom)
707 : end if
708 : end do
709 : end do
710 44 : ABI_FREE(xred_average)
711 44 : ABI_FREE(xcart)
712 44 : ABI_FREE(xcart_ideal)
713 44 : ABI_FREE(xcart_average)
714 :
715 : ! Rearrangement of the fcart tabs in column --> MD%Forces
716 557736 : ABI_CALLOC(fcart_tmp,(3,MD%natom,MD%my_nstep))
717 996 : do istep=1,MD%my_nstep
718 140148 : do iatom=1,MD%natom
719 557560 : fcart_tmp(:,iatom,istep) = MD%fcart(:,FromIdeal2Average(iatom),istep)
720 : end do
721 : end do
722 996 : do istep=1,MD%my_nstep
723 140148 : do jatom=1,MD%natom
724 557560 : do ii=1,3
725 417456 : jj = ii + 3*(jatom-1) + 3*MD%natom*(istep-1)
726 417456 : MD%Forces(jj) = fcart_tmp(ii,jatom,istep)
727 556608 : MD%ucart(ii,jatom,istep) = ucart_tmp(ii,jatom,istep)
728 : enddo
729 : enddo
730 : enddo
731 44 : ABI_FREE(FromIdeal2Average)
732 44 : ABI_FREE(ucart_tmp)
733 44 : ABI_FREE(fcart_tmp)
734 :
735 : ! Define Rlatt_scaled, fulfilling the definition of mkphdos (ABINIT routine)
736 176 : do ii=1,3
737 572 : rprimd_md_tmp(ii,:) = Lattice%rprimd_md(ii,:) / Lattice%acell_unitcell(ii)
738 : end do
739 6926 : do iatom=1,MD%natom
740 21812 : do iatcell=1,MD%natom_unitcell
741 21768 : call DGEMV('T',3,3,1.d0,rprimd_md_tmp,3,Rlatt_red(:,iatcell,iatom),1,0.d0,MD%Rlatt_scaled(:,iatcell,iatom),1)
742 : end do
743 : end do
744 :
745 : ! Find the symetry operation between 2 atoms
746 44 : call tdep_SearchS_1at(Invar,MPIdata,Sym,xred_ideal)
747 27572 : MD%xred_ideal(:,:)=xred_ideal(:,:)
748 44 : ABI_FREE(xred_ideal)
749 44 : ABI_FREE(Rlatt_red)
750 :
751 44 : end subroutine tdep_MatchIdeal2Average
752 :
753 : !====================================================================================================
754 :
755 44 : subroutine tdep_write_xred_average(Invar,MPIdata,Lattice,&
756 44 : xred_ideal,xred_center,&
757 44 : FromIdeal2Average)
758 : type(atdep_dataset_type), intent(in) :: Invar
759 : type(MPI_enreg_type),intent(in) :: MPIdata
760 : type(Lattice_type),intent(in) :: Lattice
761 : double precision,intent(in) :: xred_ideal(3,Invar%natom)
762 : double precision,intent(in) :: xred_center(3,Invar%natom)
763 : integer,intent(in),optional :: FromIdeal2Average(Invar%natom)
764 :
765 : integer :: unt
766 : !integer :: natom,natom_unitcell
767 : integer :: iatom,jatom,ii,jj
768 : !logical :: with_xcart
769 44 : integer,allocatable :: ideal2average(:)
770 : double precision :: rprimd(3,3)
771 : double precision :: xred_C(3),xred_I(3),xcart_C(3),xcart_I(3)
772 :
773 44 : if (MPIdata%iam_master) then
774 :
775 572 : rprimd(:,:) = Lattice%rprimd_md(:,:)
776 :
777 132 : ABI_MALLOC(ideal2average,(Invar%natom))
778 6926 : ideal2average(:)=0
779 44 : if (present(FromIdeal2Average)) then
780 6926 : ideal2average(:) = FromIdeal2Average(:)
781 : else
782 0 : do iatom=1,Invar%natom
783 0 : ideal2average(iatom) = iatom
784 : end do
785 : end if
786 :
787 44 : unt=31
788 44 : open(unit=unt,file=trim(Invar%output_prefix)//'_xred_average.xyz')
789 44 : write(unt,'(a,i4)') '# natom = ',Invar%natom
790 44 : write(unt,'(a,i4)') '# natom_unitcell = ',Invar%natom_unitcell
791 572 : write(unt,'(a,9(f4.1,1x))') '# multiplicity = ',((Lattice%multiplicity(ii,jj),jj=1,3),ii=1,3 )
792 44 : write(unt,'(a)') '#'
793 :
794 44 : write(unt,'(a1,1x,a8,2x,a6,2x,2(a5,30x))') '#', 'position', 'iatom', 'xred ', 'xcart'
795 44 : write(unt,'(a)')''
796 :
797 44 : xred_I = zero
798 44 : xred_C = zero
799 6926 : do iatom=1,Invar%natom
800 6882 : jatom = ideal2average(iatom)
801 27528 : xred_I = xred_ideal (:,iatom)
802 27528 : xred_C = xred_center(:,jatom)
803 :
804 6882 : xcart_I(:)=zero
805 6882 : xcart_C(:)=zero
806 6882 : call DGEMV('T',3,3,1.d0,rprimd(:,:),3,xred_I,1,0.d0,xcart_I,1)
807 6882 : call DGEMV('T',3,3,1.d0,rprimd(:,:),3,xred_C,1,0.d0,xcart_C,1)
808 :
809 6882 : write(unt,'(2x,a6,4x,i6,2x,3(f10.6,1x),2x,3(f10.6,1x))')'Ideal ',iatom,xred_I,xcart_I
810 6882 : write(unt,'(2x,a6,4x,i6,2x,3(f10.6,1x),2x,3(f10.6,1x))')'Center',jatom,xred_C,xcart_C
811 6926 : write(unt,'(a)')''
812 :
813 : end do
814 :
815 44 : close(unt)
816 44 : ABI_FREE(ideal2average)
817 : end if
818 :
819 44 : end subroutine tdep_write_xred_average
820 :
821 : !====================================================================================================
822 :
823 139152 : end module m_tdep_sampling
824 : !!***
|