Branch data 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
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
|