LCOV - code coverage report
Current view: top level - src/78_effpot - m_multibinit_manager.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 77.1 % 301 232
Test Date: 2026-09-21 22:40:37 Functions: 77.3 % 22 17

            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
        

Generated by: LCOV version 2.3-1