LCOV - code coverage report
Current view: top level - src/78_effpot - m_spin_hist.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.0 % 105 85
Test Date: 2026-09-19 17:42:43 Functions: 70.0 % 10 7

            Line data    Source code
       1              : !!****m* ABINIT/m_spin_hist
       2              : !! NAME
       3              : !! m_spin_hist
       4              : !!
       5              : !! FUNCTION
       6              : !! This module contains definition the type spin_hist_t
       7              : !! and its related routines
       8              : !! The observables are also calculated.
       9              : !!
      10              : !! Datatypes:
      11              : !!
      12              : !! * spin_hist_t: history record of spin orientations and amplitudes
      13              : !!
      14              : !! Subroutines:
      15              : !!
      16              : !! * init
      17              : !! * free
      18              : !! * spin_hist_t
      19              : !! * get_S
      20              : !! * findIndex
      21              : !! * set_vars
      22              : !! * set_params
      23              : !!
      24              : !!
      25              : !! COPYRIGHT
      26              : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      27              : !! This file is distributed under the terms of the
      28              : !! GNU General Public License, see ~abinit/COPYING
      29              : !! or http://www.gnu.org/copyleft/gpl.txt .
      30              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      31              : !!
      32              : !! SOURCE
      33              : 
      34              : ! TODO hexu:
      35              : ! sync ihist_latt when with lattice dynamics
      36              : ! add average, variance, etc (should they be here?)
      37              : ! structural information and some parameters are no longer
      38              : ! used here. They should be removed form this file.
      39              : 
      40              : #if defined HAVE_CONFIG_H
      41              : #include "config.h"
      42              : #endif
      43              : 
      44              : #include "abi_common.h"
      45              : module m_spin_hist
      46              :   use defs_basis
      47              :   use m_abicore
      48              :   use m_errors
      49              :   use m_xmpi
      50              :   implicit none
      51              : 
      52              :   private
      53              : !!***
      54              : 
      55              :   !----------------------------------------------------------------------
      56              : 
      57              :   !!****t* m_spin_hist/spin_hist_t
      58              :   !! NAME
      59              :   !! spin_hist_t
      60              :   !!
      61              :   !! FUNCTION
      62              :   !! This type has several vectors, and index scalars to store
      63              :   !! a proper history of previous evaluations of forces and
      64              :   !! stresses,velocities,positions and energies
      65              :   !!
      66              :   !! It contains:
      67              :   !! * mxhist                  : Maximum size of history
      68              :   !! * ihist                   : index of history
      69              : 
      70              :   !! natoms : number of atoms
      71              :   !! nspin: number of magnetic atoms
      72              :   !! * acell(3)         : Acell (acell , rprimd, xred: only initial value kept if there is!!  no lattice dynamics. Other wise for each step, the corresponding lattice step number is kept)
      73              :   !! * rprimd(3,3)      : Rprimd
      74              :   !! * xred(3,natoms)    : Xred
      75              :   !! * index_spin     : the index of atom in spin model, -1 if it is not in the spin model
      76              :   !! * heff(3,nspin,mxhist)   : effective magnetic field (cartesian)
      77              :   !! * snorm(nspin, mxhist) : magnetitude of spin.
      78              :   !! * S(3,nspin,mxhist)   : spin orientation of atoms (cartesian)
      79              :   !! * dSdt(3, nspin, mxhist) : dS/dt (cartesian)
      80              :   !! * etot(mxhist)            : Electronic total Energy
      81              :   !! * entropy(mxhist)         : Entropy
      82              :   !! * itime(mxhist)           : index of spin dynamics step.
      83              :   !! * time(mxhist)            : Time (or iteration number for GO)
      84              :   !!
      85              :   !! * has_latt (whether lattice dynamics is also present)
      86              :   !! * ihist_latt(mxhist): the corresponding lattice step. 0 if none.
      87              :   !! SOURCE
      88              : 
      89              :   type, public :: spin_hist_t
      90              :      ! scalars
      91              :      ! Index of the last element on all records
      92              :      integer :: ihist = 0
      93              :      integer :: ihist_prev = -1
      94              :      ! Maximun size of the historical records
      95              :      integer :: mxhist = 0
      96              : 
      97              :      integer :: nspin, nspin_prim
      98              :      ! whether lattice dynamics is also present
      99              :      integer, allocatable :: ihist_latt(:)
     100              :      logical :: has_latt
     101              : 
     102              :      ! arrays
     103              :      !  placeholders for structure-related parameters. They are not used currently.
     104              :      integer :: natoms
     105              :      real(dp) :: acell(3)
     106              :      real(dp) :: rprimd(3,3)
     107              :      real(dp), allocatable :: xred(:, :)
     108              :      integer :: ntypat
     109              :      integer, allocatable :: typat(:)
     110              :      real(dp), allocatable :: znucl(:)
     111              :      integer, allocatable :: spin_index(:)
     112              : 
     113              :      ! spin
     114              :      !heff(3, nspin, mxhist)
     115              :      real(dp), allocatable :: heff(:, :, :)
     116              :      !snorm(nspin, mxhist)
     117              :      real(dp), allocatable :: snorm(:, :)
     118              : 
     119              :      !S(3, nspin, mxhist)
     120              :      real(dp), allocatable :: S(:, :, :)
     121              :      !dSdt(3, nspin, mxhist)
     122              :      ! TODO hexu: is it useful?
     123              :      real(dp), allocatable :: dSdt(:, :, :)
     124              : 
     125              :      ! etot(mxhist)
     126              :      real(dp), allocatable :: etot(:)
     127              :      real(dp), allocatable :: entropy(:)
     128              :      real(dp), allocatable :: time(:)
     129              :      integer, allocatable :: itime(:)
     130              : 
     131              :      ! spin_nctime: interval of step for writing to netcdf hist file.
     132              :      integer :: spin_nctime
     133              :      real(dp) :: spin_temperature
     134              : 
     135              :      ! observables
     136              :      integer:: calc_thermo_obs, calc_traj_obs, calc_correlation_obs
     137              : 
     138              :      real(dp), allocatable :: ms_sub(:,:)   ! staggered M.
     139              :      real(dp), allocatable :: Cv(:) ! specfic heat
     140              :      real(dp), allocatable :: binderU4_sub(:,:), binderU4(:)
     141              :      real(dp), allocatable :: chi_sub(:, :), chi(:) ! magnetic susceptibility
     142              :      real(dp), allocatable :: rcorr(:,:)
     143              :      real(dp), allocatable :: sp_corr_func(:,:,:)
     144              :    contains
     145              :      procedure :: initialize
     146              :      procedure :: finalize
     147              :      procedure :: reset
     148              :      procedure :: set_vars
     149              :      procedure :: get_S => get_S
     150              :      procedure :: findIndex => findIndex
     151              :      procedure :: set_params => set_params
     152              :      procedure :: inc1
     153              :   end type spin_hist_t
     154              :   !!***
     155              : 
     156              :   !public :: spinhist2var
     157              :   !public :: var2spinhist
     158              :   !public :: write_sd_hist
     159              :   !public :: read_md_hist
     160              :   !public :: get_dims_spinhist
     161              : 
     162              : contains
     163              : 
     164              : 
     165              : !!****f* m_spin_hist/initialize
     166              : !!
     167              : !! NAME
     168              : !! initialize
     169              : !!
     170              : !! FUNCTION
     171              : !! initialize spin hist
     172              : !!
     173              : !! INPUTS
     174              : !! nspin = number of magnetic atoms
     175              : !! mxhist = maximum number of hist steps
     176              : !! has_latt = whether spin dynamics in with lattice dynamics
     177              : !!
     178              : !! OUTPUT
     179              : !! hist <type(spin_hist_t)()> = spin hist type
     180              : !! SOURCE
     181              : 
     182            2 :   subroutine initialize(self, nspin, mxhist, has_latt)
     183              : 
     184              :     class(spin_hist_t), intent(inout) :: self
     185              :     integer, intent(in) :: nspin, mxhist
     186              :     logical, intent(in) :: has_latt
     187              :     !integer, optional,  intent(in) :: calc_traj_obs, calc_thermo_obs, calc_correlation_obs
     188              : 
     189            2 :     self%nspin=nspin
     190            2 :     self%ntypat=0
     191            2 :     self%ihist=1
     192            2 :     self%ihist_prev=0
     193            2 :     self%mxhist=mxhist
     194            2 :     self%natoms=0
     195            2 :     self%has_latt=has_latt
     196              : 
     197            8 :     ABI_MALLOC(self%heff, (3, nspin, mxhist))
     198            8 :     ABI_MALLOC(self%snorm, (nspin, mxhist))
     199            6 :     ABI_MALLOC(self%S, (3, nspin, mxhist))
     200            6 :     ABI_MALLOC(self%dSdt, (3, nspin, mxhist))
     201              : 
     202            6 :     ABI_MALLOC(self%etot, (mxhist))
     203            4 :     ABI_MALLOC(self%entropy, (mxhist))
     204            4 :     ABI_MALLOC(self%time, (mxhist))
     205            6 :     ABI_MALLOC(self%itime, (mxhist))
     206              : 
     207            4 :     ABI_MALLOC(self%ihist_latt, (mxhist))
     208              : 
     209              :     ! TODO: add observable allocation here.
     210              : 
     211            2 :     self%etot(1) =zero
     212            2 :     self%entropy(1) =zero
     213            2 :     self%time(1) =zero
     214              : 
     215              :     !self%acell(:)=zero
     216              :     !self%rprimd(:, :)=zero
     217              :     !self%xred(:,:) =zero
     218         5192 :     self%heff(:,:,:)=zero
     219         5192 :     self%S(:,:,:)=zero
     220         5192 :     self%dSdt(:,:,:)=zero
     221         1304 :     self%snorm(:,:)=zero
     222            2 :   end subroutine initialize
     223              : !!***
     224              : 
     225            2 :   subroutine reset(self, array_to_zero)
     226              :     class(spin_hist_t), intent(inout) :: self
     227              :     logical :: array_to_zero
     228            2 :     self%ntypat=0
     229            2 :     self%ihist=1
     230            2 :     self%ihist_prev=0
     231            2 :     self%natoms=0
     232              : 
     233            2 :     self%etot(1) =zero
     234            2 :     self%entropy(1) =zero
     235            2 :     self%time(1) =zero
     236              : 
     237            2 :     if(array_to_zero) then
     238            0 :        self%heff(:,:,1)=zero
     239            0 :        self%S(:,:,1)=zero
     240            0 :        self%dSdt(:,:,1)=zero
     241            0 :        self%snorm(:,1)=zero
     242            0 :        self%Cv( 1)=zero
     243            0 :        self%sp_corr_func(:, :, 1)=zero
     244              :     endif
     245              : 
     246              : 
     247            2 :   end subroutine reset
     248              : 
     249              :   !!****f* m_spin_hist/set_atomic_structure
     250              :   !!
     251              :   !! NAME
     252              :   !! set_atomic_structure
     253              :   !!
     254              :   !! FUNCTION
     255              :   !!
     256              :   !! set atomic structure
     257              :   !!
     258              :   !! INPUTS
     259              :   !! acell(3) = acell
     260              :   !! rprimd(3, 3) =
     261              :   !! xred(3, natoms) = positions in reduced coordinates
     262              :   !! spin_index(3, natoms) = index of atom in spin hamiltonian
     263              :   !! ntypat = number of types of atoms
     264              :   !! typat(ntypat)=types of atoms
     265              :   !! znucl=z of atoms
     266              :   !!
     267              :   !! OUTPUT
     268              :   !! hist <type(spin_hist_t)()> = spin hist type
     269              :   !! SOURCE
     270              :   subroutine set_atomic_structure(self, acell, rprimd, xred, spin_index, ntypat,  typat, znucl)
     271              : 
     272              :     class(spin_hist_t), intent(inout) :: self
     273              :     real(dp), intent(in) :: acell(3), rprimd(3,3), xred(:,:), znucl(:)
     274              :     integer, intent(in):: spin_index(:), ntypat, typat(:)
     275              :     integer :: natoms
     276              :     natoms=size(typat)
     277              :     ABI_MALLOC(self%xred, (3, natoms))
     278              :     ABI_MALLOC(self%spin_index, (natoms))
     279              :     ABI_MALLOC(self%typat,(ntypat))
     280              :     ABI_MALLOC(self%znucl, (ntypat))
     281              : 
     282              :     self%acell(:)=acell(:)
     283              :     self%rprimd(:,:)=rprimd(:,:)
     284              :     self%xred(:,:)=xred(:,:)
     285              :     self%spin_index(:)=spin_index(:)
     286              :     self%ntypat=ntypat
     287              :     self%typat(:)=typat(:)
     288              :     self%znucl(:)=znucl(:)
     289              :   end subroutine set_atomic_structure
     290              :   !!***
     291              : 
     292              : 
     293              :   !!****f* m_spin_hist/set_params
     294              :   !!
     295              :   !! NAME
     296              :   !! set_params
     297              :   !!
     298              :   !! FUNCTION
     299              :   !!
     300              :   !! set parameters for spin_hist_t
     301              :   !!
     302              :   !! INPUTS
     303              :   !! spin_nctime=number of step between two write to netcdf hist file
     304              :   !! spin_temperate= temperature of spin
     305              :   !!
     306              :   !! OUTPUT
     307              :   !! hist <type(spin_hist_t)()> = spin hist type
     308              :   !! SOURCE
     309              : 
     310            2 :   subroutine set_params(self, spin_nctime, spin_temperature)
     311              : 
     312              :     class(spin_hist_t), intent(inout) :: self
     313              :     integer, intent(in) :: spin_nctime
     314              :     real(dp), intent(in) :: spin_temperature
     315            2 :     self%spin_nctime= spin_nctime
     316            2 :     self%spin_temperature=spin_temperature
     317            2 :   end subroutine set_params
     318              : !!***
     319              : 
     320              :   !!****f* m_spin_hist/finalize
     321              :   !!
     322              :   !! NAME
     323              :   !! finalize
     324              :   !!
     325              :   !! FUNCTION
     326              :   !!
     327              :   !! free memory for spin_hist_t
     328              :   !!
     329              :   !! INPUTS
     330              :   !!
     331              :   !! OUTPUT
     332              :   !! hist <type(spin_hist_t)()> = spin hist type
     333              :   !! SOURCE
     334            2 :   subroutine finalize(self)
     335              : 
     336              :     class(spin_hist_t) , intent(inout) :: self
     337              : 
     338            2 :     ABI_SFREE(self%xred)
     339            2 :     ABI_SFREE(self%typat)
     340            2 :     ABI_SFREE(self%znucl)
     341            2 :     ABI_SFREE(self%spin_index)
     342            2 :     ABI_SFREE(self%heff)
     343            2 :     ABI_SFREE(self%snorm)
     344            2 :     ABI_SFREE(self%S)
     345            2 :     ABI_SFREE(self%dSdt)
     346            2 :     ABI_SFREE(self%etot)
     347            2 :     ABI_SFREE(self%entropy)
     348            2 :     ABI_SFREE(self%time)
     349            2 :     ABI_SFREE(self%itime)
     350            2 :     ABI_SFREE(self%ihist_latt)
     351              : 
     352            2 :   end subroutine finalize
     353              : !!***
     354              : 
     355              : 
     356              : 
     357              :   !!****f* m_spin_hist/get_S
     358              :   !!
     359              :   !! NAME
     360              :   !! get_S
     361              :   !!
     362              :   !! FUNCTION
     363              :   !!
     364              :   !! get the S for step. step=0 is current. step=-1 is last...
     365              :   !!
     366              :   !! INPUTS
     367              :   !! hist <type(spin_hist_t)()> = spin hist type
     368              :   !! step = index of step. current step is 0. last step is -1.
     369              :   !! OUTPUT
     370              :   !! S(3, nspin)=spin orientations at step
     371              :   !! SOURCE
     372            0 :   function get_S(self, step) result(S)
     373              :     class(spin_hist_t), intent(inout) :: self
     374              :     integer, intent(in), optional:: step
     375              :     real(dp) :: S(3, self%nspin)
     376              :     integer :: i, j
     377            0 :     if (.not. present(step)) then
     378            0 :        j=0
     379              :     else
     380            0 :        j=step
     381              :     end if
     382            0 :     i=self%findIndex(step=j)
     383            0 :     S(:,:)=self%S(:,:,i)
     384            0 :   end function get_S
     385              :   !!***
     386              : 
     387              :   !!****f* m_spin_hist/inc1
     388              :   !!
     389              :   !! NAME
     390              :   !! inc1
     391              :   !!
     392              :   !! FUNCTION
     393              :   !!
     394              :   !! time counter increase
     395              :   !!
     396              :   !! INPUTS
     397              :   !!
     398              :   !! OUTPUT
     399              :   !!   hist <type(spin_hist_t)()> = spin hist type
     400              :   !! SOURCE
     401         2004 :   subroutine inc1(self)
     402              : 
     403              :     class(spin_hist_t), intent(inout) :: self
     404         2004 :     if(self%ihist_prev ==0 ) then
     405            4 :         self%itime(self%ihist)=1
     406              :     else
     407         2000 :         self%itime(self%ihist)=self%itime(self%ihist_prev)+1
     408              :     endif
     409         2004 :     self%ihist_prev=self%ihist
     410         2004 :     self%ihist=self%findIndex(1)
     411         2004 :   end subroutine inc1
     412              :   !!***
     413              : 
     414              : 
     415              :   !!***f* m_spin_hist/findIndex
     416              :   !!
     417              :   !! NAME
     418              :   !! get_findIndex
     419              :   !!
     420              :   !! FUNCTION
     421              :   !! get the index of the step in the self%S array
     422              :   !! INPUTS
     423              :   !!
     424              :   !! OUTPUT
     425              :   !!   index: the index of the step in the self%S array.
     426              :   !! SOURCE
     427         2004 :   function findIndex(self, step) result(index)
     428              : 
     429              :     class(spin_hist_t), intent(inout) :: self
     430              :     integer , intent(in) :: step
     431              :     integer :: index
     432              :     !Local variables-------------------------------
     433              :     !scalars
     434              :     integer :: mxhist
     435              :     !arrays
     436              :     character(len=500) :: msg
     437              :     ! *************************************************************
     438              : 
     439         2004 :     mxhist = self%mxhist
     440         2004 :     if ((mxhist ==1.and.step/=+1).or.&
     441              :          &    (mxhist /=1.and.abs(step) >=mxhist)) then
     442            0 :        write(msg,'(a,I0,2a)')' The requested step must be less than ',mxhist,ch10,&
     443            0 :             &                     'Action: increase the number of history store in the hist'
     444            0 :        ABI_BUG(msg)
     445              :     end if
     446         2004 :     index= mod(self%ihist+step, self%mxhist)+1
     447         2004 :   end function findIndex
     448              :   !!***
     449              : 
     450              : 
     451              :   !!***f* m_spin_hist/set_vars
     452              :   !!
     453              :   !! NAME
     454              :   !! get_set_vars
     455              :   !!
     456              :   !! FUNCTION
     457              :   !! put the data into hist
     458              :   !! INPUTS
     459              :   !! S(3, nspin)=spin orientation
     460              :   !! Snorm(nspin)=spin amplitude
     461              :   !! dSdt(3,nspin)= dS/dt
     462              :   !! Heff(3, nspin) = effective magnetic field
     463              :   !! etot = total energy
     464              :   !! entropy = entropy
     465              :   !! time = time (note: not index of time)
     466              :   !! ihist_latt = index of lattice dynamics step.
     467              :   !! inc = whether this step is finished. If true, increment counter.
     468              :   !! OUTPUT
     469              :   !!   index: the index of the step in the self%S array.
     470              :   !! SOURCE
     471         4008 :   subroutine set_vars(self, S, Snorm, dSdt, Heff, etot, entropy, time, ihist_latt, inc)
     472              : 
     473              :     class(spin_hist_t), intent(inout) ::self
     474              :     real(dp), optional, intent(in) :: S(3, self%nspin), Snorm(self%nspin), dSdt(3, self%nspin), &
     475              :         &  Heff(3, self%nspin), etot, entropy, time
     476              :     integer, optional :: ihist_latt
     477              :     logical, intent(in), optional :: inc
     478              :     integer :: ihist
     479         4006 :     ihist=self%ihist
     480         4006 :     if(present(inc)) then
     481         4006 :        if (inc) then
     482         2004 :           call self%inc1()
     483              :        end if
     484              :     end if
     485         4006 :     if(present(S)) then
     486      1733460 :        self%S(:, :, ihist)=S(:,:)
     487              :     end if
     488         4006 :     if(present(Snorm)) then
     489       434868 :        self%Snorm(:,  ihist)=Snorm(:)
     490              :     endif
     491         4006 :     if(present(dSdt)) then
     492            0 :        self%dSdt(:, :, ihist)=dSdt(:,:)
     493              :     end if
     494         4006 :     if(present(Heff)) then
     495            0 :        self%Heff(:, :, ihist)=Heff(:,:)
     496              :     end if
     497         4006 :     if(present(etot)) then
     498         2002 :        self%etot(ihist)=etot
     499              :     end if
     500         4006 :     if(present(entropy)) then
     501            0 :        self%entropy(ihist)=entropy
     502              :     end if
     503         4006 :     if(present(time)) then
     504         2004 :        self%time( ihist)=time
     505              :     end if
     506         4006 :     if(present(ihist_latt)) then
     507            2 :        self%ihist_latt(ihist)=ihist_latt
     508              :     endif
     509         8014 :   end subroutine set_vars
     510              :   !!***
     511              : 
     512            0 : end module m_spin_hist
        

Generated by: LCOV version 2.3-1