LCOV - code coverage report
Current view: top level - src/78_effpot - m_spin_primitive_potential.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 52.7 % 429 226
Test Date: 2026-11-09 22:30:52 Functions: 75.0 % 16 12
Branches: 26.7 % 804 215

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_spin_primitive_potential
       2                 :             : !! NAME
       3                 :             : !! m_spin_primitive_potential
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module contains the atomic structures and the spin hamiltonian inside the primitive cell
       7                 :             : !! which can be directly mapped to the xml file. It is not for the calculation, but for constructing
       8                 :             : !! the hamiltonian in supercell. It is also used as input for the magnon band structure calculation.
       9                 :             : !!
      10                 :             : !! Datatypes:
      11                 :             : !!  spin_primitive_potential_t
      12                 :             : !!
      13                 :             : !! Subroutines:
      14                 :             : !!
      15                 :             : !! COPYRIGHT
      16                 :             : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      17                 :             : !! This file is distributed under the terms of the
      18                 :             : !! GNU General Public License, see ~abinit/COPYING
      19                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      20                 :             : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      21                 :             : !!
      22                 :             : !! SOURCE
      23                 :             : 
      24                 :             : 
      25                 :             : #if defined HAVE_CONFIG_H
      26                 :             : #include "config.h"
      27                 :             : #endif
      28                 :             : #include "abi_common.h"
      29                 :             : 
      30                 :             : module m_spin_primitive_potential
      31                 :             :   use, intrinsic :: iso_c_binding
      32                 :             :   use m_dynamic_array, only: int_array_type, real_array_type, int2d_array_type
      33                 :             :   use m_mathfuncs
      34                 :             :   use defs_basis
      35                 :             :   use m_abicore
      36                 :             :   use m_errors
      37                 :             :   use m_xmpi
      38                 :             :   use m_nctk
      39                 :             : #if defined HAVE_NETCDF
      40                 :             :   use netcdf
      41                 :             : #endif
      42                 :             : 
      43                 :             :   use m_mpi_scheduler, only: init_mpi_info
      44                 :             :   use m_multibinit_dataset, only: multibinit_dtset_type
      45                 :             :   use m_multibinit_io_xml, only: xml_read_spin, xml_free_spin
      46                 :             :   use m_multibinit_cell, only: mbcell_t, mbsupercell_t
      47                 :             :   use m_primitive_potential, only: primitive_potential_t
      48                 :             :   use m_abstract_potential, only: abstract_potential_t
      49                 :             :   use m_dynamic_array, only: int2d_array_type
      50                 :             :   use m_supercell_maker, only: supercell_maker_t
      51                 :             :   use m_spmat_ndcoo, only: ndcoo_mat_t
      52                 :             :   use m_spin_potential, only: spin_potential_t
      53                 :             : 
      54                 :             :   implicit none
      55                 :             :   private
      56                 :             :   !!***
      57                 :             : 
      58                 :             : 
      59                 :             :   type, public, extends(primitive_potential_t) :: spin_primitive_potential_t
      60                 :             :      integer :: natoms
      61                 :             :      integer ::  nspin    ! on every mpi node
      62                 :             :      type(ndcoo_mat_t) :: coeff  ! only on master node
      63                 :             :      type(int2d_array_type) :: Rlist !only on master node
      64                 :             : 
      65                 :             :      ! Here the coeff is a NOCOO matrix, which has the indices and values.
      66                 :             :      ! The indices is a 2d integer matrix.
      67                 :             :      ! |     indices    | value|
      68                 :             :      ! |  i1 | j1| indR1| val1 |
      69                 :             :      ! |  i2 | j2| indR2| val2 |
      70                 :             :      !
      71                 :             :      ! and the Rlist is a list of R values.
      72                 :             :      ! for  the k'th element ik, jk, indRk, valk, the R value is Rlist(indRk).
      73                 :             :    contains
      74                 :             :      procedure:: initialize
      75                 :             :      procedure:: finalize
      76                 :             :      procedure :: set_spin_primcell   ! set primitve cell infor (rprimd, xcart, ...)
      77                 :             :      procedure :: set_bilinear_1term  ! set one (i,j,R) val(3,3)
      78                 :             :      procedure:: set_bilinear         ! set list of bilinear terms (ilist, jlist, Rlist, valllist)
      79                 :             :      procedure:: set_exchange         ! set list of exchange terms
      80                 :             :      procedure:: set_dmi              ! set list of dmi terms
      81                 :             :      procedure:: set_sia             ! set list of sia terms
      82                 :             :      procedure :: add_input_sia       ! add a SIA term from input file
      83                 :             :      procedure :: load_from_files    ! read potential from files
      84                 :             :      procedure:: read_xml            ! read potential from one xml file
      85                 :             :      procedure :: read_netcdf        ! read potential from one netcdf file
      86                 :             :      procedure:: fill_supercell      ! fill supercell.
      87                 :             :   end type spin_primitive_potential_t
      88                 :             : 
      89                 :             : contains
      90                 :             : 
      91                 :           2 :   subroutine initialize(self, primcell)
      92                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
      93                 :             :     type(mbcell_t), target, intent(inout) :: primcell
      94                 :             :     !integer, intent(in) :: nspin
      95                 :           2 :     self%primcell=>primcell
      96                 :           2 :     self%label="Spin_primitive_potential"
      97                 :           2 :     self%has_spin=.True.
      98                 :           2 :     self%has_displacement=.False.
      99                 :           2 :     self%has_strain=.False.
     100                 :           2 :     self%has_lwf=.False.
     101                 :           2 :   end subroutine initialize
     102                 :             : 
     103                 :             : 
     104                 :           2 :   subroutine finalize(self)
     105                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     106                 :           2 :     call self%coeff%finalize()
     107                 :           2 :     call self%Rlist%finalize()
     108                 :           2 :     nullify(self%primcell)
     109                 :           2 :     self%nspin=0
     110                 :           2 :     self%natoms=0
     111                 :           2 :     self%label="Destroyed Spin_primitive_potential"
     112                 :           2 :     call self%primitive_potential_t%finalize()
     113                 :           2 :   end subroutine finalize
     114                 :             : 
     115                 :             : 
     116                 :           4 :   subroutine set_spin_primcell(self, natoms, unitcell, positions, &
     117         [ -  + ]:           2 :        & nspin, index_spin, spinat, gyroratios, damping_factors, &
     118                 :             :        & Sref, ref_spin_qpoint, ref_spin_rotate_axis)
     119                 :             : 
     120                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     121                 :             :     integer,                           intent(inout) :: natoms, nspin, index_spin(:)
     122                 :             :     real(dp),                          intent(inout) :: unitcell(3, 3),  positions(3,natoms)
     123                 :             :     real(dp),                          intent(inout) :: spinat(3, natoms), gyroratios(nspin), damping_factors(nspin)
     124                 :             :     real(dp),                optional, intent(inout) :: Sref(3, nspin), ref_spin_qpoint(3), ref_spin_rotate_axis(3)
     125                 :             : 
     126                 :             :     integer :: iatom, ispin
     127                 :           4 :     real(dp) :: ms(nspin), spin_positions(3, nspin)
     128                 :             :     integer :: master, my_rank, comm, nproc, ierr
     129                 :             :     logical :: iam_master
     130                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     131                 :             : 
     132                 :           2 :     ABI_UNUSED_A(unitcell)
     133                 :             : 
     134                 :           2 :     self%nspin=nspin
     135                 :           2 :     call xmpi_bcast(self%nspin, master, comm, ierr)
     136         [ +  - ]:           2 :     if (iam_master) then
     137         [ +  + ]:           8 :        call self%coeff%initialize(mshape=[-1, self%nspin*3, self%nspin*3])
     138         [ +  + ]:          12 :        do iatom=1, natoms
     139                 :          10 :           ispin=index_spin(iatom)
     140         [ +  + ]:          12 :           if(ispin>0) then
     141         [ +  + ]:           8 :              spin_positions(:,ispin)= positions(:, iatom)
     142         [ +  + ]:           8 :              ms(ispin) = sqrt(sum(spinat(:,iatom)**2, dim=1))* mu_B
     143                 :             :           end if
     144                 :             :        end do
     145                 :             :     endif
     146                 :             :     call self%primcell%set_spin(nspin, ms, unitcell,  spin_positions, gyroratios, damping_factors, &
     147                 :           2 :          & Sref=Sref, ref_qpoint=ref_spin_qpoint, ref_rotate_axis=ref_spin_rotate_axis)
     148                 :             : 
     149                 :             :     !call self%primcell%set_lattice(natom=natoms, cell=unitcell, xcart=spin_positions, masses, zion)
     150                 :           2 :   end subroutine set_spin_primcell
     151                 :             : 
     152                 :             : 
     153                 :           2 :   subroutine load_from_files(self, params, fnames)
     154                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     155                 :             :     type(multibinit_dtset_type), intent(in) :: params
     156                 :             :     character(len=fnlen), intent(in) :: fnames(:)
     157                 :             :     character(len=fnlen)  :: fname
     158                 :             :     character(len=500) :: message
     159                 :             :     integer :: ii
     160                 :             :     logical:: use_sia, use_exchange, use_dmi, use_bi
     161                 :           2 :     fname=params%spin_pot_fname
     162                 :             :     ABI_UNUSED(fnames)
     163         [ +  - ]:           2 :     if (xmpi_comm_rank(xmpi_world)==0) then
     164         [ +  + ]:         164 :        write(message,'(a,(80a),3a)') ch10,('=',ii=1,80),ch10,ch10,&
     165         [ +  - ]:         166 :             &     'reading spin terms.'
     166                 :           2 :        call wrtout(ab_out,message,'COLL')
     167                 :           2 :        call wrtout(std_out,message,'COLL')
     168                 :             :     endif
     169                 :           2 :     use_exchange=.True.
     170                 :           2 :     use_sia=.True.
     171                 :           2 :     use_dmi=.True.
     172                 :           2 :     use_bi=.True.
     173                 :             :     ! Do not use sia term in xml if spin_sia_add is set to 1.
     174         [ -  + ]:           2 :     if(params%spin_sia_add == 1) use_sia=.False.
     175                 :             : 
     176         [ -  + ]:           2 :     if(endswith(trim(fname), ".xml")) then
     177                 :             :        call self%read_xml( trim(fname)//char(0), &
     178         [ #  # ]:           0 :             & use_exchange=use_exchange,  use_sia=use_sia, use_dmi=use_dmi, use_bi=use_bi)
     179         [ +  - ]:           2 :     else if(endswith(trim(fname), ".nc")) then
     180                 :           2 :        call self%read_netcdf(fname)
     181                 :             :     endif
     182         [ -  + ]:           2 :     if (params%spin_sia_add /= 0 ) then
     183                 :             :        call self%add_input_sia(params%spin_sia_k1amp, &
     184                 :           0 :             & params%spin_sia_k1dir)
     185                 :             :     end if
     186                 :           2 :   end subroutine load_from_files
     187                 :             : 
     188                 :             : 
     189                 :             :   !-------------------------------------------------------------------!
     190                 :             :   ! load_from_netcdf
     191                 :             :   ! Load spin primitive potential from a netcdf file.
     192                 :             :   !-------------------------------------------------------------------!
     193                 :           2 :   subroutine read_netcdf(self, fname)
     194                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     195                 :             :     character(len=fnlen), intent(in) :: fname
     196                 :             :     integer :: ierr, ncid, varid
     197                 :             : 
     198                 :             :     integer :: nspin, natom
     199                 :             :     real(dp) :: cell(3,3)
     200                 :             :     real(dp) :: ref_spin_qpoint(3), ref_spin_rotate_axis(3)
     201                 :           2 :     real(dp), allocatable :: ref_spin_orientation(:, :)
     202                 :           2 :     integer, allocatable :: index_spin(:)
     203                 :           2 :     real(dp), allocatable :: spinat(:,:)
     204                 :           2 :     real(dp), allocatable :: xcart(:,:)
     205                 :           2 :     real(dp), allocatable :: gyroratio(:)
     206                 :           2 :     real(dp), allocatable :: gilbert_damping(:)
     207                 :             : 
     208                 :             :     integer :: spin_exchange_nterm
     209                 :           2 :     integer , allocatable:: spin_exchange_ilist(:)
     210                 :           2 :     integer , allocatable:: spin_exchange_jlist(:)
     211                 :           2 :     integer , allocatable:: spin_exchange_Rlist(:,:)
     212                 :           2 :     real(dp), allocatable:: spin_exchange_vallist(:,:)
     213                 :             : 
     214                 :             :     integer :: spin_dmi_nterm
     215                 :           2 :     integer , allocatable:: spin_dmi_ilist(:)
     216                 :           2 :     integer , allocatable:: spin_dmi_jlist(:)
     217                 :           2 :     integer , allocatable:: spin_dmi_Rlist(:,:)
     218                 :           2 :     real(dp), allocatable:: spin_dmi_vallist(:,:)
     219                 :             : 
     220                 :             : 
     221                 :             :     integer :: spin_SIA_nterm
     222                 :           2 :     integer , allocatable:: spin_SIA_ilist(:)
     223                 :           2 :     real(dp), allocatable:: spin_SIA_k1list(:)
     224                 :           2 :     real(dp), allocatable:: spin_SIA_k1dirlist(:,:)
     225                 :             : 
     226                 :             : 
     227                 :             :     integer :: spin_bilinear_nterm
     228                 :           2 :     integer , allocatable:: spin_bilinear_ilist(:)
     229                 :           2 :     integer , allocatable:: spin_bilinear_jlist(:)
     230                 :           2 :     integer , allocatable:: spin_bilinear_Rlist(:,:)
     231                 :           2 :     real(dp), allocatable:: spin_bilinear_vallist(:,:,:)
     232                 :             : 
     233                 :             : #if defined HAVE_NETCDF
     234                 :             : 
     235                 :             :     ! open netcdf file
     236                 :           2 :     ierr=nf90_open(trim(fname)//char(0), NF90_NOWRITE, ncid)
     237         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "open netcdf file")
     238                 :             : 
     239                 :             :     ! read primcell info
     240                 :           2 :     ierr=nctk_get_dim(ncid, "natom", natom)
     241         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "getting natom in spin potential file")
     242                 :           2 :     ierr=nctk_get_dim(ncid, "nspin", nspin)
     243         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "getting nspin in spin potential file")
     244                 :             : 
     245                 :             :     ! allocate for primcell
     246   [ -  +  +  -  :           6 :     ABI_MALLOC(xcart, (3, natom))
          +  -  +  -  -  
                +  -  + ]
     247   [ -  +  +  -  :           4 :     ABI_MALLOC(spinat, (3, natom))
             -  +  -  + ]
     248   [ -  +  +  -  :           6 :     ABI_MALLOC(index_spin, (natom))
          +  -  +  -  -  
                +  -  + ]
     249   [ -  +  +  -  :           6 :     ABI_MALLOC(gyroratio, (nspin))
          +  -  +  -  -  
                +  -  + ]
     250   [ -  +  +  -  :           4 :     ABI_MALLOC(gilbert_damping, (nspin))
             -  +  -  + ]
     251   [ -  +  +  -  :           6 :     ABI_MALLOC(ref_spin_orientation, (3, nspin))
          +  -  +  -  -  
                +  -  + ]
     252                 :             : 
     253                 :           2 :     ierr =nf90_inq_varid(ncid, "ref_cell", varid)
     254         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "ref_cell")
     255                 :           2 :     ierr = nf90_get_var(ncid, varid, cell)
     256         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "ref_cell")
     257   [ +  +  +  + ]:          26 :     cell(:,:)=cell(:,:)/ Bohr_Ang
     258                 :             : 
     259                 :           2 :     ierr =nf90_inq_varid(ncid, "ref_xcart", varid)
     260         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "ref_xcart")
     261                 :           2 :     ierr = nf90_get_var(ncid, varid, xcart)
     262         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "ref_xcart")
     263                 :             : 
     264   [ +  +  +  + ]:          42 :     xcart(:,:)=xcart(:,:)/ Bohr_Ang
     265                 :             : 
     266                 :           2 :     ierr =nf90_inq_varid(ncid, "spin_ref_orientation", varid)
     267         [ -  + ]:           2 :     if(ierr==NF90_NOERR) then
     268                 :           0 :       ierr = nf90_get_var(ncid, varid, ref_spin_orientation)
     269         [ #  # ]:           0 :       NCF_CHECK_MSG(ierr, "spin_ref_orientation")
     270                 :             :     else
     271                 :           2 :       ABI_WARNING("Could not read spin_ref_orientation from nc file, will use z-direction.")
     272         [ +  + ]:           4 :       ref_spin_orientation(1,:)=0.0d0
     273         [ +  + ]:           4 :       ref_spin_orientation(2,:)=0.0d0
     274         [ +  + ]:           4 :       ref_spin_orientation(3,:)=1.0d0
     275                 :             :     endif
     276                 :             : 
     277                 :             :     !NCF_CHECK_MSG(ierr, "spin_ref_orientation")
     278                 :             :     !ierr = nf90_get_var(ncid, varid, ref_spin_orientation)
     279                 :             :     !NCF_CHECK_MSG(ierr, "spin_ref_orientation")
     280                 :             : 
     281                 :           2 :     ierr =nf90_inq_varid(ncid, "spin_ref_qpoint", varid)
     282         [ +  - ]:           2 :     if(ierr==NF90_NOERR) then
     283                 :           2 :       ierr = nf90_get_var(ncid, varid, ref_spin_qpoint)
     284         [ -  + ]:           2 :       NCF_CHECK_MSG(ierr, "spin_ref_qpoint")
     285                 :             :     else
     286                 :           0 :       ABI_WARNING("Could not read spin_ref_qpoint from nc file, will use Gamma point.")
     287                 :           0 :       ref_spin_qpoint(:)=0.0d0
     288                 :             :     endif
     289                 :             :     !NCF_CHECK_MSG(ierr, "spin_ref_qpoint")
     290                 :             :     !ierr = nf90_get_var(ncid, varid, ref_spin_qpoint)
     291                 :             :     !NCF_CHECK_MSG(ierr, "spin_ref_qpoint")
     292                 :             : 
     293                 :           2 :     ierr =nf90_inq_varid(ncid, "spin_ref_rotate_axis", varid)
     294         [ +  - ]:           2 :     if(ierr==NF90_NOERR) then
     295                 :           2 :       ierr = nf90_get_var(ncid, varid, ref_spin_rotate_axis)
     296         [ -  + ]:           2 :       NCF_CHECK_MSG(ierr, "spin_ref_rotate_axis")
     297                 :             :     else
     298                 :           0 :       ABI_WARNING("Could not read spin_ref_rotate_axis from nc file, will use x-axis.")
     299                 :           0 :       ref_spin_rotate_axis(1)=1.0d0
     300                 :           0 :       ref_spin_rotate_axis(2)=0.0d0
     301                 :           0 :       ref_spin_rotate_axis(3)=0.0d0
     302                 :             :     endif
     303                 :             : 
     304                 :             :     !NCF_CHECK_MSG(ierr, "spin_ref_rotate_axis")
     305                 :             :     !ierr = nf90_get_var(ncid, varid, ref_spin_rotate_axis)
     306                 :             :     !NCF_CHECK_MSG(ierr, "spin_ref_rotate_axis")
     307                 :             : 
     308                 :           2 :     ierr =nf90_inq_varid(ncid, "spinat", varid)
     309         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "spinat")
     310                 :           2 :     ierr = nf90_get_var(ncid, varid, spinat)
     311         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "spinat")
     312                 :             : 
     313                 :           2 :     ierr =nf90_inq_varid(ncid, "index_spin", varid)
     314         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "index_spin")
     315                 :           2 :     ierr = nf90_get_var(ncid, varid, index_spin)
     316         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "index_spin")
     317                 :             : 
     318                 :           2 :     ierr =nf90_inq_varid(ncid, "gyroratio", varid)
     319         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "gyroratio")
     320                 :           2 :     ierr = nf90_get_var(ncid, varid, gyroratio)
     321         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "gyroratio")
     322                 :             : 
     323                 :           2 :     ierr =nf90_inq_varid(ncid, "gilbert_damping", varid)
     324         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "gilbert_damping")
     325                 :           2 :     ierr = nf90_get_var(ncid, varid, gilbert_damping)
     326         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "gilbert_damping")
     327                 :             : 
     328                 :             :     call self%set_spin_primcell( natoms=natom, unitcell=cell, positions=xcart, &
     329                 :             :          & nspin=nspin, index_spin=index_spin, spinat=spinat, &
     330                 :             :          & gyroratios=gyroratio, damping_factors=gilbert_damping, &
     331                 :           2 :          & Sref=ref_spin_orientation, ref_spin_qpoint=ref_spin_qpoint, ref_spin_rotate_axis=ref_spin_rotate_axis)
     332                 :             : 
     333         [ +  - ]:           2 :     ABI_SFREE(xcart)
     334         [ +  - ]:           2 :     ABI_SFREE(spinat)
     335         [ +  - ]:           2 :     ABI_SFREE(index_spin)
     336         [ +  - ]:           2 :     ABI_SFREE(gyroratio)
     337         [ +  - ]:           2 :     ABI_SFREE(gilbert_damping)
     338         [ +  - ]:           2 :     ABI_SFREE(ref_spin_orientation)
     339                 :             : 
     340                 :             :     !== read exchange terms
     341                 :           2 :     ierr=nf90_inq_dimid(ncid, "spin_exchange_nterm", spin_exchange_nterm)
     342         [ +  - ]:           2 :     if (ierr==0) then ! if has exchange
     343                 :           2 :        ierr=nctk_get_dim(ncid, "spin_exchange_nterm", spin_exchange_nterm)
     344   [ -  +  +  -  :           6 :        ABI_MALLOC(spin_exchange_ilist, (spin_exchange_nterm))
          +  -  +  -  -  
                +  -  + ]
     345   [ -  +  +  -  :           4 :        ABI_MALLOC(spin_exchange_jlist, (spin_exchange_nterm))
             -  +  -  + ]
     346   [ -  +  +  -  :           6 :        ABI_MALLOC(spin_exchange_Rlist, (3,spin_exchange_nterm))
          +  -  +  -  -  
                +  -  + ]
     347   [ -  +  +  -  :           6 :        ABI_MALLOC(spin_exchange_vallist, (3,spin_exchange_nterm))
          +  -  +  -  -  
                +  -  + ]
     348                 :             : 
     349                 :           2 :        ierr =nf90_inq_varid(ncid, "spin_exchange_ilist", varid)
     350         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_ilist")
     351                 :           2 :        ierr = nf90_get_var(ncid, varid, spin_exchange_ilist)
     352         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_ilist")
     353                 :             : 
     354                 :           2 :        ierr =nf90_inq_varid(ncid, "spin_exchange_jlist", varid)
     355         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_jlist")
     356                 :           2 :        ierr = nf90_get_var(ncid, varid, spin_exchange_jlist)
     357         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_jlist")
     358                 :             : 
     359                 :           2 :        ierr =nf90_inq_varid(ncid, "spin_exchange_Rlist", varid)
     360         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_Rlist")
     361                 :           2 :        ierr = nf90_get_var(ncid, varid, spin_exchange_Rlist)
     362         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_Rlist")
     363                 :             : 
     364                 :             : 
     365                 :           2 :        ierr =nf90_inq_varid(ncid, "spin_exchange_vallist", varid)
     366         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_vallist")
     367                 :           2 :        ierr = nf90_get_var(ncid, varid, spin_exchange_vallist)
     368         [ -  + ]:           2 :        NCF_CHECK_MSG(ierr, "spin_exchange_vallist")
     369                 :             : 
     370   [ +  +  +  + ]:         210 :        spin_exchange_vallist(:,:) = spin_exchange_vallist(:,:) * eV_Ha
     371                 :             : 
     372                 :             :        call self%set_exchange(n=spin_exchange_nterm, ilist=spin_exchange_ilist, &
     373                 :             :             & jlist=spin_exchange_jlist, Rlist=spin_exchange_Rlist, &
     374                 :           2 :             & vallist=spin_exchange_vallist)
     375                 :             : 
     376         [ +  - ]:           2 :        ABI_SFREE(spin_exchange_ilist)
     377         [ +  - ]:           2 :        ABI_SFREE(spin_exchange_jlist)
     378         [ +  - ]:           2 :        ABI_SFREE(spin_exchange_Rlist)
     379         [ +  - ]:           2 :        ABI_SFREE(spin_exchange_vallist)
     380                 :             :     endif
     381                 :             : 
     382                 :             : 
     383                 :             : 
     384                 :             :     !== read dmi terms
     385                 :           2 :     ierr=nf90_inq_dimid(ncid, "spin_dmi_nterm", spin_dmi_nterm)
     386         [ -  + ]:           2 :     if (ierr==0) then ! if has dmi
     387                 :           0 :        ierr=nctk_get_dim(ncid, "spin_dmi_nterm", spin_dmi_nterm)
     388         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_nterm found but is not readable")
     389   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_dmi_ilist, (spin_dmi_nterm))
          #  #  #  #  #  
                #  #  # ]
     390   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_dmi_jlist, (spin_dmi_nterm))
             #  #  #  # ]
     391   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_dmi_Rlist, (3,spin_dmi_nterm))
          #  #  #  #  #  
                #  #  # ]
     392   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_dmi_vallist, (3,spin_dmi_nterm))
          #  #  #  #  #  
                #  #  # ]
     393                 :             : 
     394                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_dmi_ilist", varid)
     395         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_ilist")
     396                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_dmi_ilist)
     397         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_ilist")
     398                 :             : 
     399                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_dmi_jlist", varid)
     400         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_jlist")
     401                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_dmi_jlist)
     402         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_jlist")
     403                 :             : 
     404                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_dmi_Rlist", varid)
     405         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_Rlist")
     406                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_dmi_Rlist)
     407         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_Rlist")
     408                 :             : 
     409                 :             : 
     410                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_dmi_vallist", varid)
     411         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_vallist")
     412                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_dmi_vallist)
     413         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_dmi_vallist")
     414                 :             : 
     415   [ #  #  #  # ]:           0 :        spin_dmi_vallist(:,:) = spin_dmi_vallist(:,:) * eV_Ha
     416                 :             : 
     417                 :             :        call self%set_dmi(n=spin_dmi_nterm, ilist=spin_dmi_ilist, &
     418                 :             :             & jlist=spin_dmi_jlist, Rlist=spin_dmi_Rlist, &
     419                 :           0 :             & vallist=spin_dmi_vallist)
     420                 :             : 
     421         [ #  # ]:           0 :        ABI_SFREE(spin_dmi_ilist)
     422         [ #  # ]:           0 :        ABI_SFREE(spin_dmi_jlist)
     423         [ #  # ]:           0 :        ABI_SFREE(spin_dmi_Rlist)
     424         [ #  # ]:           0 :        ABI_SFREE(spin_dmi_vallist)
     425                 :             :     endif
     426                 :             : 
     427                 :             :     !== read SIA terms
     428                 :           2 :     ierr=nf90_inq_dimid(ncid, "spin_SIA_nterm", spin_SIA_nterm)
     429         [ -  + ]:           2 :     if (ierr==0) then ! if has SIA
     430                 :           0 :        ierr=nctk_get_dim(ncid, "spin_SIA_nterm", spin_SIA_nterm)
     431   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_SIA_ilist, (spin_SIA_nterm))
          #  #  #  #  #  
                #  #  # ]
     432   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_SIA_k1list, (spin_SIA_nterm))
          #  #  #  #  #  
                #  #  # ]
     433   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_SIA_k1dirlist, (3,spin_SIA_nterm))
          #  #  #  #  #  
                #  #  # ]
     434                 :             : 
     435                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_SIA_ilist", varid)
     436         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_SIA_ilist")
     437                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_SIA_ilist)
     438         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_SIA_ilist")
     439                 :             : 
     440                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_SIA_k1list", varid)
     441         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_SIA_k1list")
     442                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_SIA_k1list)
     443         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_SIA_k1list")
     444                 :             : 
     445                 :             : 
     446                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_SIA_k1dirlist", varid)
     447         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_SIA_k1dirlist")
     448                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_SIA_k1dirlist)
     449         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_SIA_k1dirlist")
     450                 :             : 
     451         [ #  # ]:           0 :        spin_SIA_k1list(:) = spin_SIA_k1list(:) * eV_Ha
     452                 :             : 
     453                 :             :        call self%set_SIA(n=spin_SIA_nterm, ilist=spin_SIA_ilist, &
     454                 :           0 :             & k1list=spin_SIA_k1list, k1dirlist=spin_SIA_k1dirlist)
     455                 :             : 
     456         [ #  # ]:           0 :        ABI_SFREE(spin_SIA_ilist)
     457         [ #  # ]:           0 :        ABI_SFREE(spin_SIA_k1list)
     458         [ #  # ]:           0 :        ABI_SFREE(spin_SIA_k1dirlist)
     459                 :             :     endif
     460                 :             : 
     461                 :             : 
     462                 :             : 
     463                 :             :     ! read bilinear terms
     464                 :           2 :     ierr=nf90_inq_dimid(ncid, "spin_bilinear_nterm", varid)
     465         [ -  + ]:           2 :     if (ierr==0) then  ! if has bilinear
     466   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_bilinear_ilist, (spin_bilinear_nterm))
          #  #  #  #  #  
                #  #  # ]
     467   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_bilinear_jlist, (spin_bilinear_nterm))
             #  #  #  # ]
     468   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_bilinear_Rlist, (3,spin_bilinear_nterm))
          #  #  #  #  #  
                #  #  # ]
     469   [ #  #  #  #  :           0 :        ABI_MALLOC(spin_bilinear_vallist, (3,3,spin_bilinear_nterm))
          #  #  #  #  #  
                #  #  # ]
     470                 :             : 
     471                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_bilinear_ilist", varid)
     472         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_ilist")
     473                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_bilinear_ilist)
     474         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_ilist")
     475                 :             : 
     476                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_bilinear_jlist", varid)
     477         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_jlist")
     478                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_bilinear_jlist)
     479         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_jlist")
     480                 :             : 
     481                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_bilinear_Rlist", varid)
     482         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_Rlist")
     483                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_bilinear_Rlist)
     484         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_Rlist")
     485                 :             : 
     486                 :           0 :        ierr =nf90_inq_varid(ncid, "spin_bilinear_vallist", varid)
     487         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_vallist")
     488                 :           0 :        ierr = nf90_get_var(ncid, varid, spin_bilinear_vallist)
     489         [ #  # ]:           0 :        NCF_CHECK_MSG(ierr, "spin_bilinear_vallist")
     490                 :             : 
     491   [ #  #  #  #  :           0 :        spin_bilinear_vallist(:,:,:) = spin_bilinear_vallist(:,:,:) * eV_Ha
                   #  # ]
     492                 :             : 
     493                 :             :        call self%set_bilinear( n=spin_bilinear_nterm, ilist=spin_bilinear_ilist, &
     494                 :             :             & jlist=spin_bilinear_jlist, Rlist=spin_bilinear_Rlist, &
     495                 :           0 :             & vallist=spin_bilinear_vallist)
     496                 :             : 
     497         [ #  # ]:           0 :        ABI_SFREE(spin_bilinear_ilist)
     498         [ #  # ]:           0 :        ABI_SFREE(spin_bilinear_jlist)
     499         [ #  # ]:           0 :        ABI_SFREE(spin_bilinear_Rlist)
     500         [ #  # ]:           0 :        ABI_SFREE(spin_bilinear_vallist)
     501                 :             :     end if
     502                 :             : 
     503                 :           2 :     ierr=nf90_close(ncid)
     504         [ -  + ]:           2 :     NCF_CHECK_MSG(ierr, "Close netcdf file")
     505                 :             : #else
     506                 :             :     NETCDF_NOTENABLED_ERROR()
     507                 :             : #endif
     508   [ -  +  -  +  :           2 :   end subroutine read_netcdf
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                +  -  + ]
     509                 :             : 
     510                 :             : 
     511                 :             :   !-------------------------------------------------------------------!
     512                 :             :   ! set_bilinear_1term:
     513                 :             :   !   Add a bilinear term
     514                 :             :   ! Inputs:
     515                 :             :   ! i: index of spin i
     516                 :             :   ! j: index of spin j
     517                 :             :   ! R: cell vector R (vector3)
     518                 :             :   ! val : a 3*3 matrix.
     519                 :             :   !-------------------------------------------------------------------!
     520                 :          52 :   subroutine set_bilinear_1term(self, i, j, R, val)
     521                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     522                 :             :     integer, intent(in) :: i, j, R(3)
     523                 :             :     real(dp), intent(in) :: val(3,3)
     524                 :             :     real(dp) :: v
     525                 :             :     integer :: indR, iv, jv
     526                 :             : 
     527         [ +  - ]:          52 :     if (xmpi_comm_rank(xmpi_world)==0) then
     528                 :          52 :        call self%Rlist%push_unique(R, position=indR)
     529         [ +  + ]:         208 :        do jv=1,3
     530         [ +  + ]:         676 :           do iv=1,3
     531                 :         468 :              v=val(iv,jv)
     532         [ +  + ]:        2028 :              call self%coeff%add_entry(ind=[indR, (i-1)*3+iv, (j-1)*3+jv ], val=v)
     533                 :             :           end do
     534                 :             :        end do
     535                 :             :     endif
     536                 :          52 :   end subroutine set_bilinear_1term
     537                 :             : 
     538                 :             :   !-------------------------------------------------------------------!
     539                 :             :   ! set_bilinear:
     540                 :             :   !Inputs:
     541                 :             :   ! n: number of terms
     542                 :             :   ! ilist: list of i (length n)
     543                 :             :   ! jlist: list of j (length n)
     544                 :             :   ! Rlist: list of R mat(3,  n)
     545                 :             :   ! vallist: list of val . mat(3,3,n)
     546                 :             :   !-------------------------------------------------------------------!
     547                 :           2 :   subroutine  set_bilinear(self, n, ilist, jlist, Rlist, vallist)
     548                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     549                 :             :     integer, intent(in) :: n, ilist(n), jlist(n), Rlist(3,n)
     550                 :             :     real(dp), intent(in) :: vallist(3, 3,n)
     551                 :             :     integer :: idx
     552         [ +  - ]:           2 :     if (xmpi_comm_rank(xmpi_world)==0) then
     553         [ +  + ]:          54 :        do idx = 1, n
     554                 :          54 :           call self%set_bilinear_1term(ilist(idx), jlist(idx), Rlist(:,idx), vallist(:,:, idx))
     555                 :             :        end do
     556                 :             :     endif
     557                 :           2 :   end subroutine set_bilinear
     558                 :             : 
     559                 :             :   !-------------------------------------------------------------------!
     560                 :             :   ! set_exchange terms.
     561                 :             :   !  same as set_bilinear, except the vallist only have the diagonal.
     562                 :             :   !-------------------------------------------------------------------!
     563   [ -  +  -  +  :           2 :   subroutine set_exchange(self, n, ilist, jlist, Rlist, vallist)
             -  +  -  + ]
     564                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     565                 :             :     integer, intent(in) :: n, ilist(:), jlist(:), Rlist(:,:)
     566                 :             :     real(dp), intent(in) :: vallist(:,:)
     567                 :             :     integer :: idx
     568                 :           4 :     real(dp) :: bivallist(3,3, n)
     569                 :             : 
     570         [ +  - ]:           2 :     if (xmpi_comm_rank(xmpi_world)==0) then
     571   [ +  +  +  +  :         678 :        bivallist(:,:,:)=0.0d0
                   +  + ]
     572         [ +  + ]:          54 :        do idx = 1, n, 1
     573                 :          52 :           bivallist(1,1,idx)=vallist(1, idx)
     574                 :          52 :           bivallist(2,2,idx)=vallist(2, idx)
     575                 :          54 :           bivallist(3,3,idx)=vallist(3, idx)
     576                 :             :        end do
     577   [ -  +  -  -  :           2 :        call self%set_bilinear(n,ilist,jlist,Rlist,bivallist)
          -  -  -  +  -  
          -  -  -  -  +  
          -  -  -  -  -  
          -  -  +  -  +  
                   -  + ]
     578                 :             :     endif
     579                 :           2 :   end subroutine set_exchange
     580                 :             : 
     581                 :             : 
     582                 :             :   !-------------------------------------------------------------------!
     583                 :             :   ! set the DMI term.
     584                 :             :   ! here vallist is a list(n) of 3-vectors.
     585                 :             :   !-------------------------------------------------------------------!
     586   [ #  #  #  #  :           0 :   subroutine set_dmi(self, n, ilist, jlist, Rlist, vallist)
             #  #  #  # ]
     587                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     588                 :             :     integer, intent(in) :: n, ilist(:), jlist(:), Rlist(:,:)
     589                 :             :     real(dp), intent(in) :: vallist(:,:)
     590                 :             :     integer :: idx
     591                 :           0 :     real(dp) :: bivallist(3,3, n), D(3)
     592                 :             : 
     593         [ #  # ]:           0 :     if (xmpi_comm_rank(xmpi_world)==0) then
     594   [ #  #  #  #  :           0 :        bivallist(:,:,:)=0.0d0
                   #  # ]
     595         [ #  # ]:           0 :        do idx=1,n, 1
     596         [ #  # ]:           0 :           D(:)=vallist(:, idx)
     597                 :             :           ! 0 Dz -Dy
     598                 :             :           ! -Dz 0 Dx
     599                 :             :           ! Dy -Dx 0
     600                 :             :           bivallist(:,:, idx)=reshape ( (/0.0d0, -D(3), D(2),  &
     601                 :             :                D(3), 0.0d0, -D(1),  &
     602         [ #  # ]:           0 :                -D(2), D(1), 0.0d0 /),(/3,3/) )
     603                 :             :        end do
     604   [ #  #  #  #  :           0 :        call self%set_bilinear(n,ilist,jlist,Rlist,bivallist)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     605                 :             :     endif
     606                 :           0 :   end subroutine set_dmi
     607                 :             : 
     608                 :             :   !-------------------------------------------------------------------!
     609                 :             :   ! set_sia:
     610                 :             :   !  set a list of single ion anisotropy
     611                 :             :   !   k1list: amplitudes  mat(n)
     612                 :             :   !   k1dirlist: directions  mat(3, n)
     613                 :             :   !-------------------------------------------------------------------!
     614   [ #  #  #  #  :           0 :   subroutine set_sia(self, n, ilist, k1list, k1dirlist)
                   #  # ]
     615                 :             : 
     616                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     617                 :             :     integer, intent(in) :: n, ilist(:)
     618                 :             :     real(dp), intent(in) :: k1list(:), k1dirlist(:, :)
     619                 :           0 :     integer :: idx, Rlist(3, n)
     620                 :           0 :     real(dp) :: bivallist(3,3, n)
     621         [ #  # ]:           0 :     if (xmpi_comm_rank(xmpi_world)==0) then
     622   [ #  #  #  #  :           0 :        bivallist(:,:,:)=0.0d0
                   #  # ]
     623   [ #  #  #  # ]:           0 :        Rlist(:, :)=0
     624         [ #  # ]:           0 :        do idx=1,n, 1
     625                 :             :           bivallist(:,:, idx)= (- k1list(idx))*  &
     626   [ #  #  #  # ]:           0 :                outer_product(k1dirlist(:,idx), k1dirlist(:, idx))
     627                 :             : 
     628                 :             :        end do
     629   [ #  #  #  #  :           0 :        call self%set_bilinear(n,ilist,ilist,Rlist,bivallist)
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     630                 :             :     endif
     631                 :           0 :   end subroutine set_sia
     632                 :             : 
     633                 :             :   !-------------------------------------------------------------------!
     634                 :             :   ! add a SIA for every spin, usually from a user input.
     635                 :             :   ! input_sia_k1amp: amplitude of SIA, a scalar
     636                 :             :   ! input_sia_k1dir: direction of SIA, a vector
     637                 :             :   !-------------------------------------------------------------------!
     638                 :             : 
     639                 :           0 :   subroutine add_input_sia(self,  input_sia_k1amp, input_sia_k1dir)
     640                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     641                 :             :     real(dp), intent(in):: input_sia_k1amp, input_sia_k1dir(3)
     642                 :           0 :     integer :: in_sia_ind(self%nspin)
     643                 :           0 :     real(dp)::  in_sia_k1amp(self%nspin), in_sia_k1dir(3, self%nspin)
     644                 :             : 
     645                 :             :     integer :: i
     646                 :             : 
     647         [ #  # ]:           0 :     if (xmpi_comm_rank(xmpi_world)==0) then
     648                 :           0 :        write(std_out,'(A28)') "Adding SIA terms from input"
     649         [ #  # ]:           0 :        do i =1, self%nspin
     650                 :           0 :           in_sia_ind(i)=i
     651                 :           0 :           in_sia_k1amp(i)=input_sia_k1amp
     652         [ #  # ]:           0 :           in_sia_k1dir(:,i)=input_sia_k1dir
     653                 :             :        end do
     654                 :           0 :        call self%set_sia(self%nspin, in_sia_ind, in_sia_k1amp, in_sia_k1dir )
     655                 :             :     endif
     656                 :           0 :   end subroutine add_input_sia
     657                 :             : 
     658                 :             : 
     659                 :             :   !-------------------------------------------------------------------!
     660                 :             :   ! Read potential from xml file
     661                 :             :   ! Inputs:
     662                 :             :   !  xml_fname: filename
     663                 :             :   !  use_exchange: whether to read exchange term
     664                 :             :   !  use_dmi: whether to read DMI term
     665                 :             :   !  use_sia: whether to read SIA term
     666                 :             :   !  use_bi: whether to read bilinear term (added on top of other terms.)
     667                 :             :   !-------------------------------------------------------------------!
     668                 :           0 :   subroutine read_xml(self, xml_fname, use_exchange, use_dmi, use_sia, use_bi)
     669                 :             :     class(spin_primitive_potential_t), intent(inout) :: self
     670                 :             :     character(kind=C_CHAR) :: xml_fname(*)
     671                 :             :     integer :: natoms, nspin, exc_nnz, dmi_nnz, uni_nnz, bi_nnz
     672                 :             :     logical, optional, intent(in) :: use_exchange, use_dmi, use_sia, use_bi
     673                 :             :     logical :: uexc, udmi, usia, ubi
     674                 :             :     real(dp) :: ref_energy
     675                 :             : 
     676                 :             :     type(c_ptr) ::  p_unitcell,         &
     677                 :             :          p_masses,  p_index_spin, p_gyroratios, p_damping_factors, p_positions, p_spinat, &
     678                 :             :          p_exc_ilist, p_exc_jlist, p_exc_Rlist, p_exc_vallist, &
     679                 :             :          p_dmi_ilist, p_dmi_jlist, p_dmi_Rlist, p_dmi_vallist, &
     680                 :             :          p_uni_ilist, p_uni_amplitude_list, p_uni_direction_list, &
     681                 :             :          p_bi_ilist, p_bi_jlist, p_bi_Rlist, p_bi_vallist
     682                 :             : 
     683                 :             :     real(dp), target :: dummy_real(1)
     684                 :             :     integer(c_int),target :: dummy_int(1)
     685                 :             : 
     686                 :             :     integer(c_int),pointer :: index_spin(:)=>null() ,&
     687                 :             :          exc_ilist(:)=>null(), exc_jlist(:)=>null(),  exc_Rlist(:)=>null(), &
     688                 :             :          dmi_ilist(:)=>null(), dmi_jlist(:)=>null(),  dmi_Rlist(:)=>null(), &
     689                 :             :          bi_ilist(:)=>null(), bi_jlist(:)=>null(), bi_Rlist(:)=>null(), &
     690                 :             :          uni_ilist(:)=>null()
     691                 :             : 
     692                 :             :     real(c_double), pointer:: unitcell(:)=>null(), masses(:)=>null(),  &
     693                 :             :          gyroratios(:)=>null(), damping_factors(:)=>null(), &
     694                 :             :          positions(:)=>null(), spinat(:)=>null(), &
     695                 :             :          exc_vallist(:)=>null(), dmi_vallist(:)=>null(), &
     696                 :             :          uni_amplitude_list(:)=>null(), uni_direction_list(:)=>null(), &
     697                 :             :          bi_vallist(:)=>null()
     698                 :             : 
     699                 :             : 
     700                 :             :     real(dp) :: uc(3,3)
     701                 :             : 
     702                 :             :     integer :: master, my_rank, comm, nproc
     703                 :             :     logical :: iam_master
     704                 :           0 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     705                 :             : 
     706                 :             :     ! associate the fortran pointers with the dummy variables
     707         [ #  # ]:           0 :     if(.not. iam_master) then
     708                 :           0 :       index_spin=>dummy_int
     709                 :           0 :       exc_ilist=>dummy_int
     710                 :           0 :       exc_jlist=>dummy_int
     711                 :           0 :       exc_Rlist=>dummy_int
     712                 :           0 :       exc_vallist=>dummy_real
     713                 :           0 :       dmi_ilist=>dummy_int
     714                 :           0 :       dmi_jlist=>dummy_int
     715                 :           0 :       dmi_Rlist=>dummy_int
     716                 :           0 :       dmi_vallist=>dummy_real
     717                 :           0 :       uni_ilist=>dummy_int
     718                 :           0 :       uni_amplitude_list=>dummy_real
     719                 :           0 :       uni_direction_list=>dummy_real
     720                 :           0 :       bi_ilist=>dummy_int
     721                 :           0 :       bi_jlist=>dummy_int
     722                 :           0 :       bi_Rlist=>dummy_int
     723                 :           0 :       bi_vallist=>dummy_real
     724                 :           0 :       unitcell=>dummy_real
     725                 :           0 :       masses=>dummy_real
     726                 :           0 :       gyroratios=>dummy_real
     727                 :           0 :       damping_factors=>dummy_real
     728                 :           0 :       positions=>dummy_real
     729                 :           0 :       spinat=>dummy_real
     730                 :             :    endif
     731                 :             : 
     732         [ #  # ]:           0 :     if (iam_master) then
     733                 :           0 :        write(std_out,'(A58)') "Reading parameters from xml file and setting up spin model"
     734                 :           0 :        write(std_out,'(A80)') " "
     735                 :             :        call xml_read_spin(xml_fname, ref_energy, p_unitcell,                 &
     736                 :             :             natoms, p_masses, nspin, p_index_spin, p_gyroratios, p_damping_factors, p_positions, p_spinat, &
     737                 :             :             exc_nnz, p_exc_ilist, p_exc_jlist, p_exc_Rlist, p_exc_vallist, &
     738                 :             :             dmi_nnz, p_dmi_ilist, p_dmi_jlist, p_dmi_Rlist, p_dmi_vallist, &
     739                 :             :             uni_nnz, p_uni_ilist, p_uni_amplitude_list, p_uni_direction_list, &
     740                 :           0 :             bi_nnz, p_bi_ilist, p_bi_jlist, p_bi_Rlist, p_bi_vallist)
     741         [ #  # ]:           0 :        call c_f_pointer(p_unitcell, unitcell, [9])
     742         [ #  # ]:           0 :        call c_f_pointer(p_masses, masses, [natoms])
     743         [ #  # ]:           0 :        call c_f_pointer(p_index_spin, index_spin, [natoms])
     744         [ #  # ]:           0 :        call c_f_pointer(p_gyroratios, gyroratios, [nspin])
     745         [ #  # ]:           0 :        call c_f_pointer(p_damping_factors, damping_factors, [nspin])
     746         [ #  # ]:           0 :        call c_f_pointer(p_positions, positions, [natoms*3])
     747         [ #  # ]:           0 :        call c_f_pointer(p_spinat, spinat, [natoms*3])
     748         [ #  # ]:           0 :        call c_f_pointer(p_exc_ilist, exc_ilist, [exc_nnz])
     749         [ #  # ]:           0 :        call c_f_pointer(p_exc_jlist, exc_jlist, [exc_nnz])
     750         [ #  # ]:           0 :        call c_f_pointer(p_exc_Rlist, exc_Rlist, [exc_nnz*3])
     751         [ #  # ]:           0 :        call c_f_pointer(p_exc_vallist, exc_vallist, [exc_nnz*3])
     752         [ #  # ]:           0 :        call c_f_pointer(p_dmi_ilist, dmi_ilist, [dmi_nnz])
     753         [ #  # ]:           0 :        call c_f_pointer(p_dmi_jlist, dmi_jlist, [dmi_nnz])
     754         [ #  # ]:           0 :        call c_f_pointer(p_dmi_Rlist, dmi_Rlist, [dmi_nnz*3])
     755         [ #  # ]:           0 :        call c_f_pointer(p_dmi_vallist, dmi_vallist, [dmi_nnz*3])
     756         [ #  # ]:           0 :        call c_f_pointer(p_uni_ilist, uni_ilist, [uni_nnz])
     757         [ #  # ]:           0 :        call c_f_pointer(p_uni_amplitude_list, uni_amplitude_list, [uni_nnz])
     758         [ #  # ]:           0 :        call c_f_pointer(p_uni_direction_list, uni_direction_list, [uni_nnz*3])
     759         [ #  # ]:           0 :        call c_f_pointer(p_bi_ilist, bi_ilist, [bi_nnz])
     760         [ #  # ]:           0 :        call c_f_pointer(p_bi_jlist, bi_jlist, [bi_nnz])
     761         [ #  # ]:           0 :        call c_f_pointer(p_bi_Rlist, bi_Rlist, [bi_nnz*3])
     762         [ #  # ]:           0 :        call c_f_pointer(p_bi_vallist, bi_vallist, [bi_nnz*9])
     763                 :             : 
     764                 :             :        ! change of units to a.u.
     765                 :             : 
     766                 :             :        ! unitcell already Bohr
     767                 :             : 
     768                 :             :        !gyroratios already in a.u. (unit=1)
     769                 :             : 
     770                 :             :        ! masses already in a.u.
     771                 :             : 
     772                 :             :        ! J, DMI, k1, bi are in eV
     773         [ #  # ]:           0 :        exc_vallist(:) =exc_vallist(:) * eV_Ha
     774         [ #  # ]:           0 :        dmi_vallist(:) = dmi_vallist(:) * eV_Ha
     775         [ #  # ]:           0 :        uni_amplitude_list(:) = uni_amplitude_list(:) * eV_Ha
     776         [ #  # ]:           0 :        bi_vallist(:) = bi_vallist(:) * eV_Ha
     777                 :             : 
     778                 :           0 :        write(std_out,'(A80)') " "
     779                 :           0 :        write(std_out,'(A21)') "Setting up spin model"
     780                 :           0 :        write(std_out,'(A15)') "Setting system"
     781   [ #  #  #  # ]:           0 :        uc(:,:)=transpose(reshape(unitcell, [3,3]))
     782                 :             :        !call set_atoms(self,)
     783                 :             :     endif
     784                 :             : 
     785                 :             :     ! (MPI) Only this runs on non-master node
     786                 :             :     call self%set_spin_primcell(natoms, uc, positions, &
     787   [ #  #  #  #  :           0 :          nspin, index_spin, spinat, gyroratios, damping_factors )
             #  #  #  # ]
     788                 :             : 
     789         [ #  # ]:           0 :     if (iam_master) then
     790         [ #  # ]:           0 :        if(.not. present(use_exchange))  then
     791                 :             :           uexc=.True.
     792                 :             :        else
     793                 :           0 :           uexc=use_exchange
     794                 :             :        end if
     795                 :             : 
     796   [ #  #  #  # ]:           0 :        if(uexc .and. exc_nnz>0) then
     797                 :           0 :           write(std_out,'(A23)') "Setting exchange terms"
     798                 :             :           call self%set_exchange(exc_nnz,exc_ilist,exc_jlist,&
     799                 :             :                reshape(exc_Rlist, (/3, exc_nnz /)), &
     800   [ #  #  #  # ]:           0 :                reshape(exc_vallist, (/3, exc_nnz/)))
     801                 :             :        else
     802                 :           0 :         if (.not. uexc)  write(std_out, '(A38)') " Exchange term from xml file not used."
     803                 :             :        endif
     804                 :             : 
     805         [ #  # ]:           0 :        if(.not. present(use_dmi))  then
     806                 :             :           udmi=.True.
     807                 :             :        else
     808                 :           0 :           udmi=use_dmi
     809                 :             :        end if
     810   [ #  #  #  # ]:           0 :        if (udmi .and. dmi_nnz>0) then
     811                 :           0 :           write(std_out,'(A19)') "Setting DMI terms."
     812                 :             :           call self%set_dmi( n=dmi_nnz, ilist=dmi_ilist, jlist=dmi_jlist, &
     813                 :             :                Rlist=reshape(dmi_Rlist, (/3, dmi_nnz /)), &
     814   [ #  #  #  # ]:           0 :                vallist = reshape(dmi_vallist, (/3, dmi_nnz/)))
     815                 :             :        else
     816                 :           0 :           if (.not. udmi) write(std_out, '(A35)') " DMI term from xml file not used."
     817                 :             :        end if
     818                 :             : 
     819         [ #  # ]:           0 :        if(.not. present(use_sia)) then
     820                 :             :           usia=.True.
     821                 :             :        else
     822                 :           0 :           usia=use_sia
     823                 :             :        end if
     824   [ #  #  #  # ]:           0 :        if (usia .and. uni_nnz>0) then
     825                 :           0 :           write(std_out,'(A18)') "Setting SIA terms"
     826                 :             :           call self%set_sia(uni_nnz, uni_ilist, uni_amplitude_list, &
     827         [ #  # ]:           0 :                reshape(uni_direction_list, [3, uni_nnz]) )
     828                 :             :        else
     829                 :           0 :          if(.not. usia) write(std_out,'(A34)') " SIA term in xml file not used."
     830                 :             :        end if
     831                 :             : 
     832         [ #  # ]:           0 :        if(.not. present(use_bi)) then
     833                 :             :           ubi=.True.
     834                 :             :        else
     835                 :           0 :           ubi=use_bi
     836                 :             :        endif
     837   [ #  #  #  # ]:           0 :        if (ubi .and. bi_nnz>0) then
     838                 :           0 :           write(std_out,'(A23)') "Setting bilinear terms."
     839                 :             :           call self%set_bilinear(bi_nnz, bi_ilist, bi_jlist,  &
     840                 :             :                Rlist=reshape(bi_Rlist, (/3, bi_nnz /)), &
     841   [ #  #  #  #  :           0 :                vallist = reshape(bi_vallist, (/3,3, bi_nnz/)))
          #  #  #  #  #  
                #  #  # ]
     842                 :             :        else
     843                 :           0 :           if(.not. ubi) write(std_out, '(A38)') " Bilinear term in xml file not used."
     844                 :             :        endif
     845                 :             :     endif
     846                 :             : 
     847         [ #  # ]:           0 :     if (iam_master) then
     848                 :             :        call xml_free_spin(xml_fname, ref_energy, p_unitcell,                 &
     849                 :             :             natoms, p_masses, nspin, p_index_spin, p_gyroratios, p_damping_factors, p_positions, p_spinat, &
     850                 :             :             exc_nnz, p_exc_ilist, p_exc_jlist, p_exc_Rlist, p_exc_vallist, &
     851                 :             :             dmi_nnz, p_dmi_ilist, p_dmi_jlist, p_dmi_Rlist, p_dmi_vallist, &
     852                 :             :             uni_nnz, p_uni_ilist, p_uni_amplitude_list, p_uni_direction_list, &
     853                 :           0 :             bi_nnz, p_bi_ilist, p_bi_jlist, p_bi_Rlist, p_bi_vallist)
     854                 :             :     endif
     855                 :             : 
     856                 :           0 :   end subroutine read_xml
     857                 :             : 
     858                 :             :   !-------------------------------------------------------------------!
     859                 :             :   ! fill_supercell:
     860                 :             :   !  generate a supercell potential from primitive potential
     861                 :             :   ! Input:
     862                 :             :   !  scmaker: supercell maker helper class
     863                 :             :   !  scpot: supercell potential (a pointer to a abstract potential)
     864                 :             :   !-------------------------------------------------------------------!
     865                 :           2 :   subroutine fill_supercell(self, scmaker, params, scpot, supercell)
     866                 :             :     class(spin_primitive_potential_t) , intent(inout) :: self
     867                 :             :     type(supercell_maker_t),            intent(inout) :: scmaker
     868                 :             :     type(multibinit_dtset_type),        intent(inout) :: params
     869                 :             :     class(abstract_potential_t), pointer, intent(inout) :: scpot
     870                 :             :     type(mbsupercell_t), target :: supercell
     871                 :             : 
     872                 :             :     integer :: nspin, sc_nspin, i, R(3), ind_Rij(3), iR, ii, ij, inz
     873                 :             :     integer :: master, my_rank, comm, nproc, ierr
     874                 :           2 :     integer, allocatable :: i_sc(:), j_sc(:), Rj_sc(:, :)
     875                 :             :     logical :: iam_master
     876                 :           4 :     real(dp) :: val_sc(scmaker%ncells)
     877                 :             : 
     878                 :           2 :     ABI_UNUSED_A(params)
     879                 :             : 
     880                 :           2 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     881                 :             : 
     882                 :           2 :     nspin=self%nspin
     883                 :           2 :     sc_nspin= nspin * scmaker%ncells
     884                 :           2 :     call xmpi_bcast(sc_nspin, master, comm, ierr)
     885                 :             :     !ABI_MALLOC_SCALAR(spin_potential_t::scpot)
     886         [ -  + ]:           2 :     ABI_MALLOC_TYPE_SCALAR(spin_potential_t, scpot)
     887                 :             :     select type(scpot) ! use select type because properties only defined for spin_potential is used.
     888                 :             :     type is (spin_potential_t)
     889                 :           2 :       call scpot%initialize(sc_nspin)
     890                 :           2 :       call scpot%set_supercell(supercell)
     891         [ +  - ]:           4 :       if (iam_master) then
     892                 :           2 :         call self%coeff%sum_duplicates()
     893         [ +  + ]:         158 :          do inz=1, self%coeff%nnz
     894                 :         156 :           ind_Rij=self%coeff%get_ind_inz(inz)
     895                 :         156 :           iR=ind_Rij(1)
     896                 :         156 :           ii=ind_Rij(2)
     897                 :         156 :           ij=ind_Rij(3)
     898         [ +  + ]:         624 :           R=self%Rlist%data(:,iR)
     899                 :         156 :           call scmaker%trans_i(nbasis=nspin*3, i=ii, i_sc=i_sc)
     900                 :         156 :           call scmaker%trans_j_and_Rj(nbasis=nspin*3, j=ij, Rj=R, j_sc=j_sc, Rj_sc=Rj_sc)
     901         [ +  + ]:       33852 :           val_sc(:)= self%coeff%val%data(inz)
     902         [ +  + ]:       33852 :           do i=1, scmaker%ncells
     903                 :       33852 :             call scpot%add_bilinear_term(i_sc(i), j_sc(i), val_sc(i))
     904                 :             :           end do
     905         [ +  - ]:         156 :           ABI_SFREE(i_sc)
     906         [ +  - ]:         156 :           ABI_SFREE(j_sc)
     907         [ +  - ]:         158 :           ABI_SFREE(Rj_sc)
     908                 :             :         end do
     909                 :             :       endif
     910                 :             :     end select
     911                 :           2 :     ABI_UNUSED_A(params)
     912   [ -  +  -  +  :           4 :   end subroutine fill_supercell
                   -  + ]
     913                 :             : 
     914                 :             :   !-------------------------------------------------------------------!
     915                 :             :   ! check if a string1 ends with string2.
     916                 :             :   ! used to check if file is .nc or .xml
     917                 :             :   !-------------------------------------------------------------------!
     918                 :           4 :   function  endswith(string1, string2) result(answer)
     919                 :             :     character(len=*), intent(in) :: string1
     920                 :             :     character(len=*), intent(in) :: string2
     921                 :             :     logical :: answer
     922                 :           4 :     answer = .False.
     923         [ -  + ]:           4 :     if(len(string2)>len(string1)) return
     924         [ +  + ]:           4 :     if(string1(len(string1)-len(string2)+1:)==string2) answer = .True.
     925                 :             :   end function endswith
     926                 :             : 
     927                 :             : 
     928   [ +  +  -  +  :           8 : end module m_spin_primitive_potential
          +  +  -  +  -  
          +  -  +  -  +  
             -  +  -  + ]
        

Generated by: LCOV version 2.3-1