LCOV - code coverage report
Current view: top level - src/78_effpot - m_slc_potential.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 72.2 % 198 143
Test Date: 2026-11-12 07:43:35 Functions: 83.3 % 12 10
Branches: 53.6 % 392 210

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_slc_potential
       2                 :             : !! NAME
       3                 :             : !! m_slc_potential
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module contains the spin-lattice coupling, and the methods for
       7                 :             : !! calculating effective magnetic field (torque), force, and total_energy
       8                 :             : !!
       9                 :             : !!
      10                 :             : !! COPYRIGHT
      11                 :             : !! Copyright (C) 2001-2026 ABINIT group (TO, hexu, NH)
      12                 :             : !! This file is distributed under the terms of the
      13                 :             : !! GNU General Public License, see ~abinit/COPYING
      14                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      15                 :             : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      16                 :             : !!
      17                 :             : !! SOURCE
      18                 :             : 
      19                 :             : #if defined HAVE_CONFIG_H
      20                 :             : #include "config.h"
      21                 :             : #endif
      22                 :             : #include "abi_common.h"
      23                 :             : module  m_slc_potential
      24                 :             :   use defs_basis
      25                 :             :   use m_errors
      26                 :             :   use m_abicore
      27                 :             :   use m_xmpi
      28                 :             : 
      29                 :             :   use m_hashtable_strval, only: hash_table_t
      30                 :             :   use m_abstract_potential, only : abstract_potential_t
      31                 :             :   !use m_dynamic_array, only: int2d_array_type
      32                 :             :   use m_mpi_scheduler, only: mb_mpi_info_t, init_mpi_info, mpi_scheduler_t
      33                 :             :   use m_multibinit_cell, only: mbcell_t, mbsupercell_t
      34                 :             :   use m_multibinit_dataset, only: multibinit_dtset_type
      35                 :             :   use m_spmat_ndcoo, only: ndcoo_mat_t
      36                 :             : 
      37                 :             :   implicit none
      38                 :             :   private
      39                 :             : 
      40                 :             :   type, public, extends(abstract_potential_t) :: slc_potential_t
      41                 :             :      integer :: nspin=0
      42                 :             :      integer :: natom=0
      43                 :             :      logical :: has_bilin=.False.   ! bilinear coupling term, i.e. liu
      44                 :             :      logical :: has_linquad=.False. ! spin first then lattice, i.e. niuv
      45                 :             :      logical :: has_quadlin=.False. ! spin first then lattice, i.e. oiju
      46                 :             :      logical :: has_biquad=.False.  ! biquadratic coupling term, i.e. tijuv
      47                 :             : 
      48                 :             :      type(ndcoo_mat_t) :: liu_sc           ! parameter values bilin term
      49                 :             :      type(ndcoo_mat_t) :: niuv_sc          ! parameter values linquad term
      50                 :             :      type(ndcoo_mat_t) :: oiju_sc          ! parameter values quadlin term
      51                 :             :      type(ndcoo_mat_t) :: tijuv_sc         ! parameter values biquad term
      52                 :             :      type(ndcoo_mat_t) :: tuvij_sc         ! same as tijuv but sorted differently
      53                 :             : 
      54                 :             :      ! magnetic moments
      55                 :             :      real(dp), allocatable :: ms(:)
      56                 :             : 
      57                 :             :      ! precalculated things for reference spin structure
      58                 :             :      real(dp), allocatable :: luref(:) ! force from liu for reference spin structure
      59                 :             :      real(dp), allocatable :: ouref(:) ! force from oiju for reference spin structure
      60                 :             :      type(ndcoo_mat_t) :: nuvref    ! matrix in u and v from niuv for reference spin structure
      61                 :             :      type(ndcoo_mat_t) :: tuvref    ! matrix in u and v from tijuv for reference spin structure
      62                 :             : 
      63                 :             :      ! mpi
      64                 :             :      type(mb_mpi_info_t) :: mpiinfo
      65                 :             :      type(mpi_scheduler_t) :: mpsspin
      66                 :             :      type(mpi_scheduler_t) :: mpslatt
      67                 :             : 
      68                 :             :    CONTAINS
      69                 :             :      procedure :: initialize
      70                 :             :      procedure :: finalize
      71                 :             :      procedure :: set_params
      72                 :             :      procedure :: set_supercell
      73                 :             :      procedure :: calculate_ref
      74                 :             :      procedure :: add_liu_term
      75                 :             :      procedure :: add_niuv_term
      76                 :             :      procedure :: add_oiju_term
      77                 :             :      procedure :: add_tijuv_term
      78                 :             :      procedure :: calculate
      79                 :             :   end type slc_potential_t
      80                 :             : 
      81                 :             : contains
      82                 :             : 
      83                 :           2 :   subroutine initialize(self, nspin, natom)
      84                 :             :     !Arguments ------------------------------------
      85                 :             :     !scalars
      86                 :             :     class(slc_potential_t), intent(inout) :: self
      87                 :             :     integer,                intent(in)    :: nspin
      88                 :             :     integer,                intent(in)    :: natom
      89                 :             : 
      90                 :             :     integer :: master, my_rank, comm, nproc, ierr
      91                 :             :     logical :: iam_master
      92                 :             : 
      93                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
      94                 :           2 :     call self%mpsspin%initialize(ntasks=nspin, master=master, comm=comm)
      95                 :           2 :     call self%mpslatt%initialize(ntasks=natom, master=master, comm=comm)
      96                 :           2 :     self%label="SLCPotential"
      97                 :           2 :     self%has_spin=.True.
      98                 :           2 :     self%has_displacement=.True.
      99                 :           2 :     self%has_strain=.False.
     100                 :           2 :     self%is_null=.False.
     101                 :           2 :     self%nspin=nspin
     102                 :           2 :     self%natom=natom
     103                 :             : 
     104                 :           2 :     call xmpi_bcast(self%nspin, master, comm, ierr)
     105                 :           2 :     call xmpi_bcast(self%natom, master, comm, ierr)
     106   [ -  +  +  -  :           6 :     ABI_MALLOC(self%ms, (self%nspin))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     107                 :           2 :   end subroutine initialize
     108                 :             : 
     109                 :           2 :   subroutine finalize(self)
     110                 :             : 
     111                 :             :     class(slc_potential_t), intent(inout):: self
     112         [ +  - ]:           2 :     ABI_SFREE(self%ms)
     113                 :             : 
     114         [ -  + ]:           2 :     if(self%has_bilin) then
     115                 :           0 :       call self%liu_sc%finalize()
     116         [ #  # ]:           0 :       ABI_SFREE(self%luref)
     117                 :             :     endif
     118         [ +  - ]:           2 :     if(self%has_quadlin) then
     119                 :           2 :       call self%oiju_sc%finalize()
     120         [ +  - ]:           2 :       ABI_SFREE(self%ouref)
     121                 :             :     endif
     122         [ -  + ]:           2 :     if(self%has_linquad) then
     123                 :           0 :       call self%niuv_sc%finalize()
     124                 :           0 :       call self%nuvref%finalize()
     125                 :             :     endif
     126         [ +  + ]:           2 :     if(self%has_biquad) then
     127                 :           1 :       call self%tijuv_sc%finalize()
     128                 :           1 :       call self%tuvij_sc%finalize()
     129                 :           1 :       call self%tuvref%finalize()
     130                 :             :     endif
     131                 :             : 
     132                 :           2 :     call self%mpsspin%finalize()
     133                 :           2 :     call self%mpslatt%finalize()
     134                 :             : 
     135                 :           2 :   end subroutine finalize
     136                 :             : 
     137                 :             :   !-------------------------------------------------------------------!
     138                 :             :   !set_params: which coupling terms are used
     139                 :             :   !-------------------------------------------------------------------!
     140                 :           4 :   subroutine set_params(self, params)
     141                 :             :     class(slc_potential_t), intent(inout) :: self
     142                 :             :     type(multibinit_dtset_type), intent(inout) :: params
     143                 :             : 
     144                 :             :     integer :: master, my_rank, comm, nproc, ierr, coupling
     145                 :             :     logical :: iam_master
     146                 :             : 
     147                 :           4 :     coupling = params%slc_coupling
     148                 :             : 
     149                 :           4 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     150                 :             : 
     151         [ +  - ]:           4 :     if(iam_master) then
     152         [ +  + ]:           4 :       if(coupling .ge. 1000) then
     153                 :           2 :         self%has_biquad=.True.
     154                 :           2 :         call xmpi_bcast(self%has_biquad, master, comm, ierr)
     155                 :           2 :         coupling=coupling - 1000
     156                 :             :       endif
     157                 :             : 
     158         [ -  + ]:           4 :       if(coupling .ge. 100) then
     159                 :           0 :         self%has_linquad=.True.
     160                 :           0 :         call xmpi_bcast(self%has_linquad, master, comm, ierr)
     161                 :           0 :         coupling=coupling - 100
     162                 :             :       endif
     163                 :             : 
     164         [ +  - ]:           4 :       if(coupling .ge. 10) then
     165                 :           4 :         self%has_quadlin=.True.
     166                 :           4 :         call xmpi_bcast(self%has_quadlin, master, comm, ierr)
     167                 :           4 :         coupling=coupling - 10
     168                 :             :       endif
     169                 :             : 
     170         [ -  + ]:           4 :       if(coupling .ge. 1) then
     171                 :           0 :         self%has_bilin=.True.
     172                 :           0 :         call xmpi_bcast(self%has_bilin, master, comm, ierr)
     173                 :             :       endif
     174                 :             :     endif
     175                 :           4 :   end subroutine set_params
     176                 :             : 
     177                 :             :   !-------------------------------------------------------------------!
     178                 :             :   !set_supercell: use the same supercell for all terms
     179                 :             :   !               copy magnetic moments
     180                 :             :   !-------------------------------------------------------------------!
     181                 :           8 :   subroutine set_supercell(self, supercell)
     182                 :             :     class(slc_potential_t),      intent(inout) :: self
     183                 :             :     type(mbsupercell_t), target, intent(inout) :: supercell
     184                 :             :     integer :: master, my_rank, comm, nproc, ierr
     185                 :             :     logical :: iam_master
     186                 :             : 
     187                 :           4 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     188                 :             : 
     189                 :           4 :     self%supercell=>supercell
     190         [ +  + ]:         868 :     self%ms(:)=supercell%spin%ms(:)
     191                 :             : 
     192                 :           4 :     call xmpi_bcast(self%ms, master, comm, ierr)
     193                 :           4 :   end subroutine set_supercell
     194                 :             : 
     195                 :             :   !-------------------------------------------------------------------!
     196                 :             :   !calculate ref: calculates terms necessary for the force and energy
     197                 :             :   !               of the reference structure terms
     198                 :             :   !-------------------------------------------------------------------!
     199                 :             : 
     200                 :           2 :   subroutine calculate_ref(self)
     201                 :             :     class(slc_potential_t), intent(inout) :: self
     202                 :             : 
     203                 :           4 :     real(dp) :: spref(1:3*self%nspin), beta
     204                 :             :     real(dp), allocatable :: force(:)
     205                 :             : 
     206                 :             :     integer :: master, my_rank, comm, nproc
     207                 :             :     logical :: iam_master
     208                 :             : 
     209         [ +  + ]:           4 :     spref(:) = reshape(self%supercell%spin%Sref, (/ 3*self%nspin/))
     210                 :             : 
     211                 :           2 :     beta = 0.5_dp
     212                 :             : 
     213   [ +  -  -  +  :           6 :     ABI_MALLOC(force, (3*self%natom))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     214         [ -  + ]:           2 :     if(self%has_bilin) then
     215   [ #  #  #  #  :           0 :       ABI_MALLOC(self%luref, (3*self%natom))
          #  #  #  #  #  
                      # ]
     216         [ #  # ]:           0 :       self%luref=0.0d0
     217         [ #  # ]:           0 :       force = 0.0d0
     218                 :           0 :       call self%liu_sc%vec_product2d(1, spref, 2, force)
     219         [ #  # ]:           0 :       self%luref(:) = - force(:)
     220                 :             :     endif
     221         [ +  - ]:           2 :     if(self%has_quadlin) then
     222   [ +  -  -  +  :           6 :       ABI_MALLOC(self%ouref, (3*self%natom))
          +  -  +  -  +  
          -  -  +  -  +  
                   -  + ]
     223         [ +  + ]:        6482 :       force = 0.0d0
     224                 :           2 :       call self%oiju_sc%vec_product(1, spref, 2, spref, 3, force)
     225         [ +  + ]:        6482 :       self%ouref(:) = - beta*force(:)
     226                 :             :     endif
     227         [ +  - ]:           2 :     ABI_SFREE(force)
     228                 :             : 
     229                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     230                 :             : 
     231         [ -  + ]:           2 :     if(self%has_linquad) then
     232         [ #  # ]:           0 :       if(iam_master) then
     233         [ #  # ]:           0 :         call self%nuvref%initialize(mshape=[self%natom*3, self%natom*3])
     234                 :             :       endif
     235                 :           0 :       call self%niuv_sc%mv1vec(spref, 1, self%nuvref)
     236                 :             :     endif
     237                 :             : 
     238         [ +  + ]:           2 :     if(self%has_biquad) then
     239         [ +  - ]:           1 :       if(iam_master) then
     240         [ +  + ]:           3 :          call self%tuvref%initialize(mshape=[self%natom*3, self%natom*3])
     241                 :             :       endif
     242   [ +  -  +  + ]:         649 :       call self%tijuv_sc%mv2vec(0.5*spref, spref, 1, 2, self%tuvref)
     243                 :             :     endif
     244                 :             : 
     245         [ -  + ]:           2 :   end subroutine calculate_ref
     246                 :             : 
     247                 :             :   !-----------------------------------------------------
     248                 :             :   ! add different coupling terms to supercell potential
     249                 :             :   ! TODO: test liu, niuv, tijuv
     250                 :             :   !-----------------------------------------------------
     251                 :           0 :   subroutine add_liu_term(self, i, u, val)
     252                 :             :     class(slc_potential_t), intent(inout) :: self
     253                 :             :     integer,                intent(in)    :: i, u
     254                 :             :     real(dp),               intent(in)    :: val
     255                 :             : 
     256                 :             :     integer :: master, my_rank, comm, nproc
     257                 :             :     logical :: iam_master
     258                 :             : 
     259                 :           0 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     260         [ #  # ]:           0 :     if(iam_master) then
     261         [ #  # ]:           0 :        call self%liu_sc%add_entry(ind=[i,u],val=val)
     262                 :             :     endif
     263                 :           0 :   end subroutine add_liu_term
     264                 :             : 
     265                 :             : 
     266                 :           0 :   subroutine add_niuv_term(self, i, u, v,  val)
     267                 :             :     class(slc_potential_t), intent(inout) :: self
     268                 :             :     integer,                intent(in)    :: i, u, v
     269                 :             :     real(dp),               intent(in)    :: val
     270                 :             : 
     271                 :             :     integer :: master, my_rank, comm, nproc
     272                 :             :     logical :: iam_master
     273                 :             : 
     274                 :           0 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     275         [ #  # ]:           0 :     if(iam_master) then
     276         [ #  # ]:           0 :        call self%niuv_sc%add_entry(ind=[i,u,v],val=val)
     277                 :             :     endif
     278                 :           0 :   end subroutine add_niuv_term
     279                 :             : 
     280                 :             : 
     281                 :             : 
     282                 :     1041984 :   subroutine add_oiju_term(self, i,j,u, val)
     283                 :             :     class(slc_potential_t), intent(inout) :: self
     284                 :             :     integer,                intent(in)    :: i, j, u
     285                 :             :     real(dp),               intent(in)    :: val
     286                 :             : 
     287                 :             :     integer :: master, my_rank, comm, nproc
     288                 :             :     logical :: iam_master
     289                 :             : 
     290                 :     1041984 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     291         [ +  - ]:     1041984 :     if(iam_master) then
     292         [ +  + ]:     4167936 :        call self%oiju_sc%add_entry(ind=[i,j,u],val=val)
     293                 :             :     endif
     294                 :     1041984 :   end subroutine add_oiju_term
     295                 :             : 
     296                 :       69984 :   subroutine add_tijuv_term(self, i,j,u,v, val)
     297                 :             :     class(slc_potential_t), intent(inout) :: self
     298                 :             :     integer,                intent(in)    :: i, j, u, v
     299                 :             :     real(dp),               intent(in)    :: val
     300                 :             : 
     301                 :             :     integer :: master, my_rank, comm, nproc
     302                 :             :     logical :: iam_master
     303                 :             : 
     304                 :       69984 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     305         [ +  - ]:       69984 :     if(iam_master) then
     306         [ +  + ]:      349920 :        call self%tijuv_sc%add_entry(ind=[i,j,u,v],val=val)
     307         [ +  + ]:      349920 :        call self%tuvij_sc%add_entry(ind=[u,v,i,j],val=val)
     308                 :             :     endif
     309                 :       69984 :   end subroutine add_tijuv_term
     310                 :             : 
     311                 :             : 
     312                 :             :   !-----------------------------------------------------------------
     313                 :             :   ! Calculate forces, magnetic fields and energy for coupling terms
     314                 :             :   ! TODO: precalculate terms containing Sref?
     315                 :             :   !-----------------------------------------------------------------
     316                 :             : 
     317   [ +  -  +  -  :        8008 :   subroutine calculate(self, displacement, strain, spin, lwf, &
          -  +  +  -  +  
                -  -  + ]
     318   [ +  +  +  -  :        8008 :        force, stress, bfield, lwf_force, energy, energy_table)
          -  +  +  +  +  
                -  -  + ]
     319                 :             :     class(slc_potential_t), intent(inout) :: self
     320                 :             :     real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
     321                 :             :     real(dp), optional, intent(inout) :: force(:,:), stress(:,:), bfield(:,:), lwf_force(:), energy
     322                 :             :     type(hash_table_t),optional, intent(inout) :: energy_table
     323                 :             : 
     324                 :             :     integer :: ii
     325                 :             :     character(len=80) :: label
     326                 :             :     real(dp) :: eslc, beta, eterm
     327                 :       16016 :     real(dp) :: disp(1:3*self%natom), sp(1:3*self%nspin), spref(1:3*self%nspin)
     328                 :       16016 :     real(dp) :: f1(1:3*self%natom), b1(1:3*self%nspin)
     329                 :       16016 :     real(dp) :: btmp(3, self%nspin), bslc(1:3*self%nspin), fslc(1:3*self%natom)
     330                 :             : 
     331                 :             :     ABI_UNUSED(lwf)
     332                 :             :     ABI_UNUSED(strain)
     333                 :             :     ABI_UNUSED(lwf_force)
     334                 :             :     ABI_UNUSED(stress)
     335                 :             : 
     336         [ +  + ]:       16016 :     sp(:) = reshape(spin, (/ 3*self%nspin /))
     337         [ +  + ]:       16016 :     spref(:) = reshape(self%supercell%spin%Sref, (/ 3*self%nspin/))
     338         [ +  + ]:       16016 :     disp(:) = reshape(displacement, (/ 3*self%natom /))
     339                 :             : 
     340                 :        8008 :     beta = 0.5_dp
     341                 :             : 
     342                 :             :     ! Magnetic field
     343         [ +  + ]:        8008 :     if(present(bfield)) then
     344         [ +  + ]:     2598596 :       bslc(:) = 0.0d0
     345         [ -  + ]:        4004 :       if(self%has_bilin) then
     346         [ #  # ]:           0 :         b1(:) = 0.0d0
     347                 :           0 :         call self%liu_sc%vec_product2d(2, disp, 1, b1)
     348         [ #  # ]:           0 :         bslc(:) = bslc(:) + b1(:)
     349                 :             :       endif
     350         [ -  + ]:        4004 :       if(self%has_linquad) then
     351         [ #  # ]:           0 :         b1(:) = 0.0d0
     352                 :           0 :         call self%niuv_sc%vec_product(2, disp, 3, disp, 1, b1)
     353         [ #  # ]:           0 :         bslc(:) = bslc(:) + beta*b1(:)
     354                 :             :       endif
     355         [ +  - ]:        4004 :       if(self%has_quadlin) then
     356         [ +  + ]:     2598596 :         b1(:) = 0.0d0
     357                 :        4004 :         call self%oiju_sc%vec_product(1, sp, 3, disp, 2, b1)
     358         [ +  + ]:     2598596 :         bslc(:) = bslc(:) + 2.0d0*beta*b1(:)
     359                 :             :       endif
     360         [ +  + ]:        4004 :       if(self%has_biquad) then
     361         [ +  + ]:     1299298 :         b1(:) = 0.0d0
     362                 :        2002 :         call self%tuvij_sc%vec_product4d(disp, disp, 3, sp, 4, b1)
     363         [ +  + ]:     1299298 :         bslc(:) = bslc(:) + beta*b1(:)
     364                 :             :       endif
     365         [ +  + ]:       12012 :       btmp = reshape(bslc, (/ 3, self%nspin /))
     366         [ +  + ]:      868868 :       do ii = 1, self%nspin
     367         [ +  + ]:     3463460 :         btmp(:,ii) = btmp(:,ii)/self%ms(ii)
     368                 :             :       enddo
     369   [ +  +  +  + ]:     3463460 :       bfield(:,:) = bfield(:,:) + btmp(:,:)
     370                 :             : 
     371                 :             :       ! TESTING: write magnetic fields to a file
     372                 :             :       !write(201,*) 'Magnetic fields are'
     373                 :             :       !do ii = 1, self%nspin
     374                 :             :       !  write(201,*) ii, btmp(:,ii)
     375                 :             :       !enddo
     376                 :             :     endif
     377                 :             : 
     378                 :             :     ! Force and energy
     379   [ -  +  -  - ]:        8008 :     if(present(force) .or. present(energy) .or. present(energy_table)) then
     380         [ +  + ]:    25953928 :       fslc(:) = 0.0d0
     381                 :        8008 :       eslc = 0.0d0
     382         [ -  + ]:        8008 :       if(self%has_bilin) then
     383                 :             :         eterm = 0.0d0
     384         [ #  # ]:           0 :         f1(:) = 0.0d0
     385                 :           0 :         call self%liu_sc%vec_product2d(1, sp, 2, f1)
     386         [ #  # ]:           0 :         fslc(:) = fslc(:) + f1(:)
     387         [ #  # ]:           0 :         eterm =  - dot_product(f1, disp)
     388                 :             :         ! add contributions from reference spin structure
     389         [ #  # ]:           0 :         fslc(:) = fslc(:) + self%luref(:)
     390         [ #  # ]:           0 :         eterm = eterm - dot_product(self%luref, disp)
     391         [ #  # ]:           0 :         if(present(energy_table)) then
     392         [ #  # ]:           0 :           label=trim(self%label)//'_Liu'
     393                 :           0 :           call energy_table%put(label, eterm)
     394                 :             :         endif
     395                 :           0 :         eslc = eslc + eterm
     396                 :             :       endif
     397         [ -  + ]:        8008 :       if(self%has_linquad) then
     398         [ #  # ]:           0 :         f1(:) = 0.0d0
     399                 :             :         eterm = 0.0d0
     400                 :           0 :         call self%niuv_sc%vec_product(1, sp, 2, disp, 3, f1)
     401         [ #  # ]:           0 :         fslc(:) = fslc(:) + 2.0d0*beta*f1(:)
     402         [ #  # ]:           0 :         eterm =  - beta*dot_product(f1, disp)
     403                 :             :         ! add contributions from reference spin structure
     404         [ #  # ]:           0 :         f1(:) = 0.0d0
     405                 :           0 :         call self%nuvref%vec_product2d(1, disp, 2, f1)
     406         [ #  # ]:           0 :         fslc(:)= fslc+2.0*beta*f1(:)
     407         [ #  # ]:           0 :         eterm = eterm + beta*dot_product(f1, disp)
     408         [ #  # ]:           0 :         if(present(energy_table)) then
     409         [ #  # ]:           0 :           label=trim(self%label)//'_Niuv'
     410                 :           0 :           call energy_table%put(label, eterm)
     411                 :             :         endif
     412                 :           0 :         eslc = eslc + eterm
     413                 :             :       endif
     414         [ +  - ]:        8008 :       if(self%has_quadlin) then
     415         [ +  + ]:    25953928 :         f1(:) = 0.0d0
     416                 :             :         eterm = 0.0d0
     417                 :        8008 :         call self%oiju_sc%vec_product(1, sp, 2, sp, 3, f1)
     418         [ +  + ]:    25953928 :         fslc(:) = fslc(:) + beta*f1(:)
     419         [ +  + ]:    25953928 :         eterm = - beta*dot_product(f1, disp)
     420                 :             :         ! add contributions from reference spin structure
     421         [ +  + ]:    25953928 :         fslc(:) = fslc(:) + self%ouref(:)
     422         [ +  + ]:    25953928 :         eterm = eterm - dot_product(self%ouref, disp)
     423         [ +  - ]:        8008 :         if(present(energy_table)) then
     424         [ +  - ]:        8008 :           label=trim(self%label)//'_Oiju'
     425                 :        8008 :           call energy_table%put(label, eterm)
     426                 :             :         endif
     427                 :        8008 :         eslc = eslc + eterm
     428                 :             :       endif
     429         [ +  + ]:        8008 :       if(self%has_biquad) then
     430         [ +  + ]:    12976964 :         f1(:) = 0.0d0
     431                 :             :         eterm = 0.0d0
     432                 :        4004 :         call self%tijuv_sc%vec_product4d(sp, sp, 3, disp, 4, f1)
     433         [ +  + ]:    12976964 :         fslc(:) = fslc(:) + beta*f1(:)
     434         [ +  + ]:    12976964 :         eterm = - 0.5_dp*beta*dot_product(f1, disp)
     435                 :             :         ! add contributions from reference spin structure
     436         [ +  + ]:    12976964 :         f1(:) = 0.0d0
     437                 :        4004 :         call self%tuvref%vec_product2d(1, disp, 2, f1)
     438         [ +  + ]:    12976964 :         fslc(:)= fslc+2.0*beta*f1(:)
     439         [ +  + ]:    12976964 :         eterm = eterm + beta*dot_product(f1, disp)
     440         [ +  - ]:        4004 :         if(present(energy_table)) then
     441         [ +  - ]:        4004 :           label=trim(self%label)//'_Tijuv'
     442                 :        4004 :           call energy_table%put(label, eterm)
     443                 :             :         endif
     444                 :        4004 :         eslc = eslc + eterm
     445                 :             :       endif
     446                 :             :     endif !energy or force
     447                 :             : 
     448         [ +  + ]:        8008 :     if(present(force)) then
     449   [ +  +  +  -  :    17309292 :       force(:,:) = force(:,:) + reshape(fslc, (/3, self%natom /))
             +  +  +  + ]
     450                 :             :       !TESTING write forces to file
     451                 :             :       !write(200,*) 'Forces are'
     452                 :             :       !do ii = 1, self%natom
     453                 :             :       !  write(200,*) ii, force(:,ii)
     454                 :             :       !enddo
     455                 :             :     endif
     456                 :             : 
     457         [ +  - ]:        8008 :     if(present(energy)) energy =  energy + eslc
     458                 :             : 
     459                 :             : 
     460                 :        8008 :     ABI_UNUSED_A(strain)
     461                 :        8008 :     ABI_UNUSED_A(lwf)
     462                 :        8008 :     ABI_UNUSED_A(stress)
     463                 :        8008 :     ABI_UNUSED_A(lwf_force)
     464                 :             : 
     465                 :        8008 :   end subroutine calculate
     466                 :             : 
     467                 :             :   !!***
     468   [ +  +  -  +  :           6 : end module m_slc_potential
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  -  
                      + ]
        

Generated by: LCOV version 2.3-1