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
|