Branch data Line data Source code
1 : : !!****m* ABINIT/m_spin_hist
2 : : !! NAME
3 : : !! m_spin_hist
4 : : !!
5 : : !! FUNCTION
6 : : !! This module contains definition the type spin_hist_t
7 : : !! and its related routines
8 : : !! The observables are also calculated.
9 : : !!
10 : : !! Datatypes:
11 : : !!
12 : : !! * spin_hist_t: history record of spin orientations and amplitudes
13 : : !!
14 : : !! Subroutines:
15 : : !!
16 : : !! * init
17 : : !! * free
18 : : !! * spin_hist_t
19 : : !! * get_S
20 : : !! * findIndex
21 : : !! * set_vars
22 : : !! * set_params
23 : : !!
24 : : !!
25 : : !! COPYRIGHT
26 : : !! Copyright (C) 2001-2026 ABINIT group (hexu)
27 : : !! This file is distributed under the terms of the
28 : : !! GNU General Public License, see ~abinit/COPYING
29 : : !! or http://www.gnu.org/copyleft/gpl.txt .
30 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
31 : : !!
32 : : !! SOURCE
33 : :
34 : : ! TODO hexu:
35 : : ! sync ihist_latt when with lattice dynamics
36 : : ! add average, variance, etc (should they be here?)
37 : : ! structural information and some parameters are no longer
38 : : ! used here. They should be removed form this file.
39 : :
40 : : #if defined HAVE_CONFIG_H
41 : : #include "config.h"
42 : : #endif
43 : :
44 : : #include "abi_common.h"
45 : : module m_spin_hist
46 : : use defs_basis
47 : : use m_abicore
48 : : use m_errors
49 : : use m_xmpi
50 : : implicit none
51 : :
52 : : private
53 : : !!***
54 : :
55 : : !----------------------------------------------------------------------
56 : :
57 : : !!****t* m_spin_hist/spin_hist_t
58 : : !! NAME
59 : : !! spin_hist_t
60 : : !!
61 : : !! FUNCTION
62 : : !! This type has several vectors, and index scalars to store
63 : : !! a proper history of previous evaluations of forces and
64 : : !! stresses,velocities,positions and energies
65 : : !!
66 : : !! It contains:
67 : : !! * mxhist : Maximum size of history
68 : : !! * ihist : index of history
69 : :
70 : : !! natoms : number of atoms
71 : : !! nspin: number of magnetic atoms
72 : : !! * acell(3) : Acell (acell , rprimd, xred: only initial value kept if there is!! no lattice dynamics. Other wise for each step, the corresponding lattice step number is kept)
73 : : !! * rprimd(3,3) : Rprimd
74 : : !! * xred(3,natoms) : Xred
75 : : !! * index_spin : the index of atom in spin model, -1 if it is not in the spin model
76 : : !! * heff(3,nspin,mxhist) : effective magnetic field (cartesian)
77 : : !! * snorm(nspin, mxhist) : magnetitude of spin.
78 : : !! * S(3,nspin,mxhist) : spin orientation of atoms (cartesian)
79 : : !! * dSdt(3, nspin, mxhist) : dS/dt (cartesian)
80 : : !! * etot(mxhist) : Electronic total Energy
81 : : !! * entropy(mxhist) : Entropy
82 : : !! * itime(mxhist) : index of spin dynamics step.
83 : : !! * time(mxhist) : Time (or iteration number for GO)
84 : : !!
85 : : !! * has_latt (whether lattice dynamics is also present)
86 : : !! * ihist_latt(mxhist): the corresponding lattice step. 0 if none.
87 : : !! SOURCE
88 : :
89 : : type, public :: spin_hist_t
90 : : ! scalars
91 : : ! Index of the last element on all records
92 : : integer :: ihist = 0
93 : : integer :: ihist_prev = -1
94 : : ! Maximun size of the historical records
95 : : integer :: mxhist = 0
96 : :
97 : : integer :: nspin, nspin_prim
98 : : ! whether lattice dynamics is also present
99 : : integer, allocatable :: ihist_latt(:)
100 : : logical :: has_latt
101 : :
102 : : ! arrays
103 : : ! placeholders for structure-related parameters. They are not used currently.
104 : : integer :: natoms
105 : : real(dp) :: acell(3)
106 : : real(dp) :: rprimd(3,3)
107 : : real(dp), allocatable :: xred(:, :)
108 : : integer :: ntypat
109 : : integer, allocatable :: typat(:)
110 : : real(dp), allocatable :: znucl(:)
111 : : integer, allocatable :: spin_index(:)
112 : :
113 : : ! spin
114 : : !heff(3, nspin, mxhist)
115 : : real(dp), allocatable :: heff(:, :, :)
116 : : !snorm(nspin, mxhist)
117 : : real(dp), allocatable :: snorm(:, :)
118 : :
119 : : !S(3, nspin, mxhist)
120 : : real(dp), allocatable :: S(:, :, :)
121 : : !dSdt(3, nspin, mxhist)
122 : : ! TODO hexu: is it useful?
123 : : real(dp), allocatable :: dSdt(:, :, :)
124 : :
125 : : ! etot(mxhist)
126 : : real(dp), allocatable :: etot(:)
127 : : real(dp), allocatable :: entropy(:)
128 : : real(dp), allocatable :: time(:)
129 : : integer, allocatable :: itime(:)
130 : :
131 : : ! spin_nctime: interval of step for writing to netcdf hist file.
132 : : integer :: spin_nctime
133 : : real(dp) :: spin_temperature
134 : :
135 : : ! observables
136 : : integer:: calc_thermo_obs, calc_traj_obs, calc_correlation_obs
137 : :
138 : : real(dp), allocatable :: ms_sub(:,:) ! staggered M.
139 : : real(dp), allocatable :: Cv(:) ! specfic heat
140 : : real(dp), allocatable :: binderU4_sub(:,:), binderU4(:)
141 : : real(dp), allocatable :: chi_sub(:, :), chi(:) ! magnetic susceptibility
142 : : real(dp), allocatable :: rcorr(:,:)
143 : : real(dp), allocatable :: sp_corr_func(:,:,:)
144 : : contains
145 : : procedure :: initialize
146 : : procedure :: finalize
147 : : procedure :: reset
148 : : procedure :: set_vars
149 : : procedure :: get_S => get_S
150 : : procedure :: findIndex => findIndex
151 : : procedure :: set_params => set_params
152 : : procedure :: inc1
153 : : end type spin_hist_t
154 : : !!***
155 : :
156 : : !public :: spinhist2var
157 : : !public :: var2spinhist
158 : : !public :: write_sd_hist
159 : : !public :: read_md_hist
160 : : !public :: get_dims_spinhist
161 : :
162 : : contains
163 : :
164 : :
165 : : !!****f* m_spin_hist/initialize
166 : : !!
167 : : !! NAME
168 : : !! initialize
169 : : !!
170 : : !! FUNCTION
171 : : !! initialize spin hist
172 : : !!
173 : : !! INPUTS
174 : : !! nspin = number of magnetic atoms
175 : : !! mxhist = maximum number of hist steps
176 : : !! has_latt = whether spin dynamics in with lattice dynamics
177 : : !!
178 : : !! OUTPUT
179 : : !! hist <type(spin_hist_t)()> = spin hist type
180 : : !! SOURCE
181 : :
182 : 2 : subroutine initialize(self, nspin, mxhist, has_latt)
183 : :
184 : : class(spin_hist_t), intent(inout) :: self
185 : : integer, intent(in) :: nspin, mxhist
186 : : logical, intent(in) :: has_latt
187 : : !integer, optional, intent(in) :: calc_traj_obs, calc_thermo_obs, calc_correlation_obs
188 : :
189 : 2 : self%nspin=nspin
190 : 2 : self%ntypat=0
191 : 2 : self%ihist=1
192 : 2 : self%ihist_prev=0
193 : 2 : self%mxhist=mxhist
194 : 2 : self%natoms=0
195 : 2 : self%has_latt=has_latt
196 : :
197 [ - + + - : 8 : ABI_MALLOC(self%heff, (3, nspin, mxhist))
- + + - +
- + - - +
- + - + ]
198 [ - + + - : 8 : ABI_MALLOC(self%snorm, (nspin, mxhist))
- + + - +
- + - - +
- + - + ]
199 [ - + + - : 6 : ABI_MALLOC(self%S, (3, nspin, mxhist))
- + + - -
+ - + -
+ ]
200 [ - + + - : 6 : ABI_MALLOC(self%dSdt, (3, nspin, mxhist))
- + + - -
+ - + -
+ ]
201 : :
202 [ - + + - : 6 : ABI_MALLOC(self%etot, (mxhist))
+ - + - -
+ - + -
+ ]
203 [ - + + - : 4 : ABI_MALLOC(self%entropy, (mxhist))
- + - + -
+ ]
204 [ - + + - : 4 : ABI_MALLOC(self%time, (mxhist))
- + - + -
+ ]
205 [ - + + - : 6 : ABI_MALLOC(self%itime, (mxhist))
+ - + - -
+ - + -
+ ]
206 : :
207 [ - + + - : 4 : ABI_MALLOC(self%ihist_latt, (mxhist))
- + - + -
+ ]
208 : :
209 : : ! TODO: add observable allocation here.
210 : :
211 : 2 : self%etot(1) =zero
212 : 2 : self%entropy(1) =zero
213 : 2 : self%time(1) =zero
214 : :
215 : : !self%acell(:)=zero
216 : : !self%rprimd(:, :)=zero
217 : : !self%xred(:,:) =zero
218 [ + + + + : 5192 : self%heff(:,:,:)=zero
+ + ]
219 [ + + + + : 5192 : self%S(:,:,:)=zero
+ + ]
220 [ + + + + : 5192 : self%dSdt(:,:,:)=zero
+ + ]
221 [ + + + + ]: 1304 : self%snorm(:,:)=zero
222 : 2 : end subroutine initialize
223 : : !!***
224 : :
225 : 2 : subroutine reset(self, array_to_zero)
226 : : class(spin_hist_t), intent(inout) :: self
227 : : logical :: array_to_zero
228 : 2 : self%ntypat=0
229 : 2 : self%ihist=1
230 : 2 : self%ihist_prev=0
231 : 2 : self%natoms=0
232 : :
233 : 2 : self%etot(1) =zero
234 : 2 : self%entropy(1) =zero
235 : 2 : self%time(1) =zero
236 : :
237 [ - + ]: 2 : if(array_to_zero) then
238 [ # # # # ]: 0 : self%heff(:,:,1)=zero
239 [ # # # # ]: 0 : self%S(:,:,1)=zero
240 [ # # # # ]: 0 : self%dSdt(:,:,1)=zero
241 [ # # ]: 0 : self%snorm(:,1)=zero
242 : 0 : self%Cv( 1)=zero
243 [ # # # # ]: 0 : self%sp_corr_func(:, :, 1)=zero
244 : : endif
245 : :
246 : :
247 : 2 : end subroutine reset
248 : :
249 : : !!****f* m_spin_hist/set_atomic_structure
250 : : !!
251 : : !! NAME
252 : : !! set_atomic_structure
253 : : !!
254 : : !! FUNCTION
255 : : !!
256 : : !! set atomic structure
257 : : !!
258 : : !! INPUTS
259 : : !! acell(3) = acell
260 : : !! rprimd(3, 3) =
261 : : !! xred(3, natoms) = positions in reduced coordinates
262 : : !! spin_index(3, natoms) = index of atom in spin hamiltonian
263 : : !! ntypat = number of types of atoms
264 : : !! typat(ntypat)=types of atoms
265 : : !! znucl=z of atoms
266 : : !!
267 : : !! OUTPUT
268 : : !! hist <type(spin_hist_t)()> = spin hist type
269 : : !! SOURCE
270 : : subroutine set_atomic_structure(self, acell, rprimd, xred, spin_index, ntypat, typat, znucl)
271 : :
272 : : class(spin_hist_t), intent(inout) :: self
273 : : real(dp), intent(in) :: acell(3), rprimd(3,3), xred(:,:), znucl(:)
274 : : integer, intent(in):: spin_index(:), ntypat, typat(:)
275 : : integer :: natoms
276 : : natoms=size(typat)
277 : : ABI_MALLOC(self%xred, (3, natoms))
278 : : ABI_MALLOC(self%spin_index, (natoms))
279 : : ABI_MALLOC(self%typat,(ntypat))
280 : : ABI_MALLOC(self%znucl, (ntypat))
281 : :
282 : : self%acell(:)=acell(:)
283 : : self%rprimd(:,:)=rprimd(:,:)
284 : : self%xred(:,:)=xred(:,:)
285 : : self%spin_index(:)=spin_index(:)
286 : : self%ntypat=ntypat
287 : : self%typat(:)=typat(:)
288 : : self%znucl(:)=znucl(:)
289 : : end subroutine set_atomic_structure
290 : : !!***
291 : :
292 : :
293 : : !!****f* m_spin_hist/set_params
294 : : !!
295 : : !! NAME
296 : : !! set_params
297 : : !!
298 : : !! FUNCTION
299 : : !!
300 : : !! set parameters for spin_hist_t
301 : : !!
302 : : !! INPUTS
303 : : !! spin_nctime=number of step between two write to netcdf hist file
304 : : !! spin_temperate= temperature of spin
305 : : !!
306 : : !! OUTPUT
307 : : !! hist <type(spin_hist_t)()> = spin hist type
308 : : !! SOURCE
309 : :
310 : 2 : subroutine set_params(self, spin_nctime, spin_temperature)
311 : :
312 : : class(spin_hist_t), intent(inout) :: self
313 : : integer, intent(in) :: spin_nctime
314 : : real(dp), intent(in) :: spin_temperature
315 : 2 : self%spin_nctime= spin_nctime
316 : 2 : self%spin_temperature=spin_temperature
317 : 2 : end subroutine set_params
318 : : !!***
319 : :
320 : : !!****f* m_spin_hist/finalize
321 : : !!
322 : : !! NAME
323 : : !! finalize
324 : : !!
325 : : !! FUNCTION
326 : : !!
327 : : !! free memory for spin_hist_t
328 : : !!
329 : : !! INPUTS
330 : : !!
331 : : !! OUTPUT
332 : : !! hist <type(spin_hist_t)()> = spin hist type
333 : : !! SOURCE
334 : 2 : subroutine finalize(self)
335 : :
336 : : class(spin_hist_t) , intent(inout) :: self
337 : :
338 [ - + ]: 2 : ABI_SFREE(self%xred)
339 [ - + ]: 2 : ABI_SFREE(self%typat)
340 [ - + ]: 2 : ABI_SFREE(self%znucl)
341 [ - + ]: 2 : ABI_SFREE(self%spin_index)
342 [ + - ]: 2 : ABI_SFREE(self%heff)
343 [ + - ]: 2 : ABI_SFREE(self%snorm)
344 [ + - ]: 2 : ABI_SFREE(self%S)
345 [ + - ]: 2 : ABI_SFREE(self%dSdt)
346 [ + - ]: 2 : ABI_SFREE(self%etot)
347 [ + - ]: 2 : ABI_SFREE(self%entropy)
348 [ + - ]: 2 : ABI_SFREE(self%time)
349 [ + - ]: 2 : ABI_SFREE(self%itime)
350 [ + - ]: 2 : ABI_SFREE(self%ihist_latt)
351 : :
352 : 2 : end subroutine finalize
353 : : !!***
354 : :
355 : :
356 : :
357 : : !!****f* m_spin_hist/get_S
358 : : !!
359 : : !! NAME
360 : : !! get_S
361 : : !!
362 : : !! FUNCTION
363 : : !!
364 : : !! get the S for step. step=0 is current. step=-1 is last...
365 : : !!
366 : : !! INPUTS
367 : : !! hist <type(spin_hist_t)()> = spin hist type
368 : : !! step = index of step. current step is 0. last step is -1.
369 : : !! OUTPUT
370 : : !! S(3, nspin)=spin orientations at step
371 : : !! SOURCE
372 [ # # ]: 0 : function get_S(self, step) result(S)
373 : : class(spin_hist_t), intent(inout) :: self
374 : : integer, intent(in), optional:: step
375 : : real(dp) :: S(3, self%nspin)
376 : : integer :: i, j
377 [ # # ]: 0 : if (.not. present(step)) then
378 : 0 : j=0
379 : : else
380 : 0 : j=step
381 : : end if
382 : 0 : i=self%findIndex(step=j)
383 [ # # # # ]: 0 : S(:,:)=self%S(:,:,i)
384 : 0 : end function get_S
385 : : !!***
386 : :
387 : : !!****f* m_spin_hist/inc1
388 : : !!
389 : : !! NAME
390 : : !! inc1
391 : : !!
392 : : !! FUNCTION
393 : : !!
394 : : !! time counter increase
395 : : !!
396 : : !! INPUTS
397 : : !!
398 : : !! OUTPUT
399 : : !! hist <type(spin_hist_t)()> = spin hist type
400 : : !! SOURCE
401 : 2004 : subroutine inc1(self)
402 : :
403 : : class(spin_hist_t), intent(inout) :: self
404 [ + + ]: 2004 : if(self%ihist_prev ==0 ) then
405 : 4 : self%itime(self%ihist)=1
406 : : else
407 : 2000 : self%itime(self%ihist)=self%itime(self%ihist_prev)+1
408 : : endif
409 : 2004 : self%ihist_prev=self%ihist
410 : 2004 : self%ihist=self%findIndex(1)
411 : 2004 : end subroutine inc1
412 : : !!***
413 : :
414 : :
415 : : !!***f* m_spin_hist/findIndex
416 : : !!
417 : : !! NAME
418 : : !! get_findIndex
419 : : !!
420 : : !! FUNCTION
421 : : !! get the index of the step in the self%S array
422 : : !! INPUTS
423 : : !!
424 : : !! OUTPUT
425 : : !! index: the index of the step in the self%S array.
426 : : !! SOURCE
427 : 2004 : function findIndex(self, step) result(index)
428 : :
429 : : class(spin_hist_t), intent(inout) :: self
430 : : integer , intent(in) :: step
431 : : integer :: index
432 : : !Local variables-------------------------------
433 : : !scalars
434 : : integer :: mxhist
435 : : !arrays
436 : : character(len=500) :: msg
437 : : ! *************************************************************
438 : :
439 : 2004 : mxhist = self%mxhist
440 [ - + - - : 2004 : if ((mxhist ==1.and.step/=+1).or.&
+ - - + ]
441 : : & (mxhist /=1.and.abs(step) >=mxhist)) then
442 : 0 : write(msg,'(a,I0,2a)')' The requested step must be less than ',mxhist,ch10,&
443 : 0 : & 'Action: increase the number of history store in the hist'
444 : 0 : ABI_BUG(msg)
445 : : end if
446 : 2004 : index= mod(self%ihist+step, self%mxhist)+1
447 : 2004 : end function findIndex
448 : : !!***
449 : :
450 : :
451 : : !!***f* m_spin_hist/set_vars
452 : : !!
453 : : !! NAME
454 : : !! get_set_vars
455 : : !!
456 : : !! FUNCTION
457 : : !! put the data into hist
458 : : !! INPUTS
459 : : !! S(3, nspin)=spin orientation
460 : : !! Snorm(nspin)=spin amplitude
461 : : !! dSdt(3,nspin)= dS/dt
462 : : !! Heff(3, nspin) = effective magnetic field
463 : : !! etot = total energy
464 : : !! entropy = entropy
465 : : !! time = time (note: not index of time)
466 : : !! ihist_latt = index of lattice dynamics step.
467 : : !! inc = whether this step is finished. If true, increment counter.
468 : : !! OUTPUT
469 : : !! index: the index of the step in the self%S array.
470 : : !! SOURCE
471 : 4008 : subroutine set_vars(self, S, Snorm, dSdt, Heff, etot, entropy, time, ihist_latt, inc)
472 : :
473 : : class(spin_hist_t), intent(inout) ::self
474 : : real(dp), optional, intent(in) :: S(3, self%nspin), Snorm(self%nspin), dSdt(3, self%nspin), &
475 : : & Heff(3, self%nspin), etot, entropy, time
476 : : integer, optional :: ihist_latt
477 : : logical, intent(in), optional :: inc
478 : : integer :: ihist
479 : 4006 : ihist=self%ihist
480 [ + - ]: 4006 : if(present(inc)) then
481 [ + + ]: 4006 : if (inc) then
482 : 2004 : call self%inc1()
483 : : end if
484 : : end if
485 [ + + ]: 4006 : if(present(S)) then
486 [ + + + + ]: 1733460 : self%S(:, :, ihist)=S(:,:)
487 : : end if
488 [ + + ]: 4006 : if(present(Snorm)) then
489 [ + + ]: 434868 : self%Snorm(:, ihist)=Snorm(:)
490 : : endif
491 [ - + ]: 4006 : if(present(dSdt)) then
492 [ # # # # ]: 0 : self%dSdt(:, :, ihist)=dSdt(:,:)
493 : : end if
494 [ - + ]: 4006 : if(present(Heff)) then
495 [ # # # # ]: 0 : self%Heff(:, :, ihist)=Heff(:,:)
496 : : end if
497 [ + + ]: 4006 : if(present(etot)) then
498 : 2002 : self%etot(ihist)=etot
499 : : end if
500 [ - + ]: 4006 : if(present(entropy)) then
501 : 0 : self%entropy(ihist)=entropy
502 : : end if
503 [ + + ]: 4006 : if(present(time)) then
504 : 2004 : self%time( ihist)=time
505 : : end if
506 [ + + ]: 4006 : if(present(ihist_latt)) then
507 : 2 : self%ihist_latt(ihist)=ihist_latt
508 : : endif
509 [ + + + + : 8014 : end subroutine set_vars
- + - + ]
510 : : !!***
511 : :
512 [ # # # # : 0 : end module m_spin_hist
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
|