Line data Source code
1 : !!****m* ABINIT/m_spin_mover
2 : !! NAME
3 : !! m_spin_mover
4 : !!
5 : !! FUNCTION
6 : !! This module contains the spin mover, which controls how the spin
7 : !!
8 : !!
9 : !! Datatypes:
10 : !!
11 : !! * spin_mover_t
12 : !!
13 : !! Subroutines:
14 : !!
15 : !! * spin_mover_t_initialize
16 : !! * spin_mover_t_run_one_step
17 : !! * spin_mover_t_run_time
18 : !! * TODO: update this when F2003 documentation format decided.
19 : !!
20 : !!
21 : !! COPYRIGHT
22 : !! Copyright (C) 2001-2026 ABINIT group (hexu)
23 : !! This file is distributed under the terms of the
24 : !! GNU General Public License, see ~abinit/COPYING
25 : !! or http://www.gnu.org/copyleft/gpl.txt .
26 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
27 : !!
28 : !! SOURCE
29 :
30 :
31 : #if defined HAVE_CONFIG_H
32 : #include "config.h"
33 : #endif
34 :
35 : #include "abi_common.h"
36 :
37 :
38 : module m_spin_mover
39 :
40 : use defs_basis
41 : use m_nctk
42 : #if defined HAVE_NETCDF
43 : use netcdf
44 : #endif
45 : use m_errors
46 : use m_abicore
47 : use m_xmpi
48 : use m_io_tools, only : get_unit, open_file, close_unit
49 : use m_mpi_scheduler, only: mpi_scheduler_t, init_mpi_info
50 : use m_mathfuncs, only : cross
51 : use m_spin_observables , only : spin_observable_t
52 : use m_spin_potential, only: spin_potential_t
53 : use m_spin_hist, only: spin_hist_t
54 : use m_spin_ncfile, only: spin_ncfile_t
55 : use m_multibinit_dataset, only: multibinit_dtset_type
56 : use m_multibinit_cell, only: mbcell_t, mbsupercell_t
57 : use m_random_xoroshiro128plus, only: set_seed, rand_normal_array, rng_t
58 : use m_abstract_potential, only: abstract_potential_t
59 : use m_abstract_mover, only: abstract_mover_t
60 : use m_spin_mc_mover, only : spin_mc_t
61 : use m_hashtable_strval, only: hash_table_t
62 : implicit none
63 : private
64 : !!***
65 :
66 :
67 : !!****t* m_spin_mover/spin_mover_t
68 : !! NAME
69 : !! spin_mover_t
70 : !!
71 : !! FUNCTION
72 : !! this type contains the parameters for the spin mover.
73 : !!
74 : !! It contains:
75 : !! dt: time step
76 : !! total_time
77 : !! temperature.
78 : !! nspin number of magnetic atoms
79 : !! SOURCE
80 :
81 :
82 : type, public, extends(abstract_mover_t) :: spin_mover_t
83 : integer :: nspin, method=0
84 : real(dp), allocatable :: gyro_ratio(:), damping(:), gamma_L(:), H_lang_coeff(:), ms(:), Stmp(:,:), Stmp2(:,:)
85 : real(dp), allocatable :: Heff_tmp(:,:), Htmp(:,:), Hrotate(:,:), H_lang(:,:), buffer(:,:)
86 : real(dp) :: init_qpoint(3), init_rotate_axis(3) ! qpoint and rotation axis to set up initial spin configuration
87 : real(dp) :: init_orientation(3) ! spin orientation in primitive cell which is then rotated
88 : type(spin_hist_t) :: hist
89 : logical :: gamma_l_calculated
90 : type(spin_mc_t) :: spin_mc
91 : type(mpi_scheduler_t) :: mps
92 : type(spin_observable_t) :: spin_ob
93 : type(spin_ncfile_t) :: spin_ncfile
94 : type(multibinit_dtset_type), pointer :: params
95 : CONTAINS
96 : procedure :: initialize
97 : procedure :: finalize
98 : procedure :: set_initial_state
99 : procedure :: read_hist_spin_state
100 : procedure, private :: run_one_step_DM => spin_mover_t_run_one_step_DM
101 : procedure, private :: run_one_step_HeunP => spin_mover_t_run_one_step_HeunP
102 : procedure, private :: run_one_step_dummy=> spin_mover_t_run_one_step_dummy
103 : procedure, private :: run_one_step_MC=> spin_mover_t_run_one_step_MC
104 : procedure :: run_one_step => spin_mover_t_run_one_step
105 : procedure :: run_time => spin_mover_t_run_time
106 : procedure :: run_MvT
107 : procedure :: set_temperature
108 : procedure, private :: prepare_ncfile
109 : procedure, private ::get_Langevin_Heff
110 : procedure :: current_spin
111 : procedure :: set_ncfile_name
112 : end type spin_mover_t
113 : !!***
114 :
115 : contains
116 :
117 : !!****f* m_spin_mover/initialize
118 : !!
119 : !! NAME
120 : !! initialize
121 : !!
122 : !! FUNCTION
123 : !! initialize the spin mover
124 : !!
125 : !! INPUTS
126 : !!
127 : !! OUTPUT
128 : !!
129 : !! NOTES
130 : !!
131 : !! SOURCE
132 2 : subroutine initialize(self, params, supercell, rng)
133 : class(spin_mover_t), intent(inout) :: self
134 : type(multibinit_dtset_type), target :: params
135 : type(mbsupercell_t), target :: supercell
136 : type(rng_t), target, intent(in) :: rng
137 : integer :: nspin
138 :
139 : integer :: master, my_rank, comm, nproc, ierr
140 : logical :: iam_master
141 2 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
142 :
143 2 : self%params=>params
144 2 : self%supercell=>supercell
145 2 : self%rng => rng
146 2 : if (iam_master) then
147 2 : nspin=supercell%spin%nspin
148 2 : self%nspin=nspin
149 2 : self%dt= params%spin_dt
150 2 : self%thermal_time= params%spin_ntime_pre * self%dt
151 2 : self%total_time= params%spin_ntime * self%dt
152 2 : self%temperature=params%spin_temperature
153 2 : if(params%spin_dynamics>=0) then
154 2 : self%method=params%spin_dynamics
155 : endif
156 2 : if(params%spin_init_state==3) then
157 0 : self%init_qpoint = params%spin_init_qpoint
158 0 : self%init_rotate_axis = params%spin_init_rotate_axis
159 0 : self%init_orientation = params%spin_init_orientation
160 : endif
161 : end if
162 2 : if(params%spin_dynamics==3) then ! Monte carlo
163 0 : call self%spin_mc%initialize(nspin=nspin, angle=0.2_dp, temperature=params%spin_temperature)
164 : end if
165 2 : call xmpi_bcast(self%nspin, master, comm, ierr)
166 2 : call xmpi_bcast(self%dt, master, comm, ierr)
167 2 : call xmpi_bcast(self%thermal_time, master, comm, ierr)
168 2 : call xmpi_bcast(self%total_time, master, comm, ierr)
169 2 : call xmpi_bcast(self%temperature, master, comm, ierr)
170 2 : call xmpi_bcast(self%method, master, comm, ierr)
171 :
172 6 : ABI_MALLOC(self%ms, (self%nspin) )
173 6 : ABI_MALLOC(self%gyro_ratio, (self%nspin) )
174 6 : ABI_MALLOC(self%damping, (self%nspin) )
175 6 : ABI_MALLOC(self%gamma_l, (self%nspin) )
176 6 : ABI_MALLOC(self%H_lang_coeff, (self%nspin) )
177 :
178 6 : ABI_MALLOC(self%Heff_tmp, (3,self%nspin) )
179 6 : ABI_MALLOC(self%Htmp, (3,self%nspin) )
180 6 : ABI_MALLOC(self%Hrotate, (3,self%nspin) )
181 6 : ABI_MALLOC(self%Stmp, (3,self%nspin) )
182 6 : ABI_MALLOC(self%Stmp2, (3,self%nspin) )
183 6 : ABI_MALLOC(self%buffer, (3,self%nspin) )
184 6 : ABI_MALLOC(self%H_lang, (3,self%nspin) )
185 :
186 2 : self%gamma_l_calculated=.False.
187 2 : call self%mps%initialize(ntasks=nspin,master=master, comm=comm)
188 :
189 :
190 2 : call xmpi_bcast(params%spin_damping, master, comm, ierr)
191 :
192 2 : if (iam_master) then
193 2 : if (params%spin_damping >=0) then
194 434 : self%damping(:)= params%spin_damping
195 : else
196 0 : self%damping(:)=supercell%spin%gilbert_damping(:)
197 : end if
198 :
199 434 : self%gyro_ratio(:)=supercell%spin%gyro_ratio(:)
200 434 : self%ms(:)=supercell%spin%ms(:)
201 : endif
202 :
203 2 : call xmpi_bcast(self%damping, master, comm, ierr)
204 2 : call xmpi_bcast(self%gyro_ratio, master, comm, ierr)
205 2 : call xmpi_bcast(self%ms, master, comm, ierr)
206 2 : call self%set_temperature(temperature=params%spin_temperature)
207 :
208 : ! Hist and set initial spin state
209 2 : if(iam_master) then
210 : call self%hist%initialize(nspin=self%nspin, &
211 2 : & mxhist=3, has_latt=.False.)
212 : call self%hist%set_params(spin_nctime=params%spin_nctime, &
213 2 : & spin_temperature=params%spin_temperature)
214 : endif
215 :
216 2 : call self%set_initial_state(mode=params%spin_init_state)
217 :
218 : ! observable
219 2 : if(iam_master) then
220 2 : call self%spin_ob%initialize(self%supercell, params)
221 : endif
222 :
223 6 : end subroutine initialize
224 : !!***
225 :
226 : !-------------------------------------------------------------------!
227 : !set_ncfile_name :
228 : !-------------------------------------------------------------------!
229 2 : subroutine set_ncfile_name(self, params, fname)
230 : class(spin_mover_t), intent(inout) :: self
231 : type(multibinit_dtset_type) :: params
232 : character(len=fnlen), intent(in) :: fname
233 : integer :: master, my_rank, comm, nproc
234 : logical :: iam_master
235 2 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
236 2 : if (iam_master) then
237 2 : call self%prepare_ncfile(params, trim(fname)//'_spinhist.nc')
238 2 : call self%spin_ncfile%write_one_step(self%hist)
239 : endif
240 2 : end subroutine set_ncfile_name
241 :
242 :
243 : !-------------------------------------------------------------------!
244 : ! read_hist_spin_state
245 : ! read the last step of spin from hist file.
246 : ! and save if to self%Stmp
247 : !-------------------------------------------------------------------!
248 0 : subroutine read_hist_spin_state(self, fname)
249 : class(spin_mover_t), intent(inout) :: self
250 : character(len=fnlen), intent(in) :: fname
251 : integer :: ierr, ncid, varid
252 : integer :: nspin, ntime
253 : character(len=500) :: msg
254 : ! open file
255 :
256 : #if defined HAVE_NETCDF
257 0 : ierr=nf90_open(trim(fname), NF90_NOWRITE, ncid)
258 0 : NCF_CHECK_MSG(ierr, "The spin_init_mode is set to 4. But opening netcdf file "//trim(fname)//" Failed. ")
259 :
260 : ! sanity check. If the hist file is consistent with the current calculation
261 0 : ierr=nctk_get_dim(ncid, "nspin" , nspin)
262 0 : NCF_CHECK_MSG(ierr, "when reading nspin")
263 :
264 : msg="The number of spins in histfile is not equal & & to the present calculation." // &
265 0 : & " Please check if the file is consistent."
266 0 : if (nspin /= self%nspin) then
267 0 : ABI_ERROR(msg)
268 : end if
269 :
270 :
271 0 : ierr=nctk_get_dim(ncid, "ntime", ntime)
272 0 : NCF_CHECK_MSG(ierr, "when reading ntime")
273 :
274 :
275 : ! TODO: more check ???
276 :
277 : ! read Spin and set as initial state
278 0 : ierr =nf90_inq_varid(ncid, "S", varid)
279 : msg="when reading S. Try using spin_init_state=3 option instead (specify spin_init_qpoint," // &
280 0 : & " spin_init_rotate_axis and spin_init_orientation as needed)."
281 0 : NCF_CHECK_MSG(ierr, msg)
282 :
283 0 : ierr = nf90_get_var(ncid=ncid, varid=varid, values=self%Stmp(:,:), start=(/1, 1, ntime/), count=(/3, nspin,1/))
284 0 : NCF_CHECK_MSG(ierr, "when reading S from spin hist file")
285 :
286 : ! close file
287 0 : ierr=nf90_close(ncid)
288 0 : NCF_CHECK_MSG(ierr, "Close netcdf file")
289 : #else
290 : ABI_ERROR("spin_init_state set to 4 but abinit is not compiled with netcdf.")
291 : #endif
292 :
293 0 : end subroutine read_hist_spin_state
294 :
295 : !----------------------------------------------------------------------------!
296 : !set_initial_state:
297 : ! mode: which configuration to use
298 : ! 1. Random
299 : ! 2. reference state from potential file
300 : ! 3. spin configuration using qpoint and rotation axis (e.g. for FM or AFM)
301 : ! 4. Restart from last entry of hist netcdf file
302 : !----------------------------------------------------------------------------!
303 2 : subroutine set_initial_state(self, mode)
304 : class(spin_mover_t), intent(inout) :: self
305 : integer, optional, intent(in) :: mode
306 :
307 : integer :: i, init_mode
308 : character(len=500) :: msg
309 :
310 : integer :: master, my_rank, comm, nproc, ierr
311 : logical :: iam_master
312 2 : real(dp), allocatable :: Sprim(:,:)
313 :
314 2 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
315 :
316 2 : if(iam_master) then
317 2 : if (present(mode)) then
318 2 : init_mode=mode
319 : else
320 : init_mode=1
321 : end if
322 :
323 2 : select case (init_mode)
324 : case (1)
325 : ! randomize S using uniform random number
326 2 : write(msg,*) "Initial spins set to random values."
327 2 : call wrtout(ab_out,msg,'COLL')
328 2 : call wrtout(std_out,msg,'COLL')
329 : !call random_number(self%Stmp)
330 2 : call self%rng%rand_unif_01_array(self%Stmp, self%nspin*3 )
331 1730 : self%Stmp=self%Stmp-0.5
332 434 : do i=1, self%nspin
333 3026 : self%Stmp(:,i)=self%Stmp(:,i)/sqrt(sum(self%Stmp(:, i)**2))
334 : end do
335 :
336 : case (2)
337 : ! set spin to reference state using the reference qpoint and rotation axis from potential file
338 0 : write(msg,*) "Initial spins set to reference configuration."
339 0 : call wrtout(ab_out,msg,'COLL')
340 0 : call wrtout(std_out,msg,'COLL')
341 :
342 0 : do i=1, self%nspin
343 0 : self%Stmp(:,:) = self%supercell%spin%Sref(:,:)
344 : end do
345 :
346 : case (3)
347 0 : write(msg,*) "Initial spins set according to spin_init_* variables."
348 0 : call wrtout(ab_out,msg,'COLL')
349 0 : call wrtout(std_out,msg,'COLL')
350 :
351 0 : ABI_MALLOC(Sprim, (3,self%supercell%unitcell%spin%nspin) )
352 :
353 : ! set inital spin state using the input variables
354 : ! set spin to ferromagnetic along init_orientation then rotate
355 0 : do i=1, self%supercell%unitcell%spin%nspin
356 0 : Sprim(:,i)=self%init_orientation(:)
357 : enddo
358 0 : self%Stmp(:,:) = 0.0d0
359 :
360 : call self%supercell%supercell_maker%generate_spin_wave_vectorlist(A=Sprim, &
361 0 : & kpoint=self%init_qpoint, axis=self%init_rotate_axis, A_sc=self%Stmp)
362 :
363 0 : ABI_SFREE(SPrim)
364 :
365 : case (4)
366 : ! read from last step of hist file
367 0 : write(msg,'(a,a,a)') "Initial spins set to input spin hist file ",&
368 0 : & trim(self%params%spin_init_hist_fname), '.'
369 0 : call wrtout(ab_out,msg,'COLL')
370 0 : call wrtout(std_out,msg,'COLL')
371 2 : call self%read_hist_spin_state(fname=self%params%spin_init_hist_fname)
372 :
373 : end select
374 :
375 : call self%hist%set_vars(S=self%Stmp, Snorm=self%supercell%spin%ms, &
376 2 : & time=0.0_dp, ihist_latt=0, inc=.True.)
377 :
378 : endif
379 2 : call xmpi_bcast(self%Stmp, 0, comm, ierr)
380 2 : end subroutine set_initial_state
381 :
382 :
383 : !-------------------------------------------------------------------!
384 : ! prepare_ncfile:
385 : !-------------------------------------------------------------------!
386 2 : subroutine prepare_ncfile(self, params, fname)
387 : class(spin_mover_t), intent(inout) :: self
388 : type(multibinit_dtset_type) :: params
389 : character(len=*), intent(in) :: fname
390 :
391 : integer :: master, my_rank, comm, nproc
392 : logical :: iam_master
393 2 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
394 :
395 2 : if(iam_master) then
396 2 : call self%spin_ncfile%initialize( trim(fname), params%spin_write_traj)
397 2 : call self%spin_ncfile%def_spindynamics_var(self%hist)
398 2 : call self%spin_ncfile%def_observable_var(self%spin_ob)
399 2 : call self%spin_ncfile%write_primitive_cell(self%supercell%unitcell)
400 2 : call self%spin_ncfile%write_supercell(self%supercell)
401 2 : call self%spin_ncfile%write_parameters(params)
402 : endif
403 2 : end subroutine prepare_ncfile
404 :
405 :
406 :
407 4 : subroutine set_temperature(self, temperature)
408 : class(spin_mover_t), intent(inout) :: self
409 : real(dp), optional, intent(in) :: temperature
410 :
411 : integer :: master, my_rank, comm, nproc, ierr
412 : logical :: iam_master
413 2 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
414 :
415 2 : if(present(temperature)) self%temperature=temperature
416 2 : call xmpi_bcast(self%temperature, master, comm, ierr)
417 2 : if(self%method==3) then
418 0 : if(iam_master) self%spin_mc%temperature = temperature
419 0 : if(iam_master) self%spin_mc%beta=1.0_dp/temperature
420 0 : call xmpi_bcast(self%spin_mc%temperature, master, comm, ierr)
421 0 : call xmpi_bcast(self%spin_mc%beta, master, comm, ierr)
422 : end if
423 434 : self%gamma_l(:)= self%gyro_ratio(:)/(1.0_dp+ self%damping(:)**2)
424 2 : self%gamma_l_calculated=.True.
425 : self%H_lang_coeff(:)=sqrt(2.0*self%damping(:)* self%temperature &
426 434 : & /(self%gyro_ratio(:)* self%dt *self%ms(:)))
427 2 : end subroutine set_temperature
428 :
429 :
430 2002 : subroutine get_Langevin_Heff(self, H_lang)
431 : class(spin_mover_t), intent(inout) :: self
432 : real(dp), intent(inout):: H_lang(3,self%nspin)
433 : integer :: i
434 2002 : if ( self%temperature .gt. 1d-7) then
435 2002 : call rand_normal_array(self%rng, H_lang(:, self%mps%istart:self%mps%iend), 3*self%mps%ntask)
436 434434 : do i = self%mps%istart, self%mps%iend
437 1731730 : H_lang(:,i)= H_lang(:,i) * self%H_lang_coeff(i)
438 : end do
439 : else
440 0 : H_lang(:,:)=0.0_dp
441 : end if
442 2002 : end subroutine get_Langevin_Heff
443 :
444 :
445 : !!****f* m_spin_mover/spin_mover_t_run_one_step_HeunP
446 : !!
447 : !! NAME
448 : !! spin_mover_t_run_one_step_HeunP
449 : !!
450 : !! FUNCTION
451 : !! run one spin step using HeunP method
452 : !!
453 : !! INPUTS
454 : !! effpot: abstract_potential_t type.
455 : !! S_in : input spin. (3*nspin)
456 : !!
457 : !! OUTPUT
458 : !! etot: energy (scalar)
459 : !!
460 : !! SOURCE
461 0 : subroutine spin_mover_t_run_one_step_HeunP(self, effpot, S_in, &
462 0 : & etot, displacement, strain, lwf, energy_table)
463 : !class (spin_mover_t), intent(inout):: self
464 : class(spin_mover_t), intent(inout):: self
465 : class(abstract_potential_t), intent(inout) :: effpot
466 :
467 : real(dp), optional, intent(inout):: displacement(:,:), &
468 : strain(:,:), lwf(:)
469 : real(dp), intent(inout) :: S_in(3,self%nspin)
470 : real(dp), intent(out) :: etot
471 : integer :: i
472 : real(dp) :: dSdt(3), Htmp(3), Ri(3)
473 : type(hash_table_t),optional, intent(inout) :: energy_table
474 :
475 : !integer :: master, my_rank, comm, nproc, ierr
476 : !logical :: iam_master
477 : !call init_mpi_info(master, iam_master, my_rank, comm, nproc)
478 :
479 : ! predict
480 0 : etot=0.0
481 0 : self%Heff_tmp(:,:)=0.0
482 : call effpot%calculate(displacement=displacement, strain=strain, lwf=lwf, spin=S_in, &
483 0 : & bfield=self%Heff_tmp, energy=etot, energy_table=energy_table)
484 0 : call self%get_Langevin_Heff(self%H_lang)
485 0 : do i=self%mps%istart, self%mps%iend
486 0 : Htmp=self%Heff_tmp(:,i)+self%H_lang(:,i)
487 0 : Ri = cross(S_in(:,i),Htmp)
488 0 : dSdt = -self%gamma_L(i)*(Ri+self%damping(i)* cross(S_in(:,i), Ri))
489 0 : Ri=S_in(:,i)+dSdt*self%dt
490 0 : Ri=Ri/norm2(Ri)
491 0 : self%Stmp2(:,i)=Ri
492 : end do
493 0 : call self%mps%allgatherv_dp2d(self%Stmp2, 3, buffer=self%buffer)
494 :
495 : ! correction
496 0 : self%Htmp(:,:)=0.0
497 0 : etot=0.0
498 : call effpot%calculate(displacement=displacement, strain=strain, lwf=lwf,spin=self%Stmp2, &
499 0 : & bfield=self%Htmp, energy=etot, energy_table=energy_table)
500 0 : do i=self%mps%istart, self%mps%iend
501 0 : Htmp=(self%Heff_tmp(:,i)+self%Htmp(:,i))*0.5_dp+self%H_lang(:,i)
502 0 : Ri = cross(S_in(:,i),Htmp)
503 0 : dSdt = -self%gamma_L(i)*(Ri+self%damping(i)* cross(S_in(:,i), Ri))
504 0 : Ri=S_in(:,i)+dSdt*self%dt
505 0 : Ri=Ri/norm2(Ri)
506 0 : self%Stmp(:,i)=Ri
507 : end do
508 0 : call self%mps%allgatherv_dp2d(self%Stmp, 3, buffer=self%buffer)
509 0 : end subroutine spin_mover_t_run_one_step_HeunP
510 : !!***
511 :
512 :
513 :
514 : !!****f* m_spin_mover/spin_mover_t_run_one_step_dummy
515 : !!
516 : !! NAME
517 : !! spin_mover_t_run_one_step_dummy
518 : !!
519 : !! FUNCTION
520 : !! run one spin step using dummy method
521 : !!
522 : !! INPUTS
523 : !! effpot: abstract_potential_t type.
524 : !! S_in : input spin. (3*nspin)
525 : !!
526 : !! OUTPUT
527 : !! etot: energy (scalar)
528 : !!
529 : !! SOURCE
530 0 : subroutine spin_mover_t_run_one_step_dummy(self, effpot, S_in, etot, &
531 0 : & displacement, strain, lwf, energy_table)
532 : !class (spin_mover_t), intent(inout):: self
533 : class(spin_mover_t), intent(inout):: self
534 : class(abstract_potential_t), intent(inout) :: effpot
535 :
536 : real(dp), optional, intent(inout):: displacement(:,:), &
537 : strain(:,:), lwf(:)
538 : real(dp), intent(inout) :: S_in(3,self%nspin)
539 : real(dp), intent(out) :: etot
540 : type(hash_table_t),optional, intent(inout) :: energy_table
541 : integer :: i
542 : real(dp) :: Htmp(3), Ri(3)
543 :
544 : ! predict
545 0 : etot=0.0
546 0 : self%Heff_tmp(:,:)=0.0
547 : call effpot%calculate(displacement=displacement, strain=strain, lwf=lwf, spin=S_in, &
548 0 : & bfield=self%Heff_tmp, energy=etot, energy_table=energy_table)
549 0 : call self%get_Langevin_Heff(self%H_lang)
550 0 : do i=self%mps%istart, self%mps%iend
551 0 : Htmp=self%Heff_tmp(:,i)+self%H_lang(:,i)
552 : !Ri = cross(S_in(:,i),Htmp)
553 : !dSdt = -self%gamma_L(i)*(Ri+self%damping(i)* cross(S_in(:,i), Ri))
554 0 : Ri=S_in(:,i)!+dSdt*self%dt
555 0 : Ri=Ri/norm2(Ri)
556 0 : self%Stmp(:,i)=Ri
557 : end do
558 0 : call self%mps%allgatherv_dp2d(self%Stmp2, 3, buffer=self%buffer)
559 :
560 0 : end subroutine spin_mover_t_run_one_step_dummy
561 : !!***
562 :
563 :
564 :
565 : !----------------------------------------------------------------------
566 : !> @brief rotate spin with a rotation matrix
567 : !>
568 : !> @param[in] S_in: input spin array(3)
569 : !> @param[in] Heff: effective field
570 : !> @param[in] dt: time step
571 : !> @param[out] S_out: output spin
572 : !----------------------------------------------------------------------
573 :
574 864864 : pure function rotate_S_DM(S_in, Heff, dt) result(S_out)
575 : ! Depondt & Mertens method to rotate S_in
576 : real(dp), intent(in) :: S_in(3), Heff(3), dt
577 : real(dp) :: S_out(3)
578 : real(dp) :: B(3) , w, u, Bnorm, R(3,3), cosw, sinw
579 3459456 : Bnorm=sqrt(sum(Heff*Heff))
580 3459456 : B(:)=Heff(:)/Bnorm ! axis of rotation
581 864864 : w=Bnorm*dt ! amplitude of rotation
582 864864 : sinw=sin(w)
583 864864 : cosw=cos(w)
584 864864 : u=1.0d0-cosw
585 :
586 : ! R is rotation matrix
587 864864 : R(1,1)=B(1)*B(1)*u+cosw
588 864864 : R(2,1)=B(1)*B(2)*u+B(3)*sinw
589 864864 : R(3,1)=B(1)*B(3)*u-B(2)*sinw
590 :
591 864864 : R(1,2)=B(1)*B(2)*u-B(3)*sinw
592 864864 : R(2,2)=B(2)*B(2)*u+cosw
593 864864 : R(3,2)=B(2)*B(3)*u+B(1)*sinw
594 :
595 864864 : R(1,3)=B(1)*B(3)*u+B(2)*sinw
596 864864 : R(2,3)=B(2)*B(3)*u-B(1)*sinw
597 864864 : R(3,3)=B(3)*B(3)*u+cosw
598 : ! rotate
599 13837824 : S_out=matmul(R, S_in)
600 864864 : end function rotate_S_DM
601 :
602 2002 : subroutine spin_mover_t_run_one_step_DM(self, effpot, S_in, etot, displacement, strain,&
603 2002 : & lwf, energy_table)
604 : ! Depondt & Mertens (2009) method, using a rotation matrix so length doesn't change.
605 : !class (spin_mover_t), intent(inout):: self
606 : class(spin_mover_t), intent(inout):: self
607 : class(abstract_potential_t), intent(inout) :: effpot
608 : real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), lwf(:)
609 : real(dp), intent(inout) :: S_in(3,self%nspin)
610 : real(dp), intent(out) :: etot
611 : type(hash_table_t),optional, intent(inout) :: energy_table
612 : real(dp) :: Htmp(3)
613 : integer :: i
614 :
615 : ! predict
616 1731730 : self%Stmp2(:,:)=0.0_dp
617 2002 : etot=0.0
618 1731730 : self%Heff_tmp(:,:)=0.0_dp
619 : call effpot%calculate(displacement=displacement, strain=strain, lwf=lwf,spin=S_in, &
620 6006 : bfield=self%Heff_tmp, energy=etot, energy_table=energy_table)
621 2002 : call self%get_Langevin_Heff(self%H_lang)
622 434434 : do i=self%mps%istart, self%mps%iend
623 1729728 : Htmp=self%Heff_tmp(:,i)+self%H_lang(:,i)
624 : ! Note that there is no - , because dsdt =-cross (S, Hrotate)
625 3027024 : self%Hrotate(:,i) = self%gamma_L(i) * (Htmp + self%damping(i)* cross(S_in(:,i), Htmp))
626 1731730 : self%Stmp2(:,i)= rotate_S_DM(S_in(:,i), self%Hrotate(:,i), self%dt)
627 : end do
628 2002 : call self%mps%allgatherv_dp2d(self%Stmp2, 3, self%buffer)
629 :
630 : ! correction
631 1731730 : self%Htmp(:,:)=0.0_dp
632 2002 : etot=0.0
633 : call effpot%calculate(displacement=displacement, strain=strain, lwf=lwf, spin=self%Stmp2, &
634 6006 : bfield=self%Htmp, energy=etot, energy_table=energy_table)
635 :
636 434434 : do i=self%mps%istart, self%mps%iend
637 1729728 : Htmp=(self%Heff_tmp(:,i)+self%Htmp(:,i))*0.5_dp + self%H_lang(:,i)
638 3027024 : self%Hrotate(:,i) = self%gamma_L(i) * (Htmp + self%damping(i)* cross(S_in(:,i), Htmp))
639 1731730 : self%Stmp(:, i)= rotate_S_DM(S_in(:,i), self%Hrotate(:,i), self%dt)
640 : end do
641 2002 : call self%mps%allgatherv_dp2d(self%Stmp, 3, self%buffer)
642 2002 : end subroutine spin_mover_t_run_one_step_DM
643 :
644 0 : subroutine spin_mover_t_run_one_step_MC(self, effpot, S_in, etot, displacement, strain, lwf, energy_table)
645 : class(spin_mover_t), intent(inout) :: self
646 : class(abstract_potential_t), intent(inout) :: effpot
647 : real(dp), optional, intent(inout) :: displacement(:, :), strain(:,:), lwf(:)
648 : real(dp), intent(inout) :: S_in(3,self%nspin)
649 : real(dp), intent(out) :: etot
650 : type(hash_table_t),optional, intent(inout) :: energy_table
651 0 : if(present(displacement) .or. present(lwf) .or. present(strain)) then
652 0 : ABI_BUG("Monte Carlo only implemented for spin.")
653 : else
654 0 : call self%spin_mc%run_MC(self%rng, effpot, S_in, etot, bfield=self%Htmp)
655 : end if
656 0 : call energy_table%put(self%label, etot)
657 0 : end subroutine spin_mover_t_run_one_step_MC
658 :
659 2002 : subroutine spin_mover_t_run_one_step(self, effpot, displacement, strain, spin, lwf, energy_table)
660 : class(spin_mover_t), intent(inout) :: self
661 : class(abstract_potential_t), intent(inout) :: effpot
662 : real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
663 : real(dp) :: etot
664 : type(hash_table_t),optional, intent(inout) :: energy_table
665 :
666 2002 : if(present(spin)) ABI_ERROR("spin should not be input for spin mover.")
667 2002 : if(self%method==1) then
668 : call self%run_one_step_HeunP(effpot=effpot, S_in=self%Stmp, etot=etot, &
669 0 : displacement=displacement, strain=strain, lwf=lwf, energy_table=energy_table)
670 2002 : else if (self%method==2) then
671 : call self%run_one_step_DM(effpot=effpot, S_in=self%Stmp, etot=etot,&
672 6006 : displacement=displacement, strain=strain, lwf=lwf, energy_table=energy_table)
673 0 : else if (self%method==3) then
674 0 : if(present(displacement) .or. present(strain) .or. present(lwf)) then
675 0 : ABI_ERROR("Monte carlo not implemented for lattice and lwf yet.")
676 : endif
677 0 : call self%run_one_step_MC(effpot, self%Stmp, etot, energy_table=energy_table)
678 0 : else if (self%method==20) then
679 : call self%run_one_step_dummy(effpot=effpot, S_in=self%Stmp, etot=etot, &
680 0 : displacement=displacement, strain=strain, lwf=lwf, energy_table=energy_table)
681 : end if
682 :
683 : ! do not inc until time is set to hist.
684 : ! run one step does not know about time. So it will be done in the outer loop.
685 2002 : if(self%mps%irank==0) then
686 2002 : call self%hist%set_vars(S=self%Stmp, Snorm=effpot%supercell%spin%ms, etot=etot, inc=.False.)
687 : end if
688 2002 : end subroutine spin_mover_t_run_one_step
689 :
690 : !!****f* m_spin_mover/spin_mover_t_run_time
691 : !!
692 : !! NAME
693 : !! spin_mover_t_run_time
694 : !!
695 : !! FUNCTION
696 : !! run all spin step
697 : !!
698 : !! INPUTS
699 : !!
700 : !! OUTPUT
701 : !!
702 : !! NOTES
703 : !!
704 : !!
705 : !! SOURCE
706 0 : subroutine spin_mover_t_run_time(self, calculator, displacement, strain, spin, lwf, energy_table)
707 :
708 : class(spin_mover_t), intent(inout):: self
709 : class(abstract_potential_t), intent(inout) :: calculator
710 :
711 : real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), lwf(:), spin(:,:)
712 :
713 : type(hash_table_t),optional, intent(inout) :: energy_table
714 : !type(spin_hist_t), intent(inout) :: hist
715 : !type(spin_ncfile_t), intent(inout) :: ncfile
716 : !type(spin_observable_t), intent(inout) :: ob
717 : !real(dp) :: S(3, self%nspin)
718 : real(dp):: t, etotal
719 : integer :: counter, i, ii
720 : character(len=80) :: msg, msg_empty
721 :
722 : integer :: master, my_rank, comm, nproc
723 : logical :: iam_master
724 :
725 0 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
726 :
727 0 : t=0.0
728 0 : counter=0
729 0 : if(iam_master) then
730 0 : msg_empty=ch10
731 :
732 0 : msg=repeat("=", 80)
733 0 : call wrtout(std_out,msg,'COLL')
734 0 : call wrtout(ab_out, msg, 'COLL')
735 0 : write(msg, '(A20)') "Spin dynamic steps:"
736 0 : call wrtout(std_out,msg,'COLL')
737 0 : call wrtout(ab_out, msg, 'COLL')
738 0 : msg=repeat("=", 80)
739 0 : call wrtout(std_out,msg,'COLL')
740 0 : call wrtout(ab_out, msg, 'COLL')
741 :
742 0 : write(msg, "(A13, 4X, A13, 6X, A13, 4X, A13)") "Iteration", "time(s)", "Avg_Mst/Ms", "ETOT(Ha/uc)"
743 0 : call wrtout(std_out,msg,'COLL')
744 0 : call wrtout(ab_out, msg, 'COLL')
745 :
746 0 : msg=repeat("-", 80)
747 0 : call wrtout(std_out,msg,'COLL')
748 0 : call wrtout(ab_out, msg, 'COLL')
749 : end if
750 :
751 0 : if (abs(self%thermal_time) > 1e-30) then
752 0 : if (iam_master) then
753 0 : msg="Thermalization run:"
754 0 : call wrtout(std_out,msg,'COLL')
755 0 : call wrtout(ab_out, msg, 'COLL')
756 : end if
757 :
758 0 : do while(t<self%thermal_time)
759 0 : counter=counter+1
760 : call self%run_one_step(effpot=calculator, displacement=displacement, strain=strain, &
761 0 : & lwf=lwf, energy_table=energy_table)
762 0 : if (iam_master) then
763 0 : call self%hist%set_vars( time=t, inc=.True.)
764 0 : if(mod(counter, self%hist%spin_nctime)==0) then
765 : call self%spin_ob%get_observables( self%hist%S(:,:, self%hist%ihist_prev), &
766 0 : self%hist%Snorm(:,self%hist%ihist_prev),self%hist%etot(self%hist%ihist_prev))
767 0 : etotal = energy_table%sum_val()
768 0 : write(msg, "(A1, 1X, I13, 4X, ES13.5, 4X, ES13.5, 4X, ES13.5)") "-", counter, t*Time_Sec, &
769 0 : & self%spin_ob%Mst_norm_total/self%spin_ob%Snorm_total, &
770 0 : & etotal/self%spin_ob%nscell
771 : ! total : 13+4+...= 64
772 0 : call wrtout(std_out,msg,'COLL')
773 0 : call wrtout(ab_out, msg, 'COLL')
774 : endif
775 : end if
776 0 : t=t+self%dt
777 : end do
778 :
779 0 : t=0.0
780 0 : counter=0
781 0 : if (iam_master) then
782 0 : call self%hist%reset(array_to_zero=.False.)
783 : end if
784 : endif
785 0 : if(iam_master) then
786 0 : call self%spin_ob%reset()
787 : endif
788 :
789 0 : if (iam_master) then
790 0 : msg="Measurement run:"
791 0 : call wrtout(std_out,msg,'COLL')
792 0 : call wrtout(ab_out, msg, 'COLL')
793 : end if
794 :
795 0 : do while(t<self%total_time)
796 0 : counter=counter+1
797 : call self%run_one_step(effpot=calculator, displacement=displacement, strain=strain, &
798 0 : & spin=spin, lwf=lwf, energy_table=energy_table)
799 0 : if (iam_master) then
800 0 : call self%hist%set_vars(time=t, inc=.True.)
801 : call self%spin_ob%get_observables(self%hist%S(:,:, self%hist%ihist_prev), &
802 0 : self%hist%Snorm(:,self%hist%ihist_prev), self%hist%etot(self%hist%ihist_prev))
803 0 : if(modulo(counter, self%hist%spin_nctime)==0) then
804 0 : call self%spin_ncfile%write_one_step(self%hist)
805 0 : etotal = energy_table%sum_val()
806 0 : write(msg, "(A1, 1X, I13, 4X, ES13.5, 4X, ES13.5, 4X, ES13.5)") "-", counter, t*Time_Sec, &
807 0 : & self%spin_ob%Mst_norm_total/self%spin_ob%Snorm_total, &
808 0 : & etotal/self%spin_ob%nscell
809 0 : call wrtout(std_out,msg,'COLL')
810 0 : call wrtout(ab_out, msg, 'COLL')
811 : endif
812 : end if
813 0 : t=t+self%dt
814 : enddo
815 :
816 0 : if (iam_master) then
817 0 : msg=repeat("-", 80)
818 0 : call wrtout(std_out,msg,'COLL')
819 0 : call wrtout(ab_out, msg, 'COLL')
820 :
821 0 : write(msg, "(A27)") "Summary of spin dynamics:"
822 0 : call wrtout(std_out,msg,'COLL')
823 0 : call wrtout(ab_out, msg, 'COLL')
824 :
825 0 : write(msg, "(A65)") "At the end of the run, the average spin at each sublattice is"
826 0 : call wrtout(std_out,msg,'COLL')
827 0 : call wrtout(ab_out, msg, 'COLL')
828 :
829 0 : write(msg, "(6X, A10, 5X, 3A10, A11)") 'Sublattice', '<M_i>(x)', '<M_i>(y)', '<M_i>(z)', '||<M_i>||'
830 0 : call wrtout(std_out,msg,'COLL')
831 0 : call wrtout(ab_out, msg, 'COLL')
832 :
833 0 : do i =1, self%spin_ob%nsublatt
834 0 : write(msg, "(A1, 5X, 2X, I5.4, 8X, 4F10.5)") '-', i, &
835 0 : (self%spin_ob%Mst_sub(ii,i)/self%spin_ob%nspin_sub(i)/mu_B , ii=1, 3), &
836 0 : sqrt(sum((self%spin_ob%Mst_sub(:, i)/self%spin_ob%nspin_sub(i)/mu_B)**2))
837 0 : call wrtout(std_out,msg,'COLL')
838 0 : call wrtout(ab_out, msg, 'COLL')
839 : end do
840 :
841 0 : call wrtout(std_out,msg_empty,'COLL')
842 0 : call wrtout(ab_out, msg_empty, 'COLL')
843 :
844 : write(msg, "(A1, 1X, A11, 3X, A13, 3X, A13, 3X, A13, 3X, A13 )" ) &
845 0 : "#", "Temperature", "Cv", "chi", "BinderU4", "Mst"
846 0 : call wrtout(std_out, msg, "COLL")
847 0 : call wrtout(ab_out, msg, "COLL")
848 : write(msg, "(2X, F11.5, 3X, ES13.5, 3X, ES13.5, 3X, E13.5, 3X, ES13.5, 3X )" ) &
849 0 : self%temperature*Ha_K , self%spin_ob%Cv, self%spin_ob%chi, &
850 0 : self%spin_ob%binderU4, self%spin_ob%Avg_Mst_norm_total/self%spin_ob%snorm_total
851 0 : call wrtout(std_out, msg, "COLL")
852 0 : call wrtout(ab_out, msg, "COLL")
853 :
854 0 : msg=repeat("=", 80)
855 0 : call wrtout(std_out,msg,'COLL')
856 0 : call wrtout(ab_out, msg, 'COLL')
857 : end if
858 0 : end subroutine spin_mover_t_run_time
859 : !!***
860 :
861 :
862 :
863 :
864 : !!****f* m_spin_mover/run_MvT
865 : !!
866 : !! NAME
867 : !! run_MvT
868 : !!
869 : !! FUNCTION
870 : !! run M vs Temperature
871 : !!
872 : !! INPUTS
873 : !! pot: potential
874 : !! T_start, Tend, T_nstep
875 : !u
876 : !! OUTPUT
877 : !!
878 : !! SOURCE
879 0 : subroutine run_MvT(self, pot, ncfile_prefix, displacement, strain, spin, lwf, energy_table)
880 : class(spin_mover_t), intent(inout) :: self
881 : class(abstract_potential_t), intent(inout) :: pot
882 : real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), lwf(:), spin(:,:)
883 : character(fnlen), intent(inout) :: ncfile_prefix
884 : type(hash_table_t), optional, intent(inout) :: energy_table
885 : real(dp) :: T_start, T_end
886 : integer :: T_nstep
887 : !type(spin_ncfile_t) :: spin_ncfile
888 : character(len=4) :: post_fname
889 : real(dp) :: T, T_step
890 : integer :: i, ii, Tfile, iostat
891 : character(len=90) :: msg
892 : character(len=4200) :: Tmsg ! to write to var T file
893 : character(len=150) :: iomsg
894 : character(fnlen) :: Tfname ! file name for output various T calculation
895 0 : real(dp), allocatable :: Tlist(:), chi_list(:), Cv_list(:), binderU4_list(:)
896 0 : real(dp), allocatable :: Mst_sub_norm_list(:, :)
897 0 : real(dp), allocatable :: Mst_norm_total_list(:)
898 :
899 : integer :: master, my_rank, comm, nproc, ierr
900 : logical :: iam_master
901 0 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
902 :
903 0 : if (iam_master) then
904 0 : T_start=self%params%spin_temperature_start
905 0 : T_end=self%params%spin_temperature_end
906 0 : T_nstep=self%params%spin_temperature_nstep
907 0 : Tfile=get_unit()
908 0 : Tfname = trim(ncfile_prefix)//'.varT'
909 0 : iostat=open_file(file=Tfname, unit=Tfile, iomsg=iomsg )
910 0 : if (T_nstep<=1) then
911 : T_step=0.0
912 : else
913 0 : T_step=(T_end-T_start)/(T_nstep-1)
914 : endif
915 : write(msg, "(A52, ES13.5, A11, ES13.5, A1)") &
916 0 : & "Starting temperature dependent calculations. T from ", &
917 0 : & T_start*Ha_K, "K to ", T_end*Ha_K, " K."
918 0 : call wrtout(std_out, msg, "COLL")
919 0 : call wrtout(ab_out, msg, "COLL")
920 :
921 0 : ABI_MALLOC(Tlist, (T_nstep))
922 0 : ABI_MALLOC(chi_list, (T_nstep))
923 0 : ABI_MALLOC(Cv_list, (T_nstep))
924 0 : ABI_MALLOC(binderU4_list, (T_nstep))
925 0 : ABI_MALLOC(Mst_sub_norm_list, (self%spin_ob%nsublatt, T_nstep))
926 0 : ABI_MALLOC( Mst_norm_total_list, (T_nstep))
927 : end if
928 :
929 0 : call xmpi_bcast(T_nstep, 0, comm, ierr)
930 :
931 : ! write header of varT file
932 0 : if(iam_master) then
933 : write(Tmsg, "(A1, 1X, A11, 3X, A13, 3X, A13, 3X, A13, 3X, A13, 3X, *(I13, 3X) )" ) &
934 0 : "#", "Temperature (K)", "Cv (1)", "chi (1)", "BinderU4 (1)", "Mst/Ms(1)", (ii, ii=1, self%spin_ob%nsublatt)
935 0 : call wrtout(Tfile, Tmsg, "COLL")
936 0 : flush(Tfile)
937 : endif
938 :
939 :
940 :
941 :
942 0 : do i=1, T_nstep
943 0 : if(iam_master) then
944 0 : T=T_start+(i-1)*T_step
945 0 : msg=repeat("=", 79)
946 0 : call wrtout(std_out, msg, "COLL")
947 0 : call wrtout(ab_out, msg, "COLL")
948 :
949 0 : write(msg, "(A13, 5X, ES13.5, A3)") "Temperature: ", T*Ha_K, " K."
950 0 : call wrtout(std_out, msg, "COLL")
951 0 : call wrtout(ab_out, msg, "COLL")
952 :
953 0 : call self%hist%reset(array_to_zero=.False.)
954 : ! set temperature
955 : ! TODO make this into a subroutine set_params
956 0 : self%params%spin_temperature=T
957 : endif
958 0 : call self%set_temperature(temperature=T)
959 :
960 0 : if(iam_master) then
961 : call self%hist%set_params(spin_nctime=self%params%spin_nctime, &
962 0 : & spin_temperature=T)
963 0 : call self%spin_ob%reset(self%params)
964 : endif
965 : ! uncomment if then to use spin initializer at every temperature. otherwise use last temperature
966 0 : if(i==1) then
967 0 : call self%set_initial_state(mode=self%params%spin_init_state)
968 : else
969 0 : if(iam_master) then
970 0 : call self%hist%inc1()
971 : endif
972 : endif
973 :
974 0 : if(iam_master) then
975 0 : write(post_fname, "(I4.4)") i
976 : call self%prepare_ncfile( self%params, &
977 0 : & trim(ncfile_prefix)//'_T'//post_fname//'_spinhist.nc')
978 0 : call self%spin_ncfile%write_one_step(self%hist)
979 : endif
980 :
981 : ! run in parallel
982 : call self%run_time(pot, displacement=displacement, strain=strain, spin=spin, &
983 0 : & lwf=lwf, energy_table=energy_table)
984 :
985 0 : if(iam_master) then
986 0 : call self%spin_ncfile%close()
987 : ! save observables
988 0 : Tlist(i)=T
989 0 : chi_list(i)=self%spin_ob%chi
990 0 : Cv_list(i)=self%spin_ob%Cv
991 0 : binderU4_list(i)=self%spin_ob%binderU4
992 : !Mst_sub_list(:,:,i)=self%spin_ob%Mst_sub(:,:) ! not useful
993 0 : Mst_sub_norm_list(:,i)=self%spin_ob%Avg_Mst_sub_norm(:)
994 0 : Mst_norm_total_list(i)=self%spin_ob%Avg_Mst_norm_total
995 :
996 : ! write to varT file
997 : write(Tmsg, "(2X, F11.5, 3X, ES13.5, 3X, ES13.5, 3X, E13.5, 3X, ES13.5, 3X, *(ES13.5, 3X) )" ) &
998 0 : Tlist(i)*Ha_K, Cv_list(i), chi_list(i), binderU4_list(i), Mst_norm_total_list(i)/self%spin_ob%snorm_total,&
999 0 : & (Mst_sub_norm_list(ii,i)/mu_B, ii=1, self%spin_ob%nsublatt)
1000 0 : call wrtout(Tfile, Tmsg, "COLL")
1001 0 : flush(Tfile)
1002 :
1003 : endif
1004 :
1005 : end do
1006 :
1007 :
1008 0 : if(iam_master) then
1009 : ! write summary of MvT run
1010 0 : msg=repeat("=", 79)
1011 0 : call wrtout(std_out, msg, "COLL")
1012 0 : call wrtout(ab_out, msg, "COLL")
1013 :
1014 0 : write(msg, *) "Summary of various T run: "
1015 0 : call wrtout(std_out, msg, "COLL")
1016 0 : call wrtout(ab_out, msg, "COLL")
1017 :
1018 : write(msg, "(A1, 1X, A11, 3X, A13, 3X, A13, 3X, A13, 3X, A13)" ) &
1019 0 : "#", "Temperature", "Cv", "chi", "BinderU4", "Mst"
1020 0 : call wrtout(std_out, msg, "COLL")
1021 0 : call wrtout(ab_out, msg, "COLL")
1022 :
1023 0 : do i = 1, T_nstep
1024 : write(msg, "(2X, F11.5, 3X, ES13.5, 3X, ES13.5, 3X, E13.5, 3X, ES13.5 )" ) &
1025 0 : Tlist(i)*Ha_K, Cv_list(i), chi_list(i), binderU4_list(i), Mst_norm_total_list(i)/self%spin_ob%snorm_total
1026 0 : call wrtout(std_out, msg, "COLL")
1027 0 : call wrtout(ab_out, msg, "COLL")
1028 : end do
1029 :
1030 0 : msg=repeat("=", 79)
1031 0 : call wrtout(std_out, msg, "COLL")
1032 0 : call wrtout(ab_out, msg, "COLL")
1033 :
1034 :
1035 : ! close varT file
1036 0 : iostat= close_unit(unit=Tfile, iomsg=iomsg)
1037 :
1038 0 : ABI_FREE(Tlist)
1039 0 : ABI_FREE(chi_list)
1040 0 : ABI_FREE(Cv_list)
1041 0 : ABI_FREE(binderU4_list)
1042 0 : ABI_FREE(Mst_sub_norm_list)
1043 0 : ABI_FREE( Mst_norm_total_list)
1044 :
1045 : endif
1046 0 : end subroutine run_MvT
1047 : !!***
1048 :
1049 : !!****f* m_spin_mover/current_spin
1050 : !!
1051 : !! NAME
1052 : !! current_spin
1053 : !!
1054 : !! FUNCTION
1055 : !! return the current spin state
1056 : !!
1057 : !! INPUTS
1058 : !!
1059 : !!
1060 : !! OUTPUT
1061 : !!
1062 : !!
1063 : !!
1064 : !! SOURCE
1065 0 : function current_spin(self) result(ret)
1066 : class(spin_mover_t), target, intent(inout) :: self
1067 : real(dp), pointer :: ret(:,:)
1068 : integer :: i
1069 0 : i=self%hist%findIndex(step=0)
1070 0 : ret => self%hist%S(:,:,i)
1071 0 : end function current_spin
1072 : !!***
1073 :
1074 :
1075 :
1076 :
1077 : !!****f* m_spin_mover/finalize
1078 : !!
1079 : !! NAME
1080 : !! finalize
1081 : !!
1082 : !! FUNCTION
1083 : !! finalize spin mover.
1084 : !!
1085 : !! INPUTS
1086 : !!
1087 : !! OUTPUT
1088 : !!
1089 : !! NOTES
1090 : !! does nothing. But it's better to preserve initialize-finalize symmetry.
1091 : !!
1092 : !! SOURCE
1093 2 : subroutine finalize(self)
1094 :
1095 : class(spin_mover_t), intent(inout):: self
1096 2 : if(allocated(self%gyro_ratio) ) then
1097 2 : ABI_FREE(self%gyro_ratio)
1098 : end if
1099 :
1100 2 : if(allocated(self%damping) ) then
1101 2 : ABI_FREE(self%damping)
1102 : end if
1103 :
1104 2 : if(allocated(self%gamma_l) ) then
1105 2 : ABI_FREE(self%gamma_l)
1106 : end if
1107 :
1108 2 : if(allocated(self%H_lang_coeff) ) then
1109 2 : ABI_FREE(self%H_lang_coeff)
1110 : end if
1111 :
1112 2 : if(allocated(self%ms) ) then
1113 2 : ABI_FREE(self%ms)
1114 : end if
1115 :
1116 :
1117 :
1118 2 : if(self%method==3) then
1119 0 : call self%spin_mc%finalize()
1120 : end if
1121 :
1122 2 : if(allocated(self%Stmp)) then
1123 2 : ABI_FREE(self%Stmp)
1124 : end if
1125 :
1126 2 : if(allocated(self%Stmp2)) then
1127 2 : ABI_FREE(self%Stmp2)
1128 : end if
1129 :
1130 :
1131 2 : if(allocated(self%Heff_tmp)) then
1132 2 : ABI_FREE(self%Heff_tmp)
1133 : end if
1134 :
1135 2 : if(allocated(self%Htmp)) then
1136 2 : ABI_FREE(self%Htmp)
1137 : end if
1138 :
1139 2 : if(allocated(self%Hrotate)) then
1140 2 : ABI_FREE(self%Hrotate)
1141 : end if
1142 :
1143 2 : if(allocated(self%H_lang)) then
1144 2 : ABI_FREE(self%H_lang)
1145 : end if
1146 :
1147 2 : if(allocated(self%buffer)) then
1148 2 : ABI_FREE(self%buffer)
1149 : end if
1150 :
1151 :
1152 2 : nullify(self%supercell)
1153 2 : nullify(self%params)
1154 2 : nullify(self%rng)
1155 2 : call self%mps%finalize()
1156 2 : call self%hist%finalize()
1157 2 : call self%spin_ob%finalize()
1158 : !call self%spin_ncfile%close()
1159 2 : call self%spin_ob%finalize()
1160 2 : end subroutine finalize
1161 : !!***
1162 :
1163 0 : end module m_spin_mover
|