LCOV - code coverage report
Current view: top level - src/78_effpot - m_spin_potential.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 77.2 % 162 125
Test Date: 2026-11-10 12:08:57 Functions: 76.5 % 17 13
Branches: 41.8 % 342 143

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_spin_potential
       2                 :             : !! NAME
       3                 :             : !! m_spin_potential
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module contains the spin hamiltonian, and the methods for
       7                 :             : !! calculating effective magnetic field (torque), dS/dt, and total_energy
       8                 :             : !!
       9                 :             : !!
      10                 :             : !! Datatypes:
      11                 :             : !!
      12                 :             : !! * spin_potential_t
      13                 :             : !!
      14                 :             : !! Subroutines:
      15                 :             : !!
      16                 :             : !! * spin_potential_t_initialize
      17                 :             : !! * spin_potential_t_finalize
      18                 :             : !! * spin_potential_t_total_Heff : calculate total Heff (no Langevin term)
      19                 :             : !! * spin_potential_t_Heff_to_dSdt:
      20                 :             : !!  * spin_potential_t_get_dSdt : dSdt, Langevin term is an input.
      21                 :             : !!  * spin_potential_t_get_Langevin_Heff
      22                 :             : 
      23                 :             : !!
      24                 :             : !!
      25                 :             : !! COPYRIGHT
      26                 :             : !! Copyright (C) 2001-2026 ABINIT group (TO, 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                 :             : #if defined HAVE_CONFIG_H
      35                 :             : #include "config.h"
      36                 :             : #endif
      37                 :             : #include "abi_common.h"
      38                 :             : module  m_spin_potential
      39                 :             :   use defs_basis
      40                 :             :   use m_errors
      41                 :             :   use m_abicore
      42                 :             :   use m_xmpi
      43                 :             :   use m_mpi_scheduler, only: mb_mpi_info_t, init_mpi_info, mpi_scheduler_t
      44                 :             :   use m_multibinit_dataset, only: multibinit_dtset_type
      45                 :             :   use m_multibinit_cell, only: mbcell_t, mbsupercell_t
      46                 :             :   use m_spmat_coo, only: coo_mat_t
      47                 :             :   use m_spmat_lil, only: lil_mat_t
      48                 :             :   use m_spmat_csr, only : CSR_mat_t
      49                 :             :   use m_spmat_convert, only : spmat_convert
      50                 :             :   use m_abstract_potential, only : abstract_potential_t
      51                 :             :   use m_hashtable_strval, only: hash_table_t
      52                 :             :   implicit none
      53                 :             :   !!***
      54                 :             :   private
      55                 :             : 
      56                 :             :   type, public, extends(abstract_potential_t) :: spin_potential_t
      57                 :             :      integer :: nspin=0
      58                 :             :      logical :: has_external_hfield, has_dipdip
      59                 :             :      real(dp) :: eref !energy of reference spin state
      60                 :             : 
      61                 :             :      ! Array or scalar?
      62                 :             :      real(dp), allocatable :: external_hfield(:,:)
      63                 :             : 
      64                 :             :      ! Exchange/DMI/dipdip stored like COO sparse matrix form.
      65                 :             :      type(lil_mat_t) :: coeff_coo
      66                 :             :      logical :: csr_mat_ready= .False.
      67                 :             :      logical :: has_onsite = .False.
      68                 :             :      type(CSR_mat_t) :: bilinear_csr_mat
      69                 :             :      ! 3, 3, ninit
      70                 :             : 
      71                 :             :      ! vector for calculating effective field
      72                 :             :      real(dp), allocatable :: Htmp(:, :)
      73                 :             :      real(dp), allocatable :: ms(:)
      74                 :             :      real(dp), allocatable :: onsite_bilinear_term(:, :, :)
      75                 :             :      type(mb_mpi_info_t) :: mpiinfo
      76                 :             :      type(mpi_scheduler_t) :: mps
      77                 :             :    CONTAINS
      78                 :             :      procedure :: initialize
      79                 :             :      procedure :: finalize
      80                 :             :      procedure :: set_params
      81                 :             :      procedure :: set_supercell
      82                 :             :      procedure :: get_Heff => spin_potential_t_total_Heff
      83                 :             :      procedure :: set_external_hfield
      84                 :             :      procedure :: calc_bilinear_term_Heff
      85                 :             :      procedure :: calc_external_Heff
      86                 :             :      procedure :: calculate => spin_potential_t_calculate
      87                 :             :      !procedure :: get_energy => spin_potential_t_get_energy
      88                 :             :      procedure :: get_delta_E => spin_potential_t_get_delta_E
      89                 :             :      procedure :: add_bilinear_term
      90                 :             :      procedure :: add_bilinear_term_spin_block
      91                 :             :      procedure :: set_bilinear_term
      92                 :             :      procedure, private :: prepare_csr_matrix
      93                 :             :      procedure :: set_terms
      94                 :             :   end type spin_potential_t
      95                 :             : 
      96                 :             : contains
      97                 :             : 
      98                 :           2 :   subroutine initialize(self, nspin)
      99                 :             :     !Arguments ------------------------------------
     100                 :             :     !scalars
     101                 :             :     class(spin_potential_t), intent(inout) :: self
     102                 :             :     integer :: nspin
     103                 :             : 
     104                 :             :     integer :: master, my_rank, comm, nproc, ierr
     105                 :             :     logical :: iam_master
     106                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     107                 :           2 :     call self%mps%initialize(ntasks=nspin, master=master, comm=comm)
     108                 :           2 :     self%label="SpinPotential"
     109                 :           2 :     self%has_spin=.True.
     110                 :           2 :     self%has_displacement=.False.
     111                 :           2 :     self%has_strain=.False.
     112                 :           2 :     self%is_null=.False.
     113                 :           2 :     self%nspin=nspin
     114                 :           2 :     call xmpi_bcast(self%nspin, master, comm, ierr)
     115   [ -  +  +  -  :           6 :     ABI_MALLOC( self%ms, (self%nspin))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     116         [ +  - ]:           2 :     if(iam_master) then
     117         [ +  + ]:           6 :        call self%coeff_coo%initialize([self%nspin*3, self%nspin*3])
     118                 :             :     endif
     119   [ -  +  +  -  :           6 :     ABI_MALLOC(self%external_hfield, (3,self%nspin))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     120   [ +  +  +  + ]:        1730 :     self%external_hfield=0.0_dp
     121   [ -  +  +  -  :           4 :     ABI_MALLOC( self%Htmp, (3, self%nspin))
          -  +  -  +  -  
                      + ]
     122   [ +  +  +  + ]:        1730 :     self%Htmp(:,:)=0.0_dp
     123                 :             : 
     124                 :           2 :     self%has_external_hfield=.False.
     125                 :           2 :     self%has_dipdip=.False.
     126   [ -  +  +  -  :           6 :     ABI_MALLOC(self%onsite_bilinear_term, (3, 3, self%nspin))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     127   [ +  +  +  +  :        5618 :     self%onsite_bilinear_term = 0.0_dp
                   +  + ]
     128                 :           2 :   end subroutine initialize
     129                 :             : 
     130                 :           8 :   subroutine set_supercell(self, supercell)
     131                 :             :     class(spin_potential_t), intent(inout) :: self
     132                 :             :     type(mbsupercell_t), target, intent(inout) :: supercell
     133                 :             :     integer :: master, my_rank, comm, nproc, ierr
     134                 :             :     logical :: iam_master
     135                 :           4 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     136                 :             : 
     137                 :           4 :     self%supercell=>supercell
     138         [ +  + ]:         868 :     self%ms(:)=supercell%spin%ms(:)
     139                 :           4 :     call xmpi_bcast(self%ms, master, comm, ierr)
     140                 :           4 :   end subroutine set_supercell
     141                 :             : 
     142                 :           0 :   subroutine set_terms(self, &
     143   [ #  #  #  #  :           0 :        &     external_hfield, &
                   #  # ]
     144   [ #  #  #  #  :           0 :        & bilinear_i, bilinear_j, bilinear_val)
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     145                 :             : 
     146                 :             :     !Arguments ------------------------------------
     147                 :             :     !scalars
     148                 :             :     !arrays
     149                 :             :     class(spin_potential_t), intent(inout) :: self
     150                 :             : 
     151                 :             :     ! Terms.
     152                 :             :     real(dp), optional, intent(in) :: external_hfield(:,:)
     153                 :             :     integer, optional, intent(in) :: bilinear_i(:), bilinear_j(:)
     154                 :             :     real(dp), optional,intent(in) :: bilinear_val(:)
     155                 :             : 
     156                 :             :     !Local variables-------------------------------
     157                 :             :     ! *************************************************************************
     158                 :             : 
     159                 :             : 
     160         [ #  # ]:           0 :     if(present(external_hfield)) then
     161                 :           0 :        call self%set_external_hfield( external_hfield)
     162                 :             :     end if
     163                 :             : 
     164   [ #  #  #  # ]:           0 :     if ( present(bilinear_i) .and. present( bilinear_j) .and. present(bilinear_val) ) then
     165                 :           0 :        call self%set_bilinear_term(bilinear_i, bilinear_j, bilinear_val)
     166                 :             :     endif
     167                 :             : 
     168                 :           0 :   end subroutine set_terms
     169                 :             : 
     170                 :             :   !-------------------------------------------------------------------!
     171                 :             :   !set_params :
     172                 :             :   !-------------------------------------------------------------------!
     173                 :           2 :   subroutine set_params(self, params)
     174                 :             :     class(spin_potential_t), intent(inout) :: self
     175                 :             :     type(multibinit_dtset_type), intent(inout) :: params
     176                 :           4 :     real(dp) :: tmp(3, self%nspin)
     177                 :             :     integer :: i
     178                 :             :     integer :: master, my_rank, comm, nproc
     179                 :             :     logical :: iam_master
     180                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     181         [ +  - ]:           2 :     if(iam_master) then
     182         [ +  + ]:         434 :        do i=1, self%nspin
     183         [ +  + ]:        1730 :           tmp(:, i)=params%spin_mag_field(:)
     184                 :             :        end do
     185                 :             :     endif
     186                 :           2 :     call self%set_external_hfield(tmp)
     187                 :           2 :   end subroutine set_params
     188                 :             : 
     189                 :             : 
     190         [ -  + ]:           2 :   subroutine set_external_hfield(self, external_hfield)
     191                 :             :     class(spin_potential_t), intent(inout) :: self
     192                 :             :     real(dp), intent(in) :: external_hfield(:,:)
     193                 :             :     integer :: master, my_rank, comm, nproc, ierr
     194                 :             :     logical :: iam_master
     195                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     196                 :           2 :     self%has_external_hfield = .true.
     197   [ +  -  +  -  :        1732 :     self%external_hfield = external_hfield
          -  +  -  -  +  
                +  +  + ]
     198                 :           2 :     call xmpi_bcast(self%has_external_hfield, master, comm, ierr)
     199                 :           2 :     call xmpi_bcast(self%external_hfield, master, comm, ierr)
     200                 :           2 :   end subroutine set_external_hfield
     201                 :             : 
     202         [ -  + ]:        4006 :   subroutine calc_external_Heff(self, Heff)
     203                 :             :     class(spin_potential_t), intent(inout) :: self
     204                 :             :     real(dp), intent(out) :: Heff(:,:)
     205                 :             :     integer :: i
     206         [ +  + ]:      869302 :     do i= self%mps%istart, self%mps%iend
     207         [ +  + ]:     3465190 :       Heff(:, i)= self%external_hfield(:, i)
     208                 :             :     end do
     209                 :        4006 :   end subroutine calc_external_Heff
     210                 :             : 
     211                 :       33696 :   subroutine add_bilinear_term(self, i,j, val)
     212                 :             :     class(spin_potential_t), intent(inout) :: self
     213                 :             :     integer, intent(in) :: i, j
     214                 :             :     real(dp), intent(in) :: val
     215                 :             :     integer :: master, my_rank, comm, nproc
     216                 :             :     logical :: iam_master
     217                 :       33696 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     218         [ +  - ]:       33696 :     if(iam_master) then
     219         [ +  + ]:      101088 :        call self%coeff_coo%add_entry(ind=[i,j],val=val)
     220                 :             :     endif
     221                 :       33696 :   end subroutine add_bilinear_term
     222                 :             : 
     223   [ #  #  #  #  :           0 :   subroutine set_bilinear_term(self, ilist,jlist, vallist)
                   #  # ]
     224                 :             :     class(spin_potential_t), intent(inout) :: self
     225                 :             :     integer, intent(in) :: ilist(:), jlist(:)
     226                 :             :     real(dp), intent(in) :: vallist(:)
     227                 :             :     integer :: i
     228                 :             :     integer :: master, my_rank, comm, nproc
     229                 :             :     logical :: iam_master
     230                 :           0 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     231                 :             : 
     232         [ #  # ]:           0 :     if (iam_master) then
     233         [ #  # ]:           0 :        do i = 1, size(ilist)
     234         [ #  # ]:           0 :           call self%coeff_coo%add_entry(ind=[ilist(i),jlist(i)],val=vallist(i))
     235                 :             :        end do
     236                 :             :     endif
     237                 :           0 :   end subroutine set_bilinear_term
     238                 :             : 
     239                 :             : 
     240         [ #  # ]:           0 :   subroutine add_bilinear_term_spin_block(self, ispin, jspin, val)
     241                 :             : 
     242                 :             :     class(spin_potential_t), intent(inout) :: self
     243                 :             :     integer, intent(in) :: ispin, jspin
     244                 :             :     real(dp), intent(in) :: val(:,:)
     245                 :             :     integer :: ia, ib
     246                 :             : 
     247                 :             :     integer :: master, my_rank, comm, nproc
     248                 :             :     logical :: iam_master
     249                 :           0 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     250                 :             : 
     251         [ #  # ]:           0 :     if(iam_master) then
     252         [ #  # ]:           0 :        do ia = 1, 3, 1
     253         [ #  # ]:           0 :           do ib=1, 3, 1
     254                 :             :              call self%coeff_coo%add_entry([(ispin-1)*3+ia, &
     255         [ #  # ]:           0 :                   (jspin-1)*3+ib], val=val(ia,ib))
     256                 :             :           end do
     257                 :             :        end do
     258         [ #  # ]:           0 :        if(ispin==jspin) then
     259                 :           0 :            self%has_onsite = .True.
     260   [ #  #  #  # ]:           0 :            self%onsite_bilinear_term(:, :, ispin) = val(:, :)
     261                 :             :        end if
     262                 :             :     endif
     263                 :           0 :   end subroutine add_bilinear_term_spin_block
     264                 :             : 
     265                 :        4006 :   subroutine prepare_csr_matrix(self)
     266                 :             :     class(spin_potential_t), intent(inout) :: self
     267                 :             :     integer :: master, my_rank, comm, nproc, ierr
     268                 :             :     logical :: iam_master
     269                 :             :     integer :: ispin
     270                 :             : 
     271         [ +  + ]:        4006 :     if (.not. self%csr_mat_ready) then
     272                 :           2 :        call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     273         [ +  - ]:           2 :        if(iam_master) then
     274                 :           2 :           call spmat_convert(self%coeff_coo, self%bilinear_csr_mat)
     275                 :             :        endif
     276                 :           2 :        call self%coeff_coo%finalize()
     277                 :           2 :        call self%bilinear_csr_mat%sync(master=master, comm=comm, nblock=1)
     278                 :           2 :        self%csr_mat_ready=.True.
     279                 :           2 :        call xmpi_bcast(self%csr_mat_ready, master, comm, ierr)
     280                 :             :        ! also broadcast the onsite terms.
     281         [ +  + ]:         434 :        do ispin=1, self%nspin
     282                 :         434 :            call self%bilinear_csr_mat%get_block(ispin*3-2, ispin*3-2, 3, 3, self%onsite_bilinear_term(:, :, ispin))
     283                 :             :            !print *, "ispin:", ispin
     284                 :             :            !print *, "oniste",  self%onsite_bilinear_term(:, :, ispin)
     285                 :             :        end do
     286                 :           2 :        self%has_onsite=.True.
     287                 :             : 
     288                 :           2 :        call xmpi_bcast(self%has_onsite, master, comm, ierr)
     289                 :           2 :        call xmpi_bcast(self%onsite_bilinear_term, master, comm, ierr)
     290                 :             :     endif
     291                 :        4006 :   end subroutine prepare_csr_matrix
     292                 :             : 
     293                 :             : 
     294         [ -  + ]:        4006 :   subroutine calc_bilinear_term_Heff(self, S, Heff)
     295                 :             :     class(spin_potential_t), intent(inout) :: self
     296                 :             :     real(dp), intent(inout) :: S(:,:)
     297                 :             :     real(dp), intent(out) :: Heff(3,self%nspin)
     298                 :             :     integer :: i
     299                 :             :     !call self%bilinear_csr_mat%mv(S ,Heff)
     300                 :        4006 :     call self%prepare_csr_matrix()
     301   [ -  +  -  -  :        4006 :     call self%bilinear_csr_mat%mv_mpi(x=S ,b=Heff, bcastx=.False., syncb=.False.)
          -  -  -  -  -  
             +  -  -  -  
                      - ]
     302         [ +  + ]:      869302 :     do i= self%mps%istart, self%mps%iend
     303         [ +  + ]:     3465190 :        Heff(:, i)=Heff(:,i)/self%ms(i)*2.0_dp
     304                 :             :     end do
     305                 :        4006 :   end subroutine calc_bilinear_term_Heff
     306                 :             : 
     307   [ +  -  +  -  :        8008 :   subroutine spin_potential_t_calculate(self, displacement, strain, spin, lwf, &
                   -  + ]
     308   [ +  +  +  -  :        8008 :        force, stress, bfield, lwf_force, energy, energy_table)
                   -  + ]
     309                 :             :     class(spin_potential_t), intent(inout) :: self
     310                 :             :     real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
     311                 :             :     real(dp), optional, intent(inout) :: force(:,:), stress(:,:), bfield(:,:), lwf_force(:), energy
     312                 :             :     type(hash_table_t),optional, intent(inout) :: energy_table
     313                 :             :     real(dp) :: etmp
     314                 :             :     ! if present in input
     315                 :             :     ! calculate if required
     316                 :             : 
     317         [ +  + ]:        8008 :     if (present(bfield) ) then
     318   [ -  +  -  -  :        4004 :        call self%get_Heff(spin, bfield, etmp)
          -  -  -  -  -  
          +  -  -  -  -  
          -  -  -  +  -  
          -  -  -  -  +  
             -  -  -  - ]
     319                 :             : 
     320                 :             :        ! subtract enery of reference spin configuration
     321                 :        4004 :        etmp = etmp - self%eref
     322                 :             : 
     323                 :             :        ! only update energy when bfield is asked for.
     324         [ +  - ]:        4004 :        if ( present(energy)) then
     325                 :        4004 :           energy=energy+etmp
     326                 :             :        end if
     327         [ +  - ]:        4004 :        if (present(energy_table)) then
     328                 :        4004 :           call energy_table%put(self%label, etmp)
     329                 :             :        end if
     330                 :             :     end if
     331                 :             : 
     332                 :             : 
     333                 :        8008 :     ABI_UNUSED_A(self)
     334                 :        8008 :     ABI_UNUSED_A(displacement)
     335                 :        8008 :     ABI_UNUSED_A(strain)
     336                 :        8008 :     ABI_UNUSED_A(spin)
     337                 :        8008 :     ABI_UNUSED_A(lwf)
     338                 :        8008 :     ABI_UNUSED_A(force)
     339                 :        8008 :     ABI_UNUSED_A(stress)
     340                 :        8008 :     ABI_UNUSED_A(bfield)
     341                 :        8008 :     ABI_UNUSED_A(lwf_force)
     342                 :        8008 :     ABI_UNUSED_A(energy)
     343                 :        8008 :   end subroutine spin_potential_t_calculate
     344                 :             : 
     345                 :             : 
     346                 :        4006 :   subroutine spin_potential_t_total_Heff(self,S, Heff, energy)
     347                 :             :     class(spin_potential_t), intent(inout) :: self
     348                 :             :     real(dp), intent(inout):: S(3,self%nspin)
     349                 :             :     real(dp), intent(inout):: Heff(3,self%nspin)
     350                 :             :     real(dp), intent(inout) :: energy
     351                 :             :     real(dp) :: etmp
     352                 :             :     integer :: i, j
     353                 :             :     integer :: master, my_rank, comm, nproc, ierr
     354                 :             :     logical :: iam_master
     355                 :        4006 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     356                 :             : 
     357   [ +  +  +  + ]:     3465190 :     self%Htmp(:,:)=0.0_dp
     358                 :        4006 :     etmp=0.0_dp
     359                 :             : 
     360                 :             : 
     361                 :             :     ! calculate energy from bilinear terms (all the above ones)
     362                 :        4006 :     call self%calc_bilinear_term_Heff(S,self%Htmp)
     363         [ +  + ]:      869302 :     do i= self%mps%istart, self%mps%iend
     364         [ +  + ]:     3461184 :        Heff(:,i)=Heff(:,i)+self%Htmp(:,i)
     365         [ +  + ]:     3465190 :        do j=1, 3
     366                 :     3461184 :           etmp=etmp-(self%Htmp(j, i)*S(j,i)*self%ms(i))*0.5_dp
     367                 :             :        end do
     368                 :             :     enddo
     369                 :             :     if(iam_master) then
     370                 :             :        if (self%has_dipdip) then
     371                 :             :           continue
     372                 :             :           ! TODO implement dipdip and add it
     373                 :             :        endif
     374                 :             :     endif
     375                 :             : 
     376                 :             :     ! linear terms
     377         [ +  - ]:        4006 :     if (self%has_external_hfield) then
     378   [ +  +  +  + ]:     3465190 :         self%Htmp(:,:)= 0.0_dp
     379                 :        4006 :        call self%calc_external_Heff(self%Htmp)
     380         [ +  + ]:      869302 :          do i= self%mps%istart, self%mps%iend
     381         [ +  + ]:     3461184 :            Heff(:,i)=Heff(:,i)+self%Htmp(:,i)
     382         [ +  + ]:     3465190 :            do j=1, 3
     383                 :     3461184 :               etmp=etmp-(self%Htmp(j, i)*S(j,i)*self%ms(i))
     384                 :             :            end do
     385                 :             :          enddo
     386                 :             :     endif
     387                 :             : 
     388                 :        4006 :     call xmpi_sum_master(etmp, 0, xmpi_world, ierr )
     389                 :             :     ! NOTE: here energy is not added to input energy.
     390                 :        4006 :     energy=etmp
     391                 :             : 
     392                 :        4006 :   end subroutine spin_potential_t_total_Heff
     393                 :             : 
     394                 :             : !  subroutine spin_potential_t_get_energy(self, S, energy)
     395                 :             : !    class(spin_potential_t), intent(inout) :: self
     396                 :             : !    real(dp), intent(inout):: S(3,self%nspin)
     397                 :             : !    real(dp), intent(inout) :: energy
     398                 :             : !    integer :: i, j
     399                 :             : !    integer :: master, my_rank, comm, nproc, ierr
     400                 :             : !    logical :: iam_master
     401                 :             : !    call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     402                 :             : !
     403                 :             : !
     404                 :             : !    if (.not. self%csr_mat_ready) then
     405                 :             : !       call spmat_convert(self%coeff_coo, self%bilinear_csr_mat)
     406                 :             : !       call self%bilinear_csr_mat%sync()
     407                 :             : !       self%csr_mat_ready=.True.
     408                 :             : !    endif
     409                 :             : !    call self%bilinear_csr_mat%mv_mpi(S ,self%Htmp)
     410                 :             : !    if(iam_master) then
     411                 :             : !       energy=energy - sum(sum(self%Htmp* S, dim=1))
     412                 :             : !    endif
     413                 :             : !    if(iam_master) then
     414                 :             : !       if (self%has_external_hfield) then
     415                 :             : !          call self%calc_external_Heff(self%Htmp)
     416                 :             : !          do i=1, self%nspin
     417                 :             : !             do j=1, 3
     418                 :             : !                energy= energy- self%Htmp(j, i)*S(j, i)*self%ms(i)
     419                 :             : !             end do
     420                 :             : !          end do
     421                 :             : !       endif
     422                 :             : !    end if
     423                 :             : !  end subroutine spin_potential_t_get_energy
     424                 :             : 
     425                 :             : 
     426   [ #  #  #  # ]:           0 :   subroutine spin_potential_t_get_delta_E(self, S, ispin, Snew, deltaE)
     427                 :             :     class(spin_potential_t), intent(inout) :: self
     428                 :             :     real(dp), intent(inout):: S(:,:), Snew(:)
     429                 :             :     integer, intent(in) :: ispin
     430                 :             :     real(dp), intent(inout) ::deltaE
     431                 :             :     !real(dp) ::  Eold, Enew
     432                 :             :     real(dp) :: tmp(3), dS(3)
     433                 :             : 
     434                 :             :     ! naive implementation, for test only
     435                 :             :     !real(dp) :: Stmp(3,self%nspin), Enew, Eold
     436                 :             :     !call self%get_Heff(S, self%Htmp, Eold)
     437                 :             :     !call self%bilinear_csr_mat%mv(S, self%Htmp)
     438                 :             :     !Eold=-sum(sum(self%Htmp(:,:)*S(:,:), dim=1))
     439                 :             : 
     440                 :             :     !Stmp(:,:)=S(:,:)
     441                 :             :     !Stmp(:, ispin)= Snew(:)
     442                 :             :     !call self%get_Heff(Stmp, self%Htmp, Enew)
     443                 :             :     !deltaE=Enew-Eold
     444                 :             :     !print *, "naive deltaE", deltaE
     445                 :             : 
     446                 :             :     ! more efficient one
     447         [ #  # ]:           0 :     dS(:)=Snew(:)-S(:, ispin)
     448                 :             :     !S(:, ispin)= S(:, ispin)+ dS
     449                 :             : 
     450                 :           0 :     deltaE=0.0_dp
     451                 :             : 
     452                 :           0 :     call self%prepare_csr_matrix()
     453   [ #  #  #  #  :           0 :     call self%bilinear_csr_mat%mv_select_row(3, [3*ispin-2, 3*ispin-1, 3*ispin], S, tmp)
          #  #  #  #  #  
                #  #  # ]
     454         [ #  # ]:           0 :     deltaE=deltaE-dot_product(tmp, dS ) *2.0
     455         [ #  # ]:           0 :     if (self%has_onsite) then
     456   [ #  #  #  #  :           0 :        tmp=matmul(self%onsite_bilinear_term(:, :, ispin), dS)
             #  #  #  # ]
     457         [ #  # ]:           0 :        deltaE = deltaE -  dot_product(tmp, dS)
     458                 :             :        !print *, "dS K dS:", dot_product(tmp, dS)
     459                 :             :     end if
     460                 :             :     !print *, "smart deltaE", deltaE
     461                 :             :     !S(:, ispin)=S(:,ispin)-dS
     462                 :             :     !print *, "diff for ispin:", ispin, Enew-Eold-deltaE
     463                 :             : 
     464                 :             : 
     465         [ #  # ]:           0 :     if(self%has_external_hfield) then
     466         [ #  # ]:           0 :        deltaE=deltaE - dot_product(self%external_hfield(:, ispin), dS)*self%ms(ispin)
     467                 :             :     end if
     468                 :           0 :   end subroutine spin_potential_t_get_delta_E
     469                 :             : 
     470                 :             : 
     471                 :           2 :   subroutine finalize(self)
     472                 :             :     class(spin_potential_t), intent(inout):: self
     473         [ +  - ]:           2 :     if (allocated(self%ms)) then
     474                 :           2 :        ABI_FREE(self%ms)
     475                 :             :     end if
     476                 :             : 
     477         [ +  - ]:           2 :     ABI_SFREE(self%onsite_bilinear_term)
     478                 :             : 
     479         [ +  - ]:           2 :     if (allocated(self%Htmp)) then
     480                 :           2 :        ABI_FREE(self%Htmp)
     481                 :             :     endif
     482                 :             : 
     483         [ +  - ]:           2 :     if (allocated(self%external_hfield)) then
     484                 :           2 :        ABI_FREE(self%external_hfield)
     485                 :             :     endif
     486                 :             : 
     487                 :           2 :     call self%bilinear_csr_mat%finalize()
     488         [ -  + ]:           2 :     if (.not. self%csr_mat_ready) then
     489                 :           0 :        call self%coeff_coo%finalize()
     490                 :             :     end if
     491                 :             : 
     492                 :           2 :     call self%mps%finalize()
     493                 :             : 
     494                 :           2 :   end subroutine finalize
     495                 :             : 
     496   [ +  +  -  +  :           6 : end module m_spin_potential
          +  +  -  +  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                +  -  + ]
        

Generated by: LCOV version 2.3-1