Line data Source code
1 : !!****m* ABINIT/m_multibinit_manager
2 : !! NAME
3 : !! m_multibinit_manager
4 : !!
5 : !! FUNCTION
6 : !! This module contains the manager type, which is a thin layer above ALL
7 : !! TODO: the structure of this is yet to be discussed
8 : !!
9 : !!
10 : !! Datatypes:
11 : !!
12 : !! * mb_manager_t
13 : !!
14 : !! Subroutines:
15 : !! TODO: add this when F2003 doc style is determined.
16 : !!
17 : !!
18 : !! COPYRIGHT
19 : !! Copyright (C) 2001-2026 ABINIT group (hexu)
20 : !! This file is distributed under the terms of the
21 : !! GNU General Public License, see ~abinit/COPYING
22 : !! or http://www.gnu.org/copyleft/gpl.txt .
23 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
24 : !!
25 : !! SOURCE
26 :
27 :
28 : #if defined HAVE_CONFIG_H
29 : #include "config.h"
30 : #endif
31 :
32 : #include "abi_common.h"
33 :
34 : module m_multibinit_manager
35 : use defs_basis
36 : use m_abicore
37 : use m_errors
38 : use m_xmpi
39 :
40 : use m_init10, only: init10, postfix_fnames
41 : use m_mathfuncs, only: diag
42 : use m_hashtable_strval, only: hash_table_t
43 : use m_multibinit_dataset, only: multibinit_dtset_type, invars10, &
44 : outvars_multibinit, multibinit_dtset_free
45 : ! random number generator
46 : use m_random_xoroshiro128plus, only: rng_t
47 :
48 : ! cells
49 : use m_supercell_maker, only: supercell_maker_t
50 : use m_multibinit_cell, only: mbcell_t, mbsupercell_t
51 :
52 : ! primitive potential
53 : use m_primitive_potential_list, only: primitive_potential_list_t
54 : use m_primitive_potential, only: primitive_potential_t
55 :
56 : !
57 : use m_abstract_potential, only: abstract_potential_t
58 : use m_potential_list, only: potential_list_t
59 : use m_abstract_mover, only: abstract_mover_t
60 : use m_lattice_effpot, only : lattice_effpot_t
61 :
62 : ! Spin
63 : use m_spin_primitive_potential, only: spin_primitive_potential_t
64 : use m_spin_potential, only : spin_potential_t
65 : use m_spin_mover, only : spin_mover_t
66 : use m_mpi_scheduler, only: init_mpi_info
67 : ! TODO : should these be moved into spin mover?
68 : use m_spin_ncfile, only: spin_ncfile_t
69 :
70 : ! Lattice harmonic
71 : use m_lattice_harmonic_primitive_potential, only: lattice_harmonic_primitive_potential_t
72 : use m_lattice_harmonic_potential, only: lattice_harmonic_potential_t
73 :
74 : ! Lattice movers
75 : use m_lattice_mover, only: lattice_mover_t
76 : use m_lattice_langevin_mover, only: lattice_langevin_mover_t
77 : use m_lattice_verlet_mover, only: lattice_verlet_mover_t
78 : use m_lattice_berendsen_NVT_mover, only: lattice_berendsen_NVT_mover_t
79 : use m_lattice_berendsen_NPT_mover, only: lattice_berendsen_NPT_mover_t
80 : use m_lattice_dummy_mover, only: lattice_dummy_mover_t
81 :
82 : ! Spin lattice coupling
83 : use m_slc_primitive_potential, only: slc_primitive_potential_t
84 : use m_slc_potential, only : slc_potential_t
85 : use m_slc_dynamics
86 :
87 : ! LWF
88 : use m_lwf_primitive_potential, only: lwf_primitive_potential_t
89 : use m_lwf_potential, only: lwf_potential_t
90 : use m_lwf_mover, only: lwf_mover_t
91 : use m_lwf_mc_mover, only: lwf_mc_t
92 : use m_lwf_dummy_mover, only: lwf_dummy_mover_t
93 : use m_lwf_berendsen_mover, only: lwf_berendsen_mover_t
94 :
95 : ! lattice-lwf hybrid
96 : use m_lattice_lwf_mover, only: lattice_lwf_mover_t
97 :
98 : implicit none
99 : private
100 :
101 :
102 : !!***
103 :
104 : !-------------------------------------------------------------------!
105 : ! Multibinit manager
106 : !-------------------------------------------------------------------!
107 : type, public :: mb_manager_t
108 : character(len=fnlen) :: input_path
109 : character(len=fnlen) :: filenames(18)
110 : ! pointer to parameters. it is a pointer because it is initialized outside manager
111 : type(multibinit_dtset_type), pointer :: params=>null()
112 : type(supercell_maker_t) :: sc_maker ! supercell maker
113 : type(mbcell_t) :: unitcell ! unitcell
114 : type(mbsupercell_t) :: supercell ! supercell
115 : type(primitive_potential_list_t) :: prim_pots ! list of primitive potentials
116 : type(potential_list_t) :: pots ! potential list
117 : ! a polymorphic lattice mover so multiple mover could be used.
118 : class(lattice_mover_t), pointer :: lattice_mover => null()
119 : ! as for the spin, there is only one mover which has several methods
120 : type(spin_mover_t), pointer :: spin_mover => null()
121 : ! type(lwf_mover_t) :: lwf_mover
122 :
123 : type(slc_mover_t) :: slc_mover
124 : class(lwf_mover_t), pointer :: lwf_mover => null()
125 :
126 : ! spin netcdf hist file
127 : type(rng_t) :: rng
128 : type(hash_table_t) :: energy_table
129 : ! DOC: The energy table contains
130 : ! The elements are updated by:
131 : ! - The movers: kinetic energy
132 : ! - The potentials: potential energy.
133 : ! Note that for potential_list, do not update the
134 : ! TODO: should we add a tag in the potential list to make it aware of
135 : ! whether to save itself as a whole in the energy table or ask its components
136 : ! to save the energy terms?
137 : ! FIXME: the extra white spaces are also saved to the keys of the table.
138 : ! usage:call energy_table%put("Name", value): update/insert energy term.
139 : ! call energy_table%print_all() : print all energy terms to screen.
140 : ! s= energy_table%sum_val() : sum up all energy terms.
141 :
142 : ! TODO: this is temporary. Remove after moving to multibinit_main2
143 : ! It means the parsing of the params are already done outside the manager.
144 : logical :: use_external_params=.True.
145 :
146 : logical :: has_displacement = .False.
147 : logical :: has_strain = .False.
148 : logical :: has_spin = .False.
149 : logical :: has_lwf = .False.
150 : contains
151 : procedure :: initialize
152 : procedure :: finalize
153 : procedure :: read_params ! parse input file
154 :
155 : procedure :: prepare_params ! process the parameters. e.g. convert unit, set some flags, etc.
156 : procedure :: read_potentials ! read primitve cell and potential
157 : procedure :: fill_supercell
158 : procedure :: set_movers
159 : procedure :: set_spin_mover
160 : procedure :: set_lattice_mover
161 : procedure :: set_lwf_mover
162 : procedure :: run_spin_dynamics
163 : procedure :: run_spin_varT
164 : procedure :: run_lattice_dynamics
165 : procedure :: run_lattice_varT
166 : procedure :: run_coupled_spin_latt_dynamics
167 : procedure :: run_lwf_dynamics
168 : procedure :: run_lwf_varT
169 : procedure :: run_lattice_lwf_dynamics
170 : procedure :: run
171 : procedure :: run_all
172 : end type mb_manager_t
173 :
174 : contains
175 : !-------------------------------------------------------------------!
176 : ! initialize
177 : !-------------------------------------------------------------------!
178 6 : subroutine initialize(self,input_path, filenames,params)
179 : class(mb_manager_t), intent(inout) :: self
180 : character(len=fnlen), intent(inout) :: input_path
181 : character(len=fnlen), intent(inout) :: filenames(18)
182 : type(multibinit_dtset_type), target, optional, intent(in) :: params
183 : integer :: master, my_rank, comm, nproc, ierr
184 : logical :: iam_master
185 : integer :: i
186 : integer :: c
187 6 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
188 6 : self%input_path=input_path
189 114 : self%filenames(:)=filenames(:)
190 6 : call xmpi_bcast(self%filenames, master, comm, ierr)
191 : !TODO: remove params as argument. It is here because the params are read
192 : ! in the multibinit_main function. Once we use multibinit_main2, remove it.
193 6 : if (present(params)) then
194 0 : self%params=>params
195 : else
196 6 : self%use_external_params=.False.
197 6 : ABI_MALLOC_SCALAR(self%params)
198 6 : call self%read_params()
199 : endif
200 :
201 : ! Initialize the random number generator
202 6 : c=self%params%randomseed
203 6 : if(c==0) then
204 0 : call system_clock(c)
205 : endif
206 18 : call self%rng%set_seed([int(c, dp), int(c, dp)-111109_dp ])
207 :
208 :
209 : ! use jump so that each cpu generates independent random numbers.
210 6 : if(my_rank>0) then
211 0 : do i =1,my_rank
212 0 : call self%rng%jump()
213 : end do
214 : end if
215 :
216 :
217 6 : if(self%params%spin_dynamics>0) then
218 2 : self%has_spin=.True.
219 : endif
220 6 : if(self%params%dynamics >0) then
221 5 : self%has_displacement=.True.
222 5 : self%has_strain=.True.
223 : endif
224 :
225 6 : if(self%params%lwf_dynamics >0) then
226 1 : self%has_lwf=.True.
227 : end if
228 :
229 6 : call self%prepare_params()
230 : ! read potentials from
231 :
232 :
233 6 : call self%energy_table%init()
234 :
235 6 : end subroutine initialize
236 :
237 :
238 : !-------------------------------------------------------------------!
239 : ! Finalize
240 : ! NOTE: add a entry here if new type of mover
241 : !-------------------------------------------------------------------!
242 6 : subroutine finalize(self)
243 : class(mb_manager_t), intent(inout) :: self
244 6 : call self%sc_maker%finalize()
245 6 : call self%unitcell%finalize()
246 6 : call self%supercell%finalize()
247 6 : call self%prim_pots%finalize()
248 6 : call self%pots%finalize()
249 6 : if (associated(self%spin_mover)) then
250 2 : call self%spin_mover%finalize()
251 2 : ABI_FREE_SCALAR(self%spin_mover)
252 : nullify(self%spin_mover)
253 : end if
254 : ! Note that lattice mover is a pointer.
255 : ! It might be null if there is no lattice part.
256 6 : if (associated(self%lattice_mover)) then
257 5 : call self%lattice_mover%finalize()
258 10 : ABI_FREE_SCALAR(self%lattice_mover)
259 : nullify(self%lattice_mover)
260 : end if
261 :
262 6 : if (associated(self%lwf_mover)) then
263 1 : call self%lwf_mover%finalize()
264 2 : ABI_FREE_SCALAR(self%lwf_mover)
265 : nullify(self%lwf_mover)
266 : end if
267 :
268 6 : if(.not. self%use_external_params) then
269 6 : call multibinit_dtset_free(self%params)
270 6 : if (associated(self%params)) then
271 6 : ABI_FREE_SCALAR(self%params)
272 : endif
273 : endif
274 6 : nullify(self%params)
275 :
276 6 : self%has_displacement=.False.
277 6 : self%has_strain=.False.
278 6 : self%has_spin=.False.
279 6 : self%has_lwf=.False.
280 6 : call self%energy_table%free()
281 6 : call self%slc_mover%finalize()
282 6 : end subroutine finalize
283 :
284 : !-------------------------------------------------------------------!
285 : ! read_params: read parameters from input file
286 : ! TODO: This function is copied from the implementation before using F03
287 : ! Some work need to be done to move the initialization of effective
288 : ! potential out of this function.
289 : !-------------------------------------------------------------------!
290 6 : subroutine read_params(self)
291 : use m_fstrings, only : replace, inupper
292 : use m_parser, only: instrng
293 : use m_dtset, only : chkvars
294 : use m_effective_potential_file
295 : use m_effective_potential
296 : class(mb_manager_t), intent(inout) :: self
297 : integer :: lenstr
298 : integer :: natom,nph1l,nrpt,ntypat
299 : integer :: option
300 : character(len=strlen) :: string, raw_string
301 : integer :: master, my_rank, comm, nproc, ierr
302 : logical :: iam_master
303 :
304 6 : natom=0
305 6 : nph1l=0
306 6 : nrpt=0
307 6 : ntypat=0
308 6 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
309 :
310 : !Read the input file, and store the information in a long string of characters
311 : !strlen from defs_basis module
312 6 : option=1
313 6 : if (iam_master) then
314 :
315 6 : string = repeat(" ", strlen)
316 6 : raw_string = repeat(" ", strlen)
317 6 : call instrng (self%filenames(1),lenstr,option,strlen,string, raw_string)
318 : !To make case-insensitive, map characters to upper case:
319 6 : call inupper(string(1:lenstr))
320 :
321 : !Check whether the string only contains valid keywords
322 6 : call chkvars(string)
323 : end if
324 :
325 6 : call xmpi_bcast(string,master, comm, ierr)
326 6 : call xmpi_bcast(raw_string,master, comm, ierr)
327 6 : call xmpi_bcast(lenstr,master, comm, ierr)
328 :
329 : !INPUT_STRING=raw_string
330 : ! Save input string in global variable so that we can access it in ntck_open_create
331 : !ABI_MALLOC_TYPE_SCALAR(character(len=len_trim(raw_string)), INPUT_STRING)
332 : !INPUT_STRING = string(1:len_trim(raw_string))
333 :
334 : !Read the input file
335 6 : call invars10(self%params,lenstr,natom, string)
336 6 : call postfix_fnames(self%input_path, self%filenames, self%params )
337 6 : if (iam_master) then
338 : ! Echo the inputs to console and main output file
339 6 : call outvars_multibinit(self%params,std_out)
340 6 : call outvars_multibinit(self%params,ab_out)
341 : end if
342 :
343 6 : end subroutine read_params
344 :
345 : !-------------------------------------------------------------------!
346 : ! prepare_params: after read, something has to be done:
347 : ! e.g. unit conversion
348 : ! NOTE: add an entry here if there is a new dynamics with
349 : ! temperature parameter
350 : !-------------------------------------------------------------------!
351 6 : subroutine prepare_params(self)
352 : class(mb_manager_t), intent(inout) :: self
353 : ! Kelvin to Hartree (In input file, the spin temperature is in K.
354 : ! convert to a.u.)
355 6 : if(self%has_spin) then
356 2 : self%params%spin_temperature = self%params%spin_temperature/Ha_K
357 2 : self%params%spin_temperature_start=self%params%spin_temperature_start/Ha_K
358 2 : self%params%spin_temperature_end=self%params%spin_temperature_end/Ha_K
359 : end if
360 6 : if(self%has_displacement) then
361 5 : self%params%temperature = self%params%temperature/Ha_K
362 5 : self%params%latt_temperature_start =self%params%latt_temperature_start/Ha_K
363 5 : self%params%latt_temperature_end=self%params%latt_temperature_end/Ha_K
364 : end if
365 6 : if(self%has_lwf) then
366 1 : self%params%lwf_temperature = self%params%lwf_temperature/Ha_K
367 1 : self%params%lwf_temperature_start=self%params%lwf_temperature_start/Ha_K
368 1 : self%params%lwf_temperature_end=self%params%lwf_temperature_end/Ha_K
369 : end if
370 :
371 :
372 6 : end subroutine prepare_params
373 :
374 :
375 : !-------------------------------------------------------------------!
376 : ! Read potentials from file, if needed by dynamics
377 : ! NOTE: add an entry here if there is a new type of potential
378 : !-------------------------------------------------------------------!
379 12 : subroutine read_potentials(self)
380 : class(mb_manager_t), intent(inout) :: self
381 : class(primitive_potential_t), pointer :: spin_pot
382 : class(primitive_potential_t), pointer :: slc_pot
383 : class(primitive_potential_t), pointer :: lat_ham_pot
384 : class(primitive_potential_t), pointer :: lwf_pot
385 :
386 : integer :: master, my_rank, comm, nproc, ierr
387 : logical :: iam_master
388 6 : call init_mpi_info(master, iam_master, my_rank, comm, nproc)
389 6 : call self%unitcell%initialize()
390 :
391 : ! latt : TODO (replace this with full lattice)
392 : ! only toy harmonic part
393 6 : if(self%params%dynamics>100) then
394 5 : ABI_MALLOC_TYPE_SCALAR(lattice_harmonic_primitive_potential_t, lat_ham_pot)
395 : select type(lat_ham_pot)
396 : type is (lattice_harmonic_primitive_potential_t)
397 5 : call lat_ham_pot%initialize(self%unitcell)
398 5 : call lat_ham_pot%load_from_files(self%params, self%filenames)
399 5 : call self%prim_pots%append(lat_ham_pot)
400 : end select
401 : end if
402 :
403 : ! spin
404 6 : call xmpi_bcast(self%params%spin_dynamics, master, comm, ierr)
405 6 : if(self%params%spin_dynamics>0) then
406 : ! The pointer will be allocated and added to the list
407 : ! and eventually deallocated by the list%finalize
408 2 : ABI_MALLOC_TYPE_SCALAR(spin_primitive_potential_t, spin_pot)
409 :
410 : ! One may wonder why unitcell does not read data from files
411 : ! That is because the spin_pot (which has an pointer to unitcell)
412 : ! read the file and set the spin unitcell.
413 : select type(spin_pot)
414 : type is (spin_primitive_potential_t)
415 2 : call spin_pot%initialize(self%unitcell)
416 2 : call spin_pot%load_from_files(self%params, self%filenames)
417 2 : call self%prim_pots%append(spin_pot)
418 : end select
419 :
420 : end if
421 :
422 : !LWF
423 6 : if(self%params%lwf_dynamics>0 .or. self%params%latt_lwf_anharmonic==1) then
424 1 : ABI_MALLOC_TYPE_SCALAR(lwf_primitive_potential_t, lwf_pot)
425 : select type(lwf_pot)
426 : type is (lwf_primitive_potential_t)
427 1 : call lwf_pot%initialize(self%unitcell)
428 1 : if ( trim(self%params%lwf_pot_fname) /='') then
429 2 : call lwf_pot%load_from_files(self%params, [self%params%lwf_pot_fname])
430 : else
431 0 : call lwf_pot%load_from_files(self%params, [self%filenames(3)])
432 : end if
433 1 : call self%prim_pots%append(lwf_pot)
434 : end select
435 : end if
436 :
437 : ! spin-lattice coupling
438 6 : if(self%params%slc_coupling>0) then
439 2 : ABI_MALLOC_TYPE_SCALAR(slc_primitive_potential_t, slc_pot)
440 : select type(slc_pot)
441 : type is (slc_primitive_potential_t)
442 2 : call slc_pot%initialize(self%unitcell)
443 2 : call slc_pot%load_from_files(self%params, self%filenames)
444 2 : call self%prim_pots%append(slc_pot)
445 : end select
446 : endif
447 :
448 :
449 6 : end subroutine read_potentials
450 :
451 : !-------------------------------------------------------------------!
452 : ! fill supercell. Both primitive cell and potential
453 : ! NOTE: No need to do anything if there is new potential
454 : !-------------------------------------------------------------------!
455 6 : subroutine fill_supercell(self)
456 : class(mb_manager_t), target, intent(inout) :: self
457 :
458 : ! build supercell structure
459 : !call self%unitcell%fill_supercell(self%sc_maker, self%supercell)
460 6 : call self%supercell%from_unitcell(self%sc_maker, self%unitcell)
461 :
462 : ! supercell potential
463 6 : call self%pots%initialize()
464 6 : call self%pots%set_supercell(self%supercell)
465 6 : call self%prim_pots%fill_supercell_list(self%sc_maker, self%params, self%pots, self%supercell)
466 : ! why do this twice, because each pot in the supercell is not yet linked to the supercell.
467 6 : call self%pots%set_supercell(self%supercell)
468 6 : call self%pots%set_params(self%params)
469 6 : end subroutine fill_supercell
470 :
471 : !-------------------------------------------------------------------!
472 : ! Fit lattic model
473 : !-------------------------------------------------------------------!
474 : subroutine fit_lattice_model(self)
475 : class(mb_manager_t), intent(inout) :: self
476 : ABI_UNUSED_A(self)
477 : !TODO:
478 : end subroutine fit_lattice_model
479 :
480 :
481 : !-------------------------------------------------------------------!
482 : ! initialize movers which are needed.
483 : ! NOTE: add a entry here if new type of potential is added
484 : !-------------------------------------------------------------------!
485 6 : subroutine set_movers(self)
486 : class(mb_manager_t), intent(inout) :: self
487 6 : if (self%params%spin_dynamics>0) then
488 2 : call self%set_spin_mover()
489 : end if
490 :
491 6 : if (self%params%dynamics>0) then
492 5 : call self%set_lattice_mover()
493 :
494 : end if
495 :
496 6 : if (self%params%lwf_dynamics>0 .or. self%params%latt_lwf_anharmonic==1) then
497 1 : call self%set_lwf_mover()
498 : end if
499 :
500 6 : end subroutine set_movers
501 :
502 : !-------------------------------------------------------------------!
503 : !Set_spin_mover
504 : !-------------------------------------------------------------------!
505 2 : subroutine set_spin_mover(self)
506 : class(mb_manager_t), intent(inout) :: self
507 2 : if (self%params%spin_dynamics>0) then
508 2 : ABI_MALLOC_TYPE_SCALAR(spin_mover_t, self%spin_mover)
509 : end if
510 : call self%spin_mover%initialize(params=self%params,&
511 2 : & supercell=self%supercell, rng=self%rng)
512 2 : end subroutine set_spin_mover
513 :
514 :
515 :
516 : !-------------------------------------------------------------------!
517 : !Set_lattice_mover
518 : !-------------------------------------------------------------------!
519 5 : subroutine set_lattice_mover(self)
520 : class(mb_manager_t), intent(inout) :: self
521 8 : select case(self%params%dynamics)
522 : case (101) ! Velocity Verlet (NVE)
523 3 : ABI_MALLOC_TYPE_SCALAR(lattice_verlet_mover_t, self%lattice_mover)
524 : case(102) ! Langevin (NVT)
525 1 : ABI_MALLOC_TYPE_SCALAR(lattice_langevin_mover_t, self%lattice_mover)
526 : case(103) ! Berendsen NVT
527 1 : ABI_MALLOC_TYPE_SCALAR(lattice_berendsen_NVT_mover_t, self%lattice_mover)
528 : case(104) ! Berendsen NPT (not yet avaliable)
529 0 : ABI_MALLOC_TYPE_SCALAR(lattice_berendsen_NPT_mover_t, self%lattice_mover)
530 : case(120) ! Dummy mover (Do not move atoms, For test only.)
531 5 : ABI_MALLOC_TYPE_SCALAR(lattice_dummy_mover_t, self%lattice_mover)
532 : end select
533 5 : call self%lattice_mover%initialize(params=self%params, supercell=self%supercell, rng=self%rng)
534 5 : call self%lattice_mover%set_initial_state(mode=1)
535 5 : end subroutine set_lattice_mover
536 :
537 : !-------------------------------------------------------------------!
538 : !Set_lwf_mover
539 : !-------------------------------------------------------------------!
540 1 : subroutine set_lwf_mover(self)
541 : class(mb_manager_t), intent(inout) :: self
542 1 : if(self%params%latt_lwf_anharmonic==1) then
543 0 : self%params%lwf_dynamics=2
544 : end if
545 1 : select case(self%params%lwf_dynamics)
546 : case (1) ! Metropolis Monte Carlo
547 0 : ABI_MALLOC_TYPE_SCALAR(lwf_mc_t, self%lwf_mover)
548 : case (2) ! dummy
549 0 : ABI_MALLOC_TYPE_SCALAR(lwf_dummy_mover_t, self%lwf_mover)
550 : case (3)
551 1 : ABI_MALLOC_TYPE_SCALAR(lwf_berendsen_mover_t, self%lwf_mover)
552 : end select
553 1 : call self%lwf_mover%initialize(params=self%params, supercell=self%supercell, rng=self%rng)
554 1 : call self%lwf_mover%set_initial_state(mode=self%params%lwf_init_state )
555 1 : call self%lwf_mover%read_lwf_constraints(trim(self%params%lwf_init_hist_fname))
556 :
557 1 : end subroutine set_lwf_mover
558 :
559 :
560 : !-------------------------------------------------------------------!
561 : ! Run dynamics
562 : !-------------------------------------------------------------------!
563 0 : subroutine run_spin_dynamics(self)
564 : class(mb_manager_t), intent(inout) :: self
565 0 : call self%prim_pots%initialize()
566 0 : call self%read_potentials()
567 : !call self%sc_maker%initialize(diag(self%params%ncell))
568 0 : call self%sc_maker%initialize(self%params%ncellmat)
569 0 : call self%fill_supercell()
570 0 : call self%set_movers()
571 0 : call self%spin_mover%set_ncfile_name(self%params, self%filenames(2))
572 0 : call self%spin_mover%run_time(self%pots, energy_table=self%energy_table)
573 0 : call self%spin_mover%spin_ncfile%close()
574 0 : end subroutine run_spin_dynamics
575 :
576 :
577 0 : subroutine run_spin_varT(self)
578 : class(mb_manager_t), intent(inout) :: self
579 0 : call self%prim_pots%initialize()
580 : !call self%sc_maker%initialize(diag(self%params%ncell))
581 0 : call self%sc_maker%initialize(self%params%ncellmat)
582 0 : call self%read_potentials()
583 0 : call self%fill_supercell()
584 0 : call self%set_movers()
585 0 : call self%spin_mover%run_MvT(self%pots, self%filenames(2), energy_table=self%energy_table)
586 0 : end subroutine run_spin_varT
587 :
588 :
589 : !-------------------------------------------------------------------!
590 : ! Run lattice only dynamics
591 : !-------------------------------------------------------------------!
592 3 : subroutine run_lattice_dynamics(self)
593 : class(mb_manager_t), intent(inout) :: self
594 3 : call self%prim_pots%initialize()
595 3 : call self%read_potentials()
596 : !call self%sc_maker%initialize(diag(self%params%ncell))
597 3 : call self%sc_maker%initialize(self%params%ncellmat)
598 3 : call self%fill_supercell()
599 3 : call self%set_movers()
600 3 : call self%lattice_mover%set_ncfile_name(self%params, self%filenames(2))
601 3 : call self%lattice_mover%run_time(self%pots, energy_table=self%energy_table)
602 3 : call self%lattice_mover%ncfile%finalize()
603 3 : end subroutine run_lattice_dynamics
604 :
605 :
606 : !-------------------------------------------------------------------!
607 : ! Run lattice only dynamics at various T
608 : !-------------------------------------------------------------------!
609 0 : subroutine run_lattice_varT(self)
610 : class(mb_manager_t), intent(inout) :: self
611 0 : call self%prim_pots%initialize()
612 0 : call self%read_potentials()
613 0 : call self%sc_maker%initialize(self%params%ncellmat)
614 0 : call self%fill_supercell()
615 0 : call self%set_movers()
616 0 : call self%lattice_mover%run_varT(self%pots, self%filenames(2), energy_table=self%energy_table)
617 0 : end subroutine run_lattice_varT
618 :
619 :
620 :
621 : !-------------------------------------------------------------------!
622 : ! Run lattice lwf hybrid dynamics
623 : !-------------------------------------------------------------------!
624 0 : subroutine run_lattice_lwf_dynamics(self)
625 : class(mb_manager_t), intent(inout) :: self
626 : type(lattice_lwf_mover_t) :: mover
627 0 : call self%prim_pots%initialize()
628 0 : call self%read_potentials()
629 : !call self%sc_maker%initialize(diag(self%params%ncell))
630 :
631 0 : call self%sc_maker%initialize(self%params%ncellmat)
632 0 : call self%fill_supercell()
633 0 : call self%set_movers()
634 0 : call self%lattice_mover%set_ncfile_name(self%params, self%filenames(2))
635 0 : call self%lwf_mover%set_ncfile_name(self%params, self%filenames(2))
636 0 : call mover%initialize(self%lattice_mover, self%lwf_mover)
637 0 : call mover%run_time(self%pots, energy_table=self%energy_table)
638 0 : call self%lattice_mover%ncfile%finalize()
639 0 : call self%lwf_mover%ncfile%finalize()
640 0 : call mover%finalize()
641 0 : end subroutine run_lattice_lwf_dynamics
642 :
643 :
644 :
645 :
646 : !-------------------------------------------------------------------!
647 : ! Run coupled lattice spin dynamics
648 : ! TODO: This is only a prototype. It does not have the proper logic
649 : ! to decide the time step, etc.
650 : ! TODO: move this to somewhere else, perhaps a spin-lattice mover file.
651 : !-------------------------------------------------------------------!
652 2 : subroutine run_coupled_spin_latt_dynamics(self)
653 : class(mb_manager_t), intent(inout) :: self
654 :
655 : character(len=90) :: msg
656 :
657 2 : real(dp), allocatable :: Htmp(:,:)
658 : real(dp) :: etotal
659 : integer :: i
660 :
661 2 : call self%prim_pots%initialize()
662 2 : call self%read_potentials()
663 :
664 2 : call self%sc_maker%initialize(self%params%ncellmat)
665 2 : call self%fill_supercell()
666 :
667 : ! calculate various quantities for reference spin structure
668 8 : do i =1, self%pots%size
669 : select type (scpot => self%pots%list(i)%ptr) ! use select type because properties only defined for spin_potential are used
670 : type is (spin_potential_t)
671 6 : ABI_MALLOC(Htmp, (3,scpot%nspin))
672 2 : call scpot%get_Heff(scpot%supercell%spin%Sref, Htmp, scpot%eref)
673 2 : ABI_FREE(Htmp)
674 : end select
675 :
676 2 : select type (scpot => self%pots%list(i)%ptr) ! use select type because properties only defined for slc_potential are used
677 : type is (slc_potential_t)
678 2 : call scpot%calculate_ref()
679 : end select
680 : enddo
681 :
682 2 : call self%set_movers()
683 :
684 2 : call self%spin_mover%set_ncfile_name(self%params, self%filenames(2))
685 2 : call self%slc_mover%initialize(self%spin_mover, self%lattice_mover)
686 : call self%slc_mover%run_time(self%pots, displacement=self%lattice_mover%displacement, &
687 2 : & spin=self%spin_mover%Stmp, energy_table=self%energy_table)
688 2 : msg=repeat("=", 80)
689 2 : call wrtout(std_out,msg,'COLL')
690 2 : call wrtout(ab_out, msg, 'COLL')
691 2 : msg='Energy contributions'
692 2 : call wrtout(std_out,msg,'COLL')
693 2 : call wrtout(ab_out, msg, 'COLL')
694 2 : msg=' Lattice contributions'
695 2 : call wrtout(std_out,msg,'COLL')
696 2 : call wrtout(ab_out, msg, 'COLL')
697 2 : call self%energy_table%print_entry(label='Lattice kinetic energy')
698 2 : call self%energy_table%print_entry(label='Lattice_harmonic_potential')
699 2 : msg=' Spin contributions'
700 2 : call wrtout(std_out,msg,'COLL')
701 2 : call wrtout(ab_out, msg, 'COLL')
702 2 : call self%energy_table%print_entry(label='SpinPotential')
703 2 : msg=' Spin-lattice coupling contributions'
704 2 : call wrtout(std_out,msg,'COLL')
705 2 : call wrtout(ab_out, msg, 'COLL')
706 2 : call self%energy_table%print_entry(prefix='SLCPotential')
707 2 : etotal=self%energy_table%sum_val()
708 2 : write(msg, "(A12, 29X, ES13.5)") 'Total energy', etotal
709 2 : call wrtout(std_out,msg,'COLL')
710 2 : call wrtout(ab_out, msg, 'COLL')
711 2 : msg=repeat("=", 80)
712 2 : call wrtout(std_out,msg,'COLL')
713 2 : call wrtout(ab_out, msg, 'COLL')
714 :
715 2 : call self%spin_mover%spin_ncfile%close()
716 2 : end subroutine run_coupled_spin_latt_dynamics
717 :
718 : !-------------------------------------------------------------------!
719 : ! Run LWF dynamics
720 : !-------------------------------------------------------------------!
721 0 : subroutine run_lwf_dynamics(self)
722 : class(mb_manager_t), intent(inout) :: self
723 0 : call self%prim_pots%initialize()
724 0 : call self%read_potentials()
725 : !call self%sc_maker%initialize(diag(self%params%ncell))
726 0 : call self%sc_maker%initialize(self%params%ncellmat)
727 :
728 0 : call self%fill_supercell()
729 0 : call self%set_movers()
730 0 : call self%lwf_mover%set_ncfile_name(self%params, self%filenames(2))
731 0 : call self%lwf_mover%run_time(self%pots, energy_table=self%energy_table)
732 0 : call self%lwf_mover%ncfile%finalize()
733 0 : end subroutine run_lwf_dynamics
734 :
735 : !-------------------------------------------------------------------!
736 : ! Run LWF dynamics at various T
737 : !-------------------------------------------------------------------!
738 1 : subroutine run_lwf_varT(self)
739 : class(mb_manager_t), intent(inout) :: self
740 1 : call self%prim_pots%initialize()
741 1 : call self%read_potentials()
742 : !call self%sc_maker%initialize(diag(self%params%ncell))
743 1 : call self%sc_maker%initialize(self%params%ncellmat)
744 1 : call self%fill_supercell()
745 1 : call self%set_movers()
746 : !call self%lwf_mover%set_ncfile_name(self%params, self%filenames(2))
747 : !call self%lwf_mover%run_varT(self%pots, energy_table=self%energy_table)
748 1 : call self%lwf_mover%run_varT(self%pots, self%filenames(2), energy_table=self%energy_table)
749 : !call self%lwf_mover%ncfile%finalize()
750 1 : end subroutine run_lwf_varT
751 :
752 :
753 :
754 :
755 :
756 : !-------------------------------------------------------------------!
757 : ! Run all jobs
758 : ! NOTE: add a entry here if new type of dynamics
759 : !-------------------------------------------------------------------!
760 6 : subroutine run(self)
761 : class(mb_manager_t), intent(inout) :: self
762 : ! if ... fit lattice model
763 : ! if ... fit lwf model
764 : ! if ... run dynamics...
765 : ! spin dynamics
766 6 : if(self%params%latt_lwf_anharmonic==1)then
767 0 : self%params%lwf_dynamics=2
768 : end if
769 :
770 6 : if(self%params%spin_dynamics>0 .and. self%params%dynamics<=0 .and. self%params%lwf_dynamics<=0) then
771 0 : if(self%params%spin_var_temperature==0) then
772 0 : call self%run_spin_dynamics()
773 0 : elseif (self%params%spin_var_temperature==1) then
774 0 : call self%run_spin_varT()
775 : end if
776 : ! lattice
777 6 : else if(self%params%dynamics>0 .and. self%params%spin_dynamics<=0 .and. self%params%lwf_dynamics<=0)then
778 3 : if(self%params%latt_var_temperature==0) then
779 3 : call self%run_lattice_dynamics()
780 : else
781 0 : call self%run_lattice_varT()
782 : end if
783 :
784 : ! lattice + dummy lwf
785 3 : else if(self%params%dynamics>0 .and. self%params%spin_dynamics<=0 .and. self%params%latt_lwf_anharmonic==1) then
786 0 : call self%run_lattice_lwf_dynamics()
787 : ! spin+lattice
788 3 : else if (self%params%dynamics>0 .and. self%params%spin_dynamics>0 .and. self%params%lwf_dynamics<=0) then
789 : !call self%run_spin_latt_dynamics()
790 2 : call self%run_coupled_spin_latt_dynamics()
791 : ! lwf
792 1 : else if(self%params%dynamics<=0 .and. self%params%spin_dynamics<=0 .and. self%params%lwf_dynamics>0) then
793 1 : if (self%params%lwf_var_temperature==0) then
794 0 : call self%run_lwf_dynamics()
795 : else
796 1 : call self%run_lwf_varT()
797 : end if
798 : end if
799 :
800 6 : end subroutine run
801 :
802 :
803 :
804 : !-------------------------------------------------------------------!
805 : !run_all: THE function which does everything
806 : ! from the very begining to end.
807 : !-------------------------------------------------------------------!
808 6 : subroutine run_all(self, input_path, filenames, dry_run)
809 : class(mb_manager_t), intent(inout) :: self
810 : character(len=fnlen), intent(inout) :: input_path
811 : character(len=fnlen), intent(inout) :: filenames(18)
812 : integer, intent(in) :: dry_run
813 6 : call self%initialize(input_path, filenames)
814 6 : if (dry_run==0) then
815 6 : call self%run()
816 : else
817 0 : call wrtout([std_out, ab_out], "Multibinit in dry_run mode. Exiting after input parser")
818 0 : call xmpi_end()
819 : end if
820 6 : call self%finalize()
821 6 : end subroutine run_all
822 :
823 10 : end module m_multibinit_manager
|