LCOV - code coverage report
Current view: top level - src/77_ddb - m_ddb_magpen.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.9 % 1065 1021
Test Date: 2026-09-21 13:49:52 Functions: 90.0 % 10 9

            Line data    Source code
       1              : !{\src2tex{textfont=tt}}
       2              : !!****m* ABINIT/m_ddb_magpen
       3              : !! NAME
       4              : !!  m_ddb_magpen
       5              : !!
       6              : !! FUNCTION
       7              : !!  Convert second- and -third (Berry curvatures) order total energy derivatives
       8              : !!  calculated with the magnetic penalty (constrained-B functional) into the
       9              : !!  corresponding quantities of different magnetic functionals:
      10              : !!  --constrained-M (fixed-spin)
      11              : !!  --constrained-H (relaxed spin)
      12              : !!  Calculate and write the ensuing clamped-ion susceptibilities. Lattice-mediated
      13              : !!  contributions are incorporated in m_ddb_omega_interpol.
      14              : !!
      15              : !! COPYRIGHT
      16              : !!  Copyright (C) 2023 ABINIT group (MR and MS)
      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              : !!
      21              : !! NOTES
      22              : !!
      23              : !! PARENTS
      24              : !!
      25              : !! CHILDREN
      26              : !!
      27              : !! SOURCE
      28              : 
      29              : #if defined HAVE_CONFIG_H
      30              : #include "config.h"
      31              : #endif
      32              : 
      33              : #include "abi_common.h"
      34              : 
      35              : module m_ddb_magpen
      36              : 
      37              :  use defs_basis
      38              :  use m_abicore
      39              :  use m_profiling_abi
      40              :  use m_errors
      41              :  use m_ddb
      42              :  use m_fstrings,        only : itoa, sjoin
      43              :  use m_macroave,        only : POLINT
      44              :  use m_io_tools,        only : open_file
      45              :  use m_cgtools,         only : fxphas_seq
      46              :  use m_dynmat,          only : pheigvec_normalize
      47              :  use m_numeric_tools,   only : polcoe
      48              : 
      49              :  implicit none
      50              : 
      51              :  public :: ddb_magpen       ! Convert the derivatives calculated with the magnetic penalty into the physically relevant ones.
      52              :  public :: local_spinsus    ! Treat local spin susceptibility (2nd-order magnetic derivatives)
      53              :  public :: magmom           ! Treat first-order magnetic moments (2nd-order mixed derivatives)
      54              :  public :: mp_d2etot        ! Treat 2nd-order nonmagnetic derivatives
      55              :  public :: asrw0            ! Apply the ASR correction calculated at w=0 at any value of w
      56              : 
      57              :  private
      58              : 
      59              : ! *************************************************************************
      60              : 
      61              : contains
      62              : !!***
      63              : 
      64              : !!****f* m_ddb_magpen/ddb_magpen
      65              : !! NAME
      66              : !! ddb_magpen
      67              : !!
      68              : !! FUNCTION
      69              : !! Convert the second- and possibly third-order derivatives calculated with the magnetic penalty
      70              : !! into physically relevant quantities.
      71              : !!
      72              : !! INPUTS
      73              : !! ddb (INOUT) = ddb block datastructure
      74              : !! ddb_lw (INOUT) = ddb_lw block datastructure
      75              : !! magpen = amplitude (in Ha) of the applied magnetic penalty
      76              : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
      77              : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
      78              : !! mpert = maximum number of ipert
      79              : !! mpopt = 1 calculate the frozen-magnetic second-order quantities
      80              : !!         2 calculate the spin-relaxed second-order quantities
      81              : !! natom= number of atoms in unit cell
      82              : !! ntypat= number of atom types
      83              : !! timdisp= 1 calculate the third-order Berry curvatures
      84              : !! ucvol= unit cell volume
      85              : !!
      86              : !! OUTPUT
      87              : !! ddb= ddb%val updated with the corrected second-order derivatives
      88              : !!
      89              : !! SOURCE
      90              : 
      91            3 :  subroutine ddb_magpen(ddb,ddb_lw,&
      92              : & magpen,mpatpol,mpdir,mpert,mpopt,natom, &
      93            3 : & prtvol,rftyp,ucvol,timdisp,xred)
      94              : 
      95              : !Arguments -------------------------------
      96              : !scalars
      97              :  integer,intent(in) :: mpert,mpopt,natom,prtvol,rftyp,timdisp
      98              :  real(dp),intent(in) :: magpen,ucvol
      99              : !arrays
     100              :  type(ddb_type),intent(inout) :: ddb,ddb_lw
     101              :  integer,intent(in) :: mpatpol(2),mpdir(3)
     102              :  real(dp),intent(in) :: xred(3,natom)
     103              : 
     104              : !Local variables -------------------------
     105              : !scalars
     106              :  integer :: iblok,ii,jblok,kblok,lblok,nblok,ndim
     107              :  integer :: nmat,nmdir,optgb,prtopt
     108              :  character(len=500) :: msg
     109              :  logical :: qeq0
     110              : !arrays
     111              :  integer :: rfelfd(4),rfphon(4),rfstrs(4),rfmagn(4),rffreq(4)
     112              :  real(dp) :: omega(3),qphnrm(3),qphon(3,3),qpt(3)
     113            3 :  complex(dpc), allocatable :: barmagsus(:,:),invbarmagsus(:,:)
     114            3 :  complex(dpc), allocatable :: invmagsus(:,:), magsus(:,:), invhmat(:,:)
     115            3 :  complex(dpc), allocatable :: barmmom(:,:),barmmom_tr(:,:),mmom(:,:),mmom_tr(:,:)
     116            3 :  complex(dpc), allocatable :: zfield(:,:), zfield_tr(:,:)
     117            3 :  complex(dpc), allocatable :: bc_barmagsus(:,:),bc_ss(:,:),bc_sp(:,:)
     118            3 :  complex(dpc), allocatable :: ifcmat(:,:),ifcmat_fm(:,:),zeff(:,:),zeff_tr(:,:)
     119            3 :  complex(dpc), allocatable :: fmzeff(:,:),fmzeff_tr(:,:)
     120            3 :  complex(dpc), allocatable :: lm_epsilon(:,:),dum_phongreen(:,:)
     121              : 
     122              : ! *********************************************************************
     123          246 :  write(msg, '(2a,(80a),6a)' ) ch10,('=',ii=1,80),ch10,ch10,&
     124            3 :  ' Constrained DFPT section ',ch10,ch10,&
     125          249 :  ' (Quantities are in atomic units and along Cartesian directions)'
     126            9 :  call wrtout([std_out, ab_out], msg)
     127              : 
     128            3 :  prtopt=1
     129            3 :  if (magpen<zero) then
     130              :    nmat= 1
     131            3 :  else if (magpen>zero) then
     132            3 :    nmat= mpatpol(2) - mpatpol(1) + 1
     133              :  end if
     134           12 :  nmdir=sum(mpdir(:))
     135            3 :  ndim=nmat*nmdir
     136            3 :  optgb=1
     137           12 :  ABI_MALLOC(barmagsus,(ndim,ndim))
     138            9 :  ABI_MALLOC(magsus,(ndim,ndim))
     139            9 :  ABI_MALLOC(invbarmagsus,(ndim,ndim))
     140            9 :  ABI_MALLOC(invmagsus,(ndim,ndim))
     141            9 :  ABI_MALLOC(invhmat,(ndim,ndim))
     142           12 :  ABI_MALLOC(barmmom,(ndim,(natom+5)*3))
     143            9 :  ABI_MALLOC(barmmom_tr,((natom+5)*3,ndim))
     144            9 :  ABI_MALLOC(mmom,(ndim,(natom+5)*3))
     145            9 :  ABI_MALLOC(mmom_tr,((natom+5)*3,ndim))
     146            9 :  ABI_MALLOC(zfield,(ndim,(natom+5)*3))
     147            9 :  ABI_MALLOC(zfield_tr,((natom+5)*3,ndim))
     148              : 
     149           12 :  ABI_MALLOC(ddb%val_fs,(2,ddb%msize,ddb%nblok))
     150              : ! if (mpopt==2) ABI_MALLOC(ddb%val_rs,(2,ddb%msize,ddb%nblok))
     151            9 :  ABI_MALLOC(ddb%val_rs,(2,ddb%msize,ddb%nblok))
     152              : 
     153           15 :  ABI_MALLOC(ifcmat,(3*natom,3*natom))
     154            9 :  ABI_MALLOC(ifcmat_fm,(3*natom,3*natom))
     155            9 :  ABI_MALLOC(fmzeff,(3,3*natom))
     156            9 :  ABI_MALLOC(fmzeff_tr,(3*natom,3))
     157            6 :  ABI_MALLOC(zeff,(3,3*natom))
     158            6 :  ABI_MALLOC(zeff_tr,(3*natom,3))
     159            3 :  ABI_MALLOC(lm_epsilon,(3,3))
     160            9 :  ABI_MALLOC(dum_phongreen,(3*natom,3*natom))
     161              : 
     162            3 :  nblok=ddb%nblok
     163            7 :  do kblok=1,nblok
     164              : 
     165              :    ! Look for the local spin-susceptibility block in the DDB
     166            4 :    omega=zero
     167            4 :    qphon=zero
     168           16 :    qphon(:,1)=ddb%qpt(1:3,kblok)
     169           16 :    qpt=qphon(:,1)
     170           16 :    qeq0=(sqrt(sum(qphon(:,1)**2))<tol8)
     171           16 :    qphnrm(:)=ddb%nrm(1,kblok)
     172            4 :    omega(1)=ddb%omega(1,kblok)
     173           12 :    rfphon(1:2)=0
     174           12 :    rfelfd(1:2)=0
     175           12 :    rfstrs(1:2)=0
     176            4 :    if (magpen<zero) then
     177            0 :      rfmagn(1:2)= 1
     178            4 :    else if (magpen>zero) then
     179           12 :      rfmagn(1:2)= 2
     180              :    end if
     181              : 
     182          328 :    write(msg, '(1a,(80a),2a,3f16.8,2a,f16.8,a)' ) ch10,('-',ii=1,80),ch10, &
     183            4 :    ' q point  ', qphon(:,1),ch10,&
     184          332 :    ' frequency', ddb%omega(1,kblok), ch10
     185           12 :    call wrtout([std_out, ab_out], msg)
     186              : 
     187              :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
     188            4 :   & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
     189              : 
     190              :    ! Calculate and write the spin-susceptibility matrices
     191            4 :    if (iblok /= 0) then
     192            4 :      if (prtvol>1) then
     193            4 :        if (magpen<zero) then
     194            0 :          write(msg, '(2a)' ) ' Spin susceptibility (Uniform Zeeman) ',ch10
     195            0 :          call wrtout([std_out, ab_out], msg)
     196            4 :        else if (magpen>zero) then
     197            4 :          write(msg, '(2a)' ) ' Spin susceptibility (Local Zeeman) ',ch10
     198           12 :          call wrtout([std_out, ab_out], msg)
     199              :        end if
     200              :      end if
     201              : 
     202              :      call local_spinsus(barmagsus,ddb,iblok,invbarmagsus,invmagsus,invhmat,magpen,magsus,&
     203            4 :    & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qpt,xred)
     204              : 
     205              :    end if
     206              : 
     207              :    ! Calculate and write the induced magnetic moments
     208            4 :    if (prtvol>1) then
     209          328 :      write(msg, '(2a,(80a),4a)' ) ch10,('-',ii=1,80),ch10,ch10,&
     210          332 :      ' First-order magnetic moments ',ch10
     211           12 :      call wrtout([std_out, ab_out], msg)
     212              :    end if
     213              : 
     214              :    ! First atomic-displacement
     215            4 :    rfphon(2)=1
     216           12 :    rfelfd(1:2)=0
     217           12 :    rfstrs(1:2)=0
     218            4 :    rfmagn(:)=0
     219            4 :    if (magpen<zero) then
     220            0 :      rfmagn(1)= 1
     221            4 :    else if (magpen>zero) then
     222            4 :      rfmagn(1)= 2
     223              :    end if
     224              : 
     225              :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
     226            4 :   & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
     227              : 
     228              :    ! Then electric field
     229              :    ! Look for the induced magnetic moments block in the DDB
     230            4 :    jblok=0
     231            4 :    if (qeq0) then
     232            3 :      rfphon(2)=0
     233            3 :      rfelfd(2)=2
     234            9 :      rfstrs(1:2)=0
     235            3 :      rfmagn(:)=0
     236            3 :      if (magpen<zero) then
     237            0 :        rfmagn(1)= 1
     238            3 :      else if (magpen>zero) then
     239            3 :        rfmagn(1)= 2
     240              :      end if
     241              : 
     242              :      call ddb%get_block(jblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
     243            3 :    & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
     244              :    end if
     245              : 
     246              :    ! Then macroscopic Zeeman field
     247              :    ! Look for the induced magnetic moments block in the DDB
     248              :    lblok=0
     249            4 :    rfphon(:)=0
     250            4 :    rfelfd(:)=0
     251           12 :    rfstrs(1:2)=0
     252            4 :    rfmagn(2)=1
     253            4 :    if (magpen<zero) then
     254            0 :      rfmagn(1)= 1
     255            4 :    else if (magpen>zero) then
     256            4 :      rfmagn(1)= 2
     257              :    end if
     258              : 
     259              :    call ddb%get_block(lblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
     260            4 :  & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
     261              : 
     262            4 :    if (iblok /= 0 .or. jblok /=0 .or. lblok/=0) then
     263              :      call magmom(barmmom,barmmom_tr,ddb,invbarmagsus,invhmat,iblok,jblok,lblok,magpen,magsus,mmom,mmom_tr,&
     264            4 :    & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qpt,xred,zfield,zfield_tr)
     265              :    end if
     266              : 
     267              :    !Now calculate the non-magnetic second-order quantities
     268          328 :    write(msg, '(2a,(80a),4a)' ) ch10,('-',ii=1,80),ch10,ch10,&
     269          332 :    ' Second-order linear-response tensors ',ch10
     270           12 :    call wrtout([std_out, ab_out], msg)
     271              : 
     272              :    !Convert ddb%val to second-order energies
     273            4 :    call ddb%to_d2etot(ddb%val,kblok,0,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
     274              : 
     275              :    !Convert second-order derivatives to diferent magnetic boundary conditions
     276              :    call mp_d2etot(barmagsus,ddb,kblok,magsus,mpert,mpopt,natom, &
     277            4 :  & ndim,zfield,zfield_tr)
     278              : 
     279              :    !Convert second-order energies to the physical quantities of ddb%val
     280            4 :    call ddb%to_d2etot(ddb%val,kblok,1,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
     281            4 :    call ddb%to_d2etot(ddb%val_fs,kblok,1,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
     282            4 :    if (mpopt==2) call ddb%to_d2etot(ddb%val_rs,kblok,1,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
     283              : 
     284              :    !Print the physical quantities in the new magnetic boundary conditions
     285              :    if (prtopt==1) then
     286            4 :      if (mpopt==1) then
     287            0 :        call mp_d2etot_print(ddb,ddb%val_fs,kblok,mpert,natom,nblok,1,omega,qeq0,qphnrm,qphon,ddb%msize)
     288            4 :      else if (mpopt==2) then
     289            4 :        call mp_d2etot_print(ddb,ddb%val_rs,kblok,mpert,natom,nblok,2,omega,qeq0,qphnrm,qphon,ddb%msize)
     290              :      end if
     291              :    end if
     292              : 
     293            4 :    rfmagn(:)=0
     294            4 :    rfelfd(:)=0
     295            7 :    rfphon(:)=0
     296              : 
     297              :  end do
     298              : 
     299              :  ! BERRY CURVATURES
     300            3 :  if (timdisp==1) then
     301              : 
     302            8 :    ABI_MALLOC(ddb_lw%val_fs,(2,ddb_lw%msize,ddb_lw%nblok))
     303              : 
     304            6 :    ABI_MALLOC(bc_barmagsus,(ndim,ndim))
     305            6 :    ABI_MALLOC(bc_ss,(ndim,ndim))
     306            6 :    ABI_MALLOC(bc_sp,(ndim,(natom+5)*3))
     307              : 
     308          164 :    write(msg, '(2a,(80a),4a)' ) ch10,('=',ii=1,80),ch10,ch10,&
     309          166 :    ' Frequency-derivatives (Berry curvatures) constrained DFPT section ',ch10
     310            6 :    call wrtout([std_out, ab_out], msg)
     311              : 
     312            2 :    rffreq(:)=0
     313            2 :    nblok=ddb_lw%nblok
     314            6 :    do kblok=1,nblok
     315              : 
     316            4 :      if (ddb_lw%typ(kblok)/=33) cycle
     317              : 
     318              :      !Berry curvature of the penalized spin-susceptibility
     319            2 :      qphon=zero
     320            8 :      qphon(:,1)=ddb_lw%qpt(1:3,kblok)
     321            8 :      qpt= qphon(:,1)
     322            8 :      qphnrm(:)=ddb_lw%nrm(1,kblok)
     323            8 :      omega(:)=ddb_lw%omega(:,kblok)
     324            8 :      rfphon(1:3)=0
     325            8 :      rfelfd(1:3)=0
     326            8 :      rfstrs(1:3)=0
     327            2 :      rffreq(3)=1
     328            2 :      iblok=0
     329            2 :      if (magpen<zero) then
     330            0 :        rfmagn(1:2)= 1
     331            2 :      else if (magpen>zero) then
     332            6 :        rfmagn(1:2)= 2
     333              :      end if
     334              : 
     335          164 :      write(msg, '(a,(80a),a,3(a,3f16.8,a),3(a,f16.8,a))' ) ch10,('-',ii=1,80),ch10, &
     336            2 :      ' q point 1  ', qphon(:,1),ch10,&
     337            2 :      ' q point 2  ', qphon(:,2),ch10,&
     338            2 :      ' q point 3  ', qphon(:,3),ch10,&
     339            2 :      ' frequency 1', ddb_lw%omega(1,kblok), ch10,&
     340            2 :      ' frequency 2', ddb_lw%omega(2,kblok), ch10,&
     341          166 :      ' frequency 3', ddb_lw%omega(3,kblok), ch10
     342            6 :      call wrtout([std_out, ab_out], msg)
     343              : 
     344              :      call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
     345            2 :    & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
     346              : 
     347            2 :      if (iblok /= 0) then
     348              :        call berrycurv_ss(bc_barmagsus,bc_ss,ddb_lw,iblok,invbarmagsus,mpatpol,mpdir,mpert,&
     349            2 :      & natom,ndim,nmdir,prtvol,qpt,xred)
     350              :      end if
     351              : 
     352              :      !Berry curvature of the induced Zeeman fields
     353              : 
     354              :      !First atomic-displacement
     355              :      iblok=0
     356            2 :      rfphon(2)=1
     357            2 :      rfmagn(:)=0
     358            2 :      if (magpen<zero) then
     359            0 :        rfmagn(1)= 1
     360            2 :      else if (magpen>zero) then
     361            2 :        rfmagn(1)= 2
     362              :      end if
     363              : 
     364              :      call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
     365            2 :    & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
     366              : 
     367              :      ! Then electric field
     368            2 :      jblok=0
     369            2 :      if (qeq0) then
     370            1 :        rfphon(2)=0
     371            1 :        rfelfd(2)=2
     372              : 
     373              :        call ddb_lw%get_block(jblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
     374            1 :      & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
     375              :      end if
     376              : 
     377              :      ! Then macroscopic Zeeman field
     378            2 :      lblok=0
     379            2 :      if (qeq0) then
     380            1 :        rfelfd(2)=0
     381            1 :        rfmagn(2)=1
     382              : 
     383              :        call ddb_lw%get_block(lblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
     384            1 :      & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
     385              :      end if
     386              : 
     387            2 :      if (iblok /= 0 .or. jblok /=0 .or. lblok /= 0) then
     388              :        call berrycurv_sp(barmmom,bc_sp,bc_ss,ddb_lw,iblok,invbarmagsus,jblok,lblok, &
     389            2 :      & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtvol,qpt,xred)
     390              :      end if
     391              : 
     392              :      !Berry curvature of other second-order quantites
     393              :      call berrycurv_pp(barmagsus,bc_barmagsus,bc_sp,ddb_lw,kblok, &
     394            2 :    & mpert,natom,ndim,qeq0,ucvol,zfield)
     395              : 
     396              :      !Print them
     397              :      call mp_d3etot_print(ddb_lw,ddb_lw%val_fs,kblok,mpert,natom,nblok,1,omega,&
     398            6 :    & prtvol,qeq0,qphnrm,qphon,ucvol,ddb_lw%msize)
     399              : 
     400              :    end do
     401            2 :    ABI_FREE(bc_ss)
     402            2 :    ABI_FREE(bc_sp)
     403            2 :    ABI_FREE(bc_barmagsus)
     404              :  end if
     405              : 
     406              : !Deallocations
     407            3 :  ABI_FREE(barmagsus)
     408            3 :  ABI_FREE(barmmom)
     409            3 :  ABI_FREE(barmmom_tr)
     410            3 :  ABI_FREE(magsus)
     411            3 :  ABI_FREE(invbarmagsus)
     412            3 :  ABI_FREE(invmagsus)
     413            3 :  ABI_FREE(mmom)
     414            3 :  ABI_FREE(mmom_tr)
     415            3 :  ABI_FREE(zfield)
     416            3 :  ABI_FREE(zfield_tr)
     417            3 :  ABI_FREE(ifcmat)
     418            3 :  ABI_FREE(ifcmat_fm)
     419            3 :  ABI_FREE(zeff)
     420            3 :  ABI_FREE(zeff_tr)
     421            3 :  ABI_FREE(fmzeff)
     422            3 :  ABI_FREE(fmzeff_tr)
     423            3 :  ABI_FREE(lm_epsilon)
     424            3 :  ABI_FREE(dum_phongreen)
     425            3 :  ABI_FREE(invhmat)
     426              : 
     427            3 :  end subroutine ddb_magpen
     428              : !!***
     429              : 
     430              : !!****f* m_ddb_magpen/local_spinsus
     431              : !! NAME
     432              : !! local_spinsus
     433              : !!
     434              : !! FUNCTION
     435              : !! Calculate the spin-susceptibility matrix and its inverse
     436              : !!
     437              : !! INPUTS
     438              : !! ddb=  Second-order derivative arrais
     439              : !! iblok= index of the current block
     440              : !! magpen = amplitude (in Ha) of the applied magnetic penalty
     441              : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
     442              : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
     443              : !! mpert =maximum number of ipert
     444              : !! natom= number of atoms in unit cell
     445              : !! nblok= number of blocks in the DDB
     446              : !! nmdir= number of directions along which the magnetic penalty was applied
     447              : !! ndim= dimension of the square susceptibilities
     448              : !! prtvol= control the volume of information written on output
     449              : !! fs2rs= (optional) if 1, the routine starts from a precalculated blkval_fs
     450              : !! blkval_fs(2,3,mpert,3,mpert)= fixed-spin 2nd-order derivatives
     451              : !! xred(3,natom)= reduced atomic coordinates
     452              : !!
     453              : !! OUTPUT
     454              : !! barmagsus(ndim,ndim)= Penalized spin-sussceptibility tensor
     455              : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
     456              : !! magsus(ndim,ndim)= Spin-sussceptibility tensor
     457              : !! invmagsus(ndim,ndim)= Inverse of spin-sussceptibility tensor
     458              : !!
     459              : !! SOURCE
     460              : 
     461           68 :  subroutine local_spinsus(barmagsus,ddb,iblok,invbarmagsus,invmagsus,invhmat,magpen,magsus, &
     462           34 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qphon,xred, &
     463           30 : & fs2rs,blkval_fs) !optional
     464              : 
     465              : !Arguments -------------------------------
     466              : !scalars
     467              :  integer,intent(in) :: iblok,mpert,natom,ndim,nmdir
     468              :  integer,intent(in) :: prtopt,prtvol
     469              :  integer,intent(in),optional :: fs2rs
     470              :  real(dp),intent(in) :: magpen
     471              : !arrays
     472              :  type(ddb_type),intent(inout) :: ddb
     473              :  integer,intent(in) :: mpatpol(2),mpdir(3)
     474              :  real(dp),intent(in),optional :: blkval_fs(2,3,mpert,3,mpert,1)
     475              :  real(dp),intent(in) :: qphon(3),xred(3,natom)
     476              :  complex(dpc),intent(out) :: barmagsus(ndim,ndim)
     477              :  complex(dpc),intent(out) :: invbarmagsus(ndim,ndim)
     478              :  complex(dpc),intent(out) :: invhmat(ndim,ndim)
     479              :  complex(dpc),intent(out) :: magsus(ndim,ndim)
     480              :  complex(dpc),intent(out) :: invmagsus(ndim,ndim)
     481              : 
     482              : !Local variables -------------------------
     483              : !scalars
     484              :  integer :: fs2rs_
     485              :  integer :: iat1,iat2,icol,idir1,idir2,index,info,ipert1,ipert2,irow,lwork
     486              :  integer :: ipert1_red,ipert2_red,idir1_red,idir2_red
     487              :  !real(dp) :: fac
     488              :  character(len=1000) :: msg
     489              : !arrays
     490           68 :  complex(dpc) :: idty(ndim,ndim)
     491           34 :  integer :: indexat(ndim),indexdir(ndim)
     492           34 :  integer, allocatable :: ipiv(:)
     493           34 :  complex(dpc),allocatable :: work(:),work1(:,:),work2(:,:)
     494              :  character(len=1) :: cart(3)=(/'x','y','z'/)
     495              : 
     496              : ! *********************************************************************
     497              : 
     498              : !If fixed-spin case has been precalculated do less stuff
     499           34 :  fs2rs_=0; if (present(fs2rs)) fs2rs_=fs2rs
     500           30 :  if (fs2rs_==1) then
     501           30 :    if (.not.present(blkval_fs)) then
     502            0 :      write(msg, '(3a)' )' No fixed-spin array has been passed to local_spinsus', &
     503            0 :    & ' but fs2rs=1 ',ch10
     504            0 :      ABI_ERROR(msg)
     505              :    end if
     506              :  end if
     507              : 
     508              : !Extract the penalized susceptibility
     509          714 :  idty=(zero,zero)
     510           34 :  ipert2_red= 0
     511          102 :  do iat2= mpatpol(1), mpatpol(2)
     512           68 :    ipert2= natom + 11 + iat2
     513           68 :    ipert2_red= ipert2_red + 1
     514           68 :    idir2_red= 0
     515          306 :    do idir2= 1, 3
     516          204 :      if (mpdir(idir2)==0) cycle
     517          136 :      idir2_red= idir2_red + 1
     518          136 :      icol=idir2_red+(ipert2_red-1)*nmdir
     519          136 :      indexat(icol)=iat2
     520          136 :      indexdir(icol)=idir2
     521          136 :      idty(icol,icol)=(one,zero)
     522          136 :      ipert1_red=0
     523          476 :      do iat1= mpatpol(1), mpatpol(2)
     524          272 :        ipert1= natom + 11 + iat1
     525          272 :        ipert1_red= ipert1_red + 1
     526          272 :        idir1_red= 0
     527         1292 :        do idir1= 1, 3
     528          816 :          if (mpdir(idir1)==0) cycle
     529          544 :          idir1_red=idir1_red+1
     530          544 :          irow=idir1_red+(ipert1_red-1)*nmdir
     531          544 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
     532              : 
     533              :          !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
     534              :          !displacements at finite q (See M. Stengel PRB 2013).
     535          816 :          if (fs2rs_==0) then
     536              :            barmagsus(irow,icol)= &
     537              :          & cmplx(ddb%val(1,index,iblok),ddb%val(2,index,iblok),kind=dpc) &
     538          256 :          & * exp(two_pi*(0.d0,1.d0)*dot_product(qphon,xred(:,iat1)-xred(:,iat2)))
     539          480 :          else if (fs2rs_==1) then
     540              :            invmagsus(irow,icol)= &
     541              :          & cmplx(blkval_fs(1,idir1,ipert1,idir2,ipert2,iblok), &
     542          480 :          & blkval_fs(2,idir1,ipert1,idir2,ipert2,iblok),kind=dpc)
     543              :          end if
     544              : 
     545              :        end do
     546              :      end do
     547              :    end do
     548              :  end do
     549              : 
     550              : !Use magsus to store the intermediate array
     551          714 :  magsus=idty-magpen*barmagsus
     552              : 
     553              : !Invert the arrays
     554          136 :  ABI_MALLOC(work1,(ndim,ndim))
     555          102 :  ABI_MALLOC(work2,(ndim,ndim))
     556           34 :  if (fs2rs_==0) then
     557           88 :    work1=barmagsus
     558           30 :  else if (fs2rs_==1) then
     559          660 :    work1=invmagsus
     560              :  end if
     561          748 :  work2=magsus
     562              : 
     563          102 :  ABI_MALLOC(ipiv,(ndim))
     564           34 :  call zgetrf( ndim, ndim, work1, ndim, ipiv, info )
     565           34 :  ABI_CHECK(info == 0, sjoin('zgetrf returned:', itoa(info)))
     566              : 
     567           34 :  ABI_MALLOC(work,(2))
     568           34 :  call zgetri( ndim, work1, ndim, ipiv, work, -1, info )
     569           34 :  ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
     570           34 :  lwork=int(work(1))
     571              : 
     572          102 :  ABI_REMALLOC(work,(lwork))
     573           34 :  call zgetri( ndim, work1, ndim, ipiv, work, lwork, info )
     574           34 :  ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
     575              : 
     576           34 :  if (fs2rs_==1) then
     577          630 :    magsus=work1
     578           30 :    ABI_SFREE(ipiv)
     579           30 :    ABI_SFREE(work1)
     580           30 :    ABI_SFREE(work2)
     581           30 :    ABI_SFREE(work)
     582           30 :    return
     583              :  end if
     584              : 
     585            4 :  call zgetrf( ndim, ndim, work2, ndim, ipiv, info )
     586            4 :  ABI_CHECK(info == 0, sjoin('zgetrf returned:', itoa(info)))
     587              : 
     588            4 :  call zgetri( ndim, work2, ndim, ipiv, work, -1, info )
     589            4 :  ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
     590            4 :  lwork=int(work(1))
     591              : 
     592           12 :  ABI_REMALLOC(work,(lwork))
     593            4 :  call zgetri( ndim, work2, ndim, ipiv, work, lwork, info )
     594            4 :  ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
     595            4 :  ABI_FREE(work)
     596              : 
     597              :  !Write the results in meaningfull arrays
     598           84 :  invbarmagsus=work1
     599              : 
     600              :  !At last, calculate the susceptibility and its inverse
     601           84 :  invhmat=work2
     602          420 :  magsus=matmul(work2,barmagsus)
     603           84 :  invmagsus=invbarmagsus-magpen*idty
     604              : 
     605            4 :  ABI_FREE(ipiv)
     606            4 :  ABI_FREE(work1)
     607            4 :  ABI_FREE(work2)
     608              : 
     609            4 :  if (prtopt==1.and.prtvol>1) then
     610              : 
     611              :    !Write results in output
     612            4 :    if (magpen > zero) then
     613           12 :      call wrtout([ab_out,std_out], ' Local spin susceptibility ')
     614           12 :      call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     615           20 :      do irow=1, ndim
     616           84 :        do icol=1, ndim
     617              :          write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     618           64 :        & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
     619          128 :        & real(magsus(irow,icol)), aimag(magsus(irow,icol))
     620          208 :          call wrtout([ab_out,std_out], msg)
     621              :        end do
     622              :      end do
     623           12 :      call wrtout([ab_out,std_out], '   ')
     624              : 
     625           12 :      call wrtout([ab_out,std_out], ' Inverse of local spin susceptibility ')
     626           12 :      call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     627           20 :      do irow=1, ndim
     628           84 :        do icol=1, ndim
     629              :          write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     630           64 :        & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
     631          128 :        & real(invmagsus(irow,icol)), aimag(invmagsus(irow,icol))
     632          208 :          call wrtout([ab_out,std_out], msg)
     633              :        end do
     634              :      end do
     635           12 :      call wrtout([ab_out,std_out], '   ')
     636              : 
     637            4 :      if (prtvol > 2) then
     638           12 :        call wrtout([ab_out,std_out], ' Penalized local spin susceptibility ')
     639           12 :        call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     640           20 :        do irow=1, ndim
     641           84 :          do icol=1, ndim
     642              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     643           64 :          & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
     644          128 :          & real(barmagsus(irow,icol)), aimag(barmagsus(irow,icol))
     645          208 :            call wrtout([ab_out,std_out], msg)
     646              :          end do
     647              :        end do
     648           12 :        call wrtout([ab_out,std_out], '   ')
     649              : 
     650           12 :        call wrtout([ab_out,std_out], ' Inverse of penalized local spin susceptibility ')
     651           12 :        call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     652           20 :        do irow=1, ndim
     653           84 :          do icol=1, ndim
     654              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     655           64 :          & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
     656          128 :          & real(invbarmagsus(irow,icol)), aimag(invbarmagsus(irow,icol))
     657          208 :            call wrtout([ab_out,std_out], msg)
     658              :          end do
     659              :        end do
     660           12 :        call wrtout([ab_out,std_out], '   ')
     661              : 
     662           12 :        call wrtout([ab_out,std_out], ' Inverse of H matrix (I-alpha barchi)^{-1} ')
     663           12 :        call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     664           20 :        do irow=1, ndim
     665           84 :          do icol=1, ndim
     666              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     667           64 :          & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
     668          128 :          & real(invhmat(irow,icol)), aimag(invhmat(irow,icol))
     669          208 :            call wrtout([ab_out,std_out], msg)
     670              :          end do
     671              :        end do
     672           12 :        call wrtout([ab_out,std_out], '   ')
     673              :      end if
     674              : 
     675              :    end if !magpen>zero
     676              : 
     677              :  end if !prtopt
     678              : 
     679              : !Store the FS and RS flavors on the DDB array
     680              :  ipert2_red= 0
     681           12 :  do iat2= mpatpol(1), mpatpol(2)
     682            8 :    ipert2= natom + 11 + iat2
     683            8 :    ipert2_red= ipert2_red + 1
     684            8 :    idir2_red= 0
     685           36 :    do idir2= 1, 3
     686           24 :      if (mpdir(idir2)==0) cycle
     687           16 :      idir2_red= idir2_red + 1
     688           16 :      icol=idir2_red+(ipert2_red-1)*nmdir
     689           16 :      ipert1_red=0
     690           56 :      do iat1= mpatpol(1), mpatpol(2)
     691           32 :        ipert1= natom + 11 + iat1
     692           32 :        ipert1_red= ipert1_red + 1
     693           32 :        idir1_red= 0
     694          152 :        do idir1= 1, 3
     695           96 :          if (mpdir(idir1)==0) cycle
     696           64 :          idir1_red=idir1_red+1
     697           64 :          irow=idir1_red+(ipert1_red-1)*nmdir
     698           64 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
     699              : 
     700           64 :          ddb%val_fs(1,index,iblok)=real(invmagsus(irow,icol))
     701           64 :          ddb%val_fs(2,index,iblok)=aimag(invmagsus(irow,icol))
     702              : 
     703           64 :          ddb%val_rs(1,index,iblok)=real(magsus(irow,icol))
     704          128 :          ddb%val_rs(2,index,iblok)=aimag(magsus(irow,icol))
     705              : 
     706              :        end do
     707              :      end do
     708              :    end do
     709              :  end do
     710              : 
     711           64 :  end subroutine local_spinsus
     712              : !!***
     713              : 
     714              : !!****f* m_ddb_magpen/magmom
     715              : !! NAME
     716              : !! magmom
     717              : !!
     718              : !! FUNCTION
     719              : !! Calculate the first-order magnetic moments and the constrained
     720              : !! Zeeman fields
     721              : !!
     722              : !! INPUTS
     723              : !! ddb=  Second-order derivative arrais
     724              : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
     725              : !! iblok= index of the atomic displacement block
     726              : !! jblok= index of the electric field block
     727              : !! magsus(ndim,ndim)= Spin-sussceptibility tensor
     728              : !! magpen = amplitude (in Ha) of the applied magnetic penalty
     729              : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
     730              : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
     731              : !! mpert =maximum number of ipert
     732              : !! natom= number of atoms in unit cell
     733              : !! nblok= number of blocks in the DDB
     734              : !! nmdir= number of directions along which the magnetic penalty was applied
     735              : !! ndim= dimension of the square susceptibilities
     736              : !! prtvol= control the volume of information written on output
     737              : !! fs2rs= (optional) if 1, the routine starts from a precalculated blkval_fs
     738              : !! blkval_fs(2,3,mpert,3,mpert)= fixed-spin 2nd-order derivatives
     739              : !!
     740              : !! OUTPUT
     741              : !! barmmom(ndim,(natom+2)*3)= penalized first order magnetic moments on the atoms and
     742              : !!  directions of the penalty induced by atomic displacements and/or electric fields.
     743              : !! mmom(ndim,(natom+2)*3)= first order magnetic moments on the atoms and
     744              : !!  directions of the penalty induced by atomic displacements and/or electric fields.
     745              : !! zfield(ndim,(natom+2)*3)= Zeeman fields at constrained magnetic moments.
     746              : !!
     747              : !! SOURCE
     748              : 
     749           68 :  subroutine magmom(barmmom,barmmom_tr,ddb,invbarmagsus,invhmat,iblok,jblok,lblok,magpen,magsus,mmom,mmom_tr,&
     750           34 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qphon,xred,zfield,zfield_tr, &
     751           30 : & fs2rs,blkval_fs) !optional
     752              : 
     753              : !Arguments -------------------------------
     754              : !scalars
     755              :  integer,intent(in) :: iblok,jblok,lblok,mpert,natom,ndim,nmdir,prtopt,prtvol
     756              :  integer,intent(in),optional :: fs2rs
     757              :  real(dp),intent(in) :: magpen
     758              : !arrays
     759              :  type(ddb_type),intent(inout) :: ddb
     760              :  real(dp),intent(in) :: qphon(3),xred(3,natom)
     761              :  integer,intent(in) :: mpatpol(2),mpdir(3)
     762              :  real(dp),intent(in),optional :: blkval_fs(2,3,mpert,3,mpert,1)
     763              :  complex(dpc),intent(out) :: barmmom(ndim,(natom+5)*3)
     764              :  complex(dpc),intent(out) :: barmmom_tr((natom+5)*3,ndim)
     765              :  complex(dpc),intent(in) :: invbarmagsus(ndim,ndim)
     766              :  complex(dpc),intent(in) :: invhmat(ndim,ndim)
     767              :  complex(dpc),intent(in) :: magsus(ndim,ndim)
     768              :  complex(dpc),intent(out) :: mmom(ndim,(natom+5)*3)
     769              :  complex(dpc),intent(out) :: mmom_tr((natom+5)*3,ndim)
     770              :  complex(dpc),intent(out) :: zfield(ndim,(natom+5)*3)
     771              :  complex(dpc),intent(out) :: zfield_tr((natom+5)*3,ndim)
     772              : !Local variables -------------------------
     773              : !scalars
     774              :  integer :: fs2rs_
     775              :  integer :: iat1,icol,idir1,idir2,index,ipert1,ipert2,irow
     776              :  integer :: ipert1_red,idir1_red,jndex,zblok
     777              :  complex(dpc) :: qfac, qfac_tr
     778              :  character(len=1000) :: msg
     779              : !arrays
     780           68 :  integer :: indexat1(ndim),indexdir1(ndim)
     781           68 :  integer :: indexat2((natom+5)*3),indexdir2((natom+5)*3)
     782           34 :  complex(dpc) :: mmom_alt(ndim,(natom+5)*3)
     783              :  character(len=1) :: cart(3)=(/'x','y','z'/)
     784              : 
     785              : ! *********************************************************************
     786              : 
     787              : !If fixed-spin case has been precalculated do less stuff
     788           34 :  fs2rs_=0; if (present(fs2rs)) fs2rs_=fs2rs
     789           30 :  if (fs2rs_==1) then
     790           30 :    if (.not.present(blkval_fs)) then
     791            0 :      write(msg, '(3a)' )' No fixed-spin array has been passed to magmom', &
     792            0 :    & ' but fs2rs=1 ',ch10
     793            0 :      ABI_ERROR(msg)
     794              :    end if
     795              :  end if
     796              : 
     797              : !Extract the penalized moments
     798          408 :  do ipert2=1,natom+5
     799              :    !exclude strain perturbation
     800          374 :    if (ipert2==natom+3.or.ipert2==natom+4) cycle
     801         1258 :    do idir2=1,3
     802          918 :      icol=idir2+(ipert2-1)*3
     803          918 :      indexat2(icol)=ipert2
     804          918 :      indexdir2(icol)=idir2
     805              : 
     806          918 :      ipert1_red= 0
     807         3128 :      do iat1= mpatpol(1), mpatpol(2)
     808         1836 :        ipert1= natom + 11 + iat1
     809         1836 :        ipert1_red= ipert1_red + 1
     810         1836 :        idir1_red= 0
     811              : 
     812              :        !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
     813              :        !displacements at finite q (See M. Stengel PRB 2013).
     814         7344 :        qfac= exp(two_pi*(0.d0,1.d0)* dot_product(qphon,xred(:,iat1)))
     815         7344 :        qfac_tr= exp(-two_pi*(0.d0,1.d0)* dot_product(qphon,xred(:,iat1)))
     816         8262 :        do idir1= 1, 3
     817         5508 :          if (mpdir(idir1)==0) cycle
     818         3672 :          idir1_red= idir1_red + 1
     819         3672 :          irow=idir1_red+(ipert1_red-1)*nmdir
     820         3672 :          indexat1(irow)=iat1
     821         3672 :          indexdir1(irow)=idir1
     822         3672 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
     823         3672 :          jndex= idir2 + 3*((ipert2-1)+mpert*((idir1-1)+3*(ipert1-1)))
     824              : 
     825         5508 :          if (fs2rs_==0) then
     826          432 :            if (iblok /=0 .and. ipert2 <= natom) then
     827          288 :              barmmom(irow,icol)= cmplx(ddb%val(1,index,iblok),ddb%val(2,index,iblok),kind=dpc) * qfac
     828          288 :              barmmom_tr(icol,irow)= cmplx(ddb%val(1,jndex,iblok),ddb%val(2,jndex,iblok),kind=dpc) * qfac_tr
     829          144 :            else if (jblok /=0 .and. ipert2 == natom+2) then
     830           36 :              barmmom(irow,icol)= cmplx(ddb%val(1,index,jblok),ddb%val(2,index,jblok),kind=dpc)
     831           36 :              barmmom_tr(icol,irow)= cmplx(ddb%val(1,jndex,jblok),ddb%val(2,jndex,jblok),kind=dpc)
     832          108 :            else if (lblok /=0 .and. ipert2 == natom+5) then
     833           48 :              barmmom(irow,icol)= cmplx(ddb%val(1,index,lblok),ddb%val(2,index,lblok),kind=dpc) * qfac
     834           48 :              barmmom_tr(icol,irow)= cmplx(ddb%val(1,jndex,lblok),ddb%val(2,jndex,lblok),kind=dpc) * qfac_tr
     835              :            end if
     836         3240 :          else if (fs2rs_==1) then
     837              :            zfield(irow,icol)= &
     838              :          & cmplx(blkval_fs(1,idir1,ipert1,idir2,ipert2,iblok), &
     839         3240 :          & blkval_fs(2,idir1,ipert1,idir2,ipert2,iblok),kind=dpc)
     840              :            zfield_tr(icol,irow)= &
     841              :          & cmplx(blkval_fs(1,idir2,ipert2,idir1,ipert1,iblok), &
     842         3240 :          & blkval_fs(2,idir2,ipert2,idir1,ipert1,iblok),kind=dpc)
     843              :          end if
     844              : 
     845              :        end do
     846              :      end do
     847              :    end do
     848              :  end do
     849              : 
     850              : !Compute the Zeeman fields
     851           34 :  if (fs2rs_==0) then
     852         4112 :    zfield=-matmul(invbarmagsus,barmmom)
     853         3300 :    zfield_tr=-matmul(barmmom_tr,invbarmagsus)
     854              :  end if
     855              : 
     856              : !Compute the moments
     857              :  if (fs2rs_==0) then
     858         4112 :    mmom=-matmul(magsus,zfield)
     859         3436 :    mmom_alt=matmul(invhmat,barmmom)
     860         2740 :    mmom_tr=matmul(barmmom_tr,invhmat)
     861           30 :  else if (fs2rs_==1) then
     862        30840 :    mmom=-matmul(magsus,zfield)
     863        24750 :    mmom_tr=-matmul(zfield_tr,magsus)
     864              :    return
     865              :  end if
     866              : 
     867            4 :  if (prtopt==1.and.prtvol>1) then
     868              : 
     869              :   !Write the results
     870            4 :    if (magpen > zero) then
     871              : 
     872              :      !Atomic displacements
     873            4 :      if (iblok /= 0) then
     874           12 :        call wrtout([ab_out,std_out], ' Local Zeeman fields induced by atomic displacements (at constrained magnetic moments)')
     875           12 :        call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     876           20 :        do irow=1, ndim
     877          308 :          do icol=1, natom*3
     878              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     879          288 :          & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
     880          576 :          & real(zfield(irow,icol)), aimag(zfield(irow,icol))
     881          880 :            call wrtout([ab_out,std_out], msg)
     882              :          end do
     883              :        end do
     884           12 :        call wrtout([ab_out,std_out], '   ')
     885              : 
     886           12 :        call wrtout([ab_out,std_out], ' Local magnetic moments induced by atomic displacements (from induced Zeeman fields)')
     887           12 :        call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     888           20 :        do irow=1, ndim
     889          308 :          do icol=1, natom*3
     890              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     891          288 :          & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
     892          576 :          & real(mmom(irow,icol)), aimag(mmom(irow,icol))
     893          880 :            call wrtout([ab_out,std_out], msg)
     894              :          end do
     895              :        end do
     896           12 :        call wrtout([ab_out,std_out], '   ')
     897              : 
     898           12 :        call wrtout([ab_out,std_out], ' Local magnetic moments induced by atomic displacements (from induced penalized moments)')
     899           12 :        call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     900           20 :        do irow=1, ndim
     901          308 :          do icol=1, natom*3
     902              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     903          288 :          & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
     904          576 :          & real(mmom_alt(irow,icol)), aimag(mmom_alt(irow,icol))
     905          880 :            call wrtout([ab_out,std_out], msg)
     906              :          end do
     907              :        end do
     908           12 :        call wrtout([ab_out,std_out], '   ')
     909              :      end if
     910              : 
     911              :      !Electric field
     912            4 :      if (jblok /= 0) then
     913            9 :        call wrtout([ab_out,std_out], ' Local Zeeman fields induced by electric field (at constrained magnetic moments)')
     914            9 :        call wrtout([ab_out,std_out], '  atom1  dir  E-dir            Real              Imag')
     915           15 :        do irow=1, ndim
     916           51 :          do icol=(natom+1)*3+1, (natom+2)*3
     917              :            write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
     918           36 :          & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
     919           72 :          & real(zfield(irow,icol)), aimag(zfield(irow,icol))
     920          120 :            call wrtout([ab_out,std_out], msg)
     921              :          end do
     922              :        end do
     923            9 :        call wrtout([ab_out,std_out], '   ')
     924            9 :        call wrtout([ab_out,std_out], ' Local magnetic moments induced by electric field (from induced Zeeman fields)')
     925            9 :        call wrtout([ab_out,std_out], '  atom1  dir  E-dir            Real              Imag')
     926           15 :        do irow=1, ndim
     927           51 :          do icol=(natom+1)*3+1, (natom+2)*3
     928              :            write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
     929           36 :          & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
     930           72 :          & real(mmom(irow,icol)), aimag(mmom(irow,icol))
     931          120 :            call wrtout([ab_out,std_out], msg)
     932              :          end do
     933              :        end do
     934            9 :        call wrtout([ab_out,std_out], '   ')
     935            9 :        call wrtout([ab_out,std_out], ' Local magnetic moments induced by electric field (from induced penalized moments)')
     936            9 :        call wrtout([ab_out,std_out], '  atom1  dir  E-dir            Real              Imag')
     937           15 :        do irow=1, ndim
     938           51 :          do icol=(natom+1)*3+1, (natom+2)*3
     939              :            write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
     940           36 :          & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
     941           72 :          & real(mmom_alt(irow,icol)), aimag(mmom_alt(irow,icol))
     942          120 :            call wrtout([ab_out,std_out], msg)
     943              :          end do
     944              :        end do
     945            9 :        call wrtout([ab_out,std_out], '   ')
     946              :      end if
     947              : 
     948              :      !Macroscopic Zeeman
     949            4 :      if (lblok /= 0) then
     950           12 :        call wrtout([ab_out,std_out], ' Local Zeeman fields induced by macroscopic Zeeman field (at constrained magnetic moments)')
     951           12 :        call wrtout([ab_out,std_out], '  atom1  dir  B-dir            Real              Imag')
     952           20 :        do irow=1, ndim
     953           68 :          do icol=(natom+4)*3+1, (natom+5)*3
     954              :            write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
     955           48 :          & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
     956           96 :          & real(zfield(irow,icol)), aimag(zfield(irow,icol))
     957          160 :            call wrtout([ab_out,std_out], msg)
     958              :          end do
     959              :        end do
     960           12 :        call wrtout([ab_out,std_out], '   ')
     961           12 :        call wrtout([ab_out,std_out], ' Local magnetic moments induced by macroscopic Zeeman field (from induced Zeeman fields)')
     962           12 :        call wrtout([ab_out,std_out], '  atom1  dir  B-dir            Real              Imag')
     963           20 :        do irow=1, ndim
     964           68 :          do icol=(natom+4)*3+1, (natom+5)*3
     965              :            write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
     966           48 :          & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
     967           96 :          & real(mmom(irow,icol)), aimag(mmom(irow,icol))
     968          160 :            call wrtout([ab_out,std_out], msg)
     969              :          end do
     970              :        end do
     971           12 :        call wrtout([ab_out,std_out], '   ')
     972           12 :        call wrtout([ab_out,std_out], ' Local magnetic moments induced by macroscopic Zeeman field (from induced penalized moments)')
     973           12 :        call wrtout([ab_out,std_out], '  atom1  dir  B-dir            Real              Imag')
     974           20 :        do irow=1, ndim
     975           68 :          do icol=(natom+4)*3+1, (natom+5)*3
     976              :            write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
     977           48 :          & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
     978           96 :          & real(mmom_alt(irow,icol)), aimag(mmom_alt(irow,icol))
     979          160 :            call wrtout([ab_out,std_out], msg)
     980              :          end do
     981              :        end do
     982           12 :        call wrtout([ab_out,std_out], '   ')
     983              :      end if
     984              : 
     985            4 :      if (prtvol > 2) then
     986            4 :        if (iblok /= 0) then
     987           12 :          call wrtout([ab_out,std_out], ' Penalized local magnetic moments induced by atomic displacements ')
     988           12 :          call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
     989           20 :          do irow=1, ndim
     990          308 :            do icol=1, natom*3
     991              :              write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
     992          288 :            & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
     993          576 :            & real(barmmom(irow,icol)), aimag(barmmom(irow,icol))
     994          880 :              call wrtout([ab_out,std_out], msg)
     995              :            end do
     996              :          end do
     997           12 :          call wrtout([ab_out,std_out], '   ')
     998              :        end if
     999            4 :        if (jblok /= 0) then
    1000            9 :          call wrtout([ab_out,std_out], ' Penalized local magnetic moments induced by electric field ')
    1001            9 :          call wrtout([ab_out,std_out], '  atom1  dir  E-dir            Real              Imag')
    1002           15 :          do irow=1, ndim
    1003           51 :            do icol=(natom+1)*3+1, (natom+2)*3
    1004              :              write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
    1005           36 :            & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
    1006           72 :            & real(barmmom(irow,icol)), aimag(barmmom(irow,icol))
    1007          120 :              call wrtout([ab_out,std_out], msg)
    1008              :            end do
    1009              :          end do
    1010            9 :          call wrtout([ab_out,std_out], '   ')
    1011              :        end if
    1012            4 :        if (lblok /= 0) then
    1013           12 :          call wrtout([ab_out,std_out], ' Penalized local magnetic moments induced by macroscopic Zeeman field ')
    1014           12 :          call wrtout([ab_out,std_out], '  atom1  dir  B-dir            Real              Imag')
    1015           20 :          do irow=1, ndim
    1016           68 :            do icol=(natom+4)*3+1, (natom+5)*3
    1017              :              write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
    1018           48 :            & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
    1019           96 :            & real(barmmom(irow,icol)), aimag(barmmom(irow,icol))
    1020          160 :              call wrtout([ab_out,std_out], msg)
    1021              :            end do
    1022              :          end do
    1023           12 :          call wrtout([ab_out,std_out], '   ')
    1024              :        end if
    1025              :      end if
    1026              :    end if
    1027              :  end if
    1028              : 
    1029              : !Store the FS and RS flavors on the DDB array
    1030           48 :  do ipert2=1,natom+5
    1031          180 :    do idir2=1,3
    1032          132 :      icol=idir2+(ipert2-1)*3
    1033          132 :      indexat2(icol)=ipert2
    1034          132 :      indexdir2(icol)=idir2
    1035              : 
    1036          132 :      ipert1_red= 0
    1037          440 :      do iat1= mpatpol(1), mpatpol(2)
    1038          264 :        ipert1= natom + 11 + iat1
    1039          264 :        ipert1_red= ipert1_red + 1
    1040          264 :        idir1_red= 0
    1041         1188 :        do idir1= 1, 3
    1042          792 :          if (mpdir(idir1)==0) cycle
    1043          528 :          idir1_red= idir1_red + 1
    1044          528 :          irow=idir1_red+(ipert1_red-1)*nmdir
    1045          528 :          indexat1(irow)=iat1
    1046          528 :          indexdir1(irow)=idir1
    1047          528 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1048          528 :          jndex= idir2 + 3*((ipert2-1)+mpert*((idir1-1)+3*(ipert1-1)))
    1049              : 
    1050          528 :          zblok= 0
    1051          528 :          if (iblok /=0 .and. ipert2 <= natom) zblok= iblok
    1052          528 :          if (jblok /=0 .and. ipert2 == natom+2) zblok= jblok
    1053          528 :          if (lblok /=0 .and. ipert2 == natom+5) zblok= lblok
    1054          792 :          if (zblok /= 0) then
    1055          372 :            ddb%val_fs(1,index,zblok)=real(zfield(irow,icol))
    1056          372 :            ddb%val_fs(2,index,zblok)=aimag(zfield(irow,icol))
    1057          372 :            ddb%val_fs(1,jndex,zblok)=real(zfield_tr(icol,irow))
    1058          372 :            ddb%val_fs(2,jndex,zblok)=aimag(zfield_tr(icol,irow))
    1059              : 
    1060          372 :            ddb%val_rs(1,index,zblok)=real(mmom(irow,icol))
    1061          372 :            ddb%val_rs(2,index,zblok)=aimag(mmom(irow,icol))
    1062          372 :            ddb%val_rs(1,jndex,zblok)=real(mmom_tr(icol,irow))
    1063          372 :            ddb%val_rs(2,jndex,zblok)=aimag(mmom_tr(icol,irow))
    1064              :          end if
    1065              : 
    1066              :        end do
    1067              :      end do
    1068              :    end do
    1069              :  end do
    1070              : 
    1071           34 :  end subroutine magmom
    1072              : !!***
    1073              : 
    1074              : !!****f* m_ddb_magpen/mp_d2etot
    1075              : !! NAME
    1076              : !! mp_d2etot
    1077              : !!
    1078              : !! FUNCTION
    1079              : !! Calculate the different magnetic flavors (see mpopt below) of the second-
    1080              : !! order derivatives of total energy
    1081              : !!
    1082              : !! INPUTS
    1083              : !! barmagsus(ndim,ndim)= Penalized spin-sussceptibility tensor (\bar{\chi})
    1084              : !! (equal to barmom^{\dagger} in the nondissipative regime)
    1085              : !! ddb= the ddb object
    1086              : !! iblok= index of the IFCs block
    1087              : !! invhmat(ndim,ndim)= (I-\alpha\bar{\chi})^-1 matrix
    1088              : !! magsus(ndim,ndim)= Spin-sussceptibility tensor
    1089              : !! magpen= magnetic penalty amplitude
    1090              : !! mpert =maximum number of ipert
    1091              : !! mpopt = 1 calculate the frozen-spin second-order quantities
    1092              : !!         2 calculate the relaxed-spin second-order quantities
    1093              : !! natom= number of atoms in unit cell
    1094              : !! nblok= number of blocks in the DDB
    1095              : !! ndim= number of local magnetic degres of freedom
    1096              : !! qphon= momentum wave-vector
    1097              : !! xred(3,natom)= reduced atomic coordinates
    1098              : !! zfield(ndim,(natom+2)*3)= First-order induced Zeeman fields
    1099              : !! zfield_tr(natom+2)*3,ndim)= Linear-responses to external Zeeman fields
    1100              : !! (equal to zfield^{\dagger} in the nondissipative regime)
    1101              : !! fs2rs= (optional) if 1, the routine starts from a precalculated blkval_fs
    1102              : !! blkval_fs(2,3,mpert,3,mpert,1)= fixed-spin 2nd-order derivatives
    1103              : !!
    1104              : !! OUTPUT
    1105              : !! ddb%val_fs(2,msize,nblok)= second-order derivatives at fixed spin.
    1106              : !! ddb%val_rs(2,msize,nblok)= second-order derivatives at relaxed spin.
    1107              : !! blkval_rs(2,3,mpert,3,mpert,1)= (optional) relaxed-spin 2nd-order derivatives
    1108              : !!
    1109              : !! SOURCE
    1110              : 
    1111           68 :  subroutine mp_d2etot(barmagsus,ddb,&
    1112           34 : & iblok,magsus,mpert,mpopt,&
    1113           34 : & natom,ndim,zfield,zfield_tr,&
    1114           60 : & fs2rs,blkval_fs,blkval_rs) !optional
    1115              : 
    1116              : !Arguments -------------------------------
    1117              : !scalars
    1118              :  integer,intent(in) :: iblok,mpert,mpopt,natom,ndim
    1119              :  integer,intent(in),optional :: fs2rs
    1120              : ! real(dp),intent(in) :: magpen
    1121              : !arrays
    1122              :  type(ddb_type),intent(inout) :: ddb
    1123              :  real(dp),intent(in),optional :: blkval_fs(2,3,mpert,3,mpert,1)
    1124              :  real(dp),intent(out),optional :: blkval_rs(2,3,mpert,3,mpert,1)
    1125              :  complex(dpc),intent(in) :: barmagsus(ndim,ndim)
    1126              : ! complex(dpc),intent(in) :: invhmat(ndim,ndim)
    1127              :  complex(dpc),intent(in) :: magsus(ndim,ndim)
    1128              :  complex(dpc),intent(in) :: zfield(ndim,(natom+5)*3)
    1129              :  complex(dpc),intent(in) :: zfield_tr((natom+5)*3,ndim)
    1130              : !Local variables -------------------------
    1131              : !scalars
    1132              :  integer :: fs2rs_
    1133              :  integer :: idir1,idir2,ipert1,ipert2,index,irow,icol
    1134              :  complex(dpc) :: val_ps,val_fs, val_rs
    1135              :  character(len=1000) :: msg
    1136              : !arrays
    1137              : 
    1138              : ! *********************************************************************
    1139              : 
    1140              : !If fixed-spin case has been precalculated do less stuff
    1141           34 :  fs2rs_=0; if (present(fs2rs)) fs2rs_=fs2rs
    1142           30 :  if (fs2rs_==1) then
    1143           30 :    if (.not.present(blkval_fs)) then
    1144            0 :      write(msg, '(3a)' )' No fixed-spin array has been passed to mp_d2etot', &
    1145            0 :    & ' but fs2rs=1 ',ch10
    1146            0 :      ABI_ERROR(msg)
    1147              :    end if
    1148           30 :    if (.not.present(blkval_rs)) then
    1149            0 :      write(msg, '(3a)' )' No relaxed-spin array has been passed to mp_d2etot', &
    1150            0 :    & ' but fs2rs=1 ',ch10
    1151            0 :      ABI_ERROR(msg)
    1152              :    end if
    1153              :  end if
    1154              : 
    1155              : !Extract the penalized/constrained quantities
    1156          408 :  do ipert2= 1, natom+5
    1157         1530 :    do idir2= 1, 3
    1158         1122 :      icol= (ipert2-1)*3 + idir2
    1159        13838 :      do ipert1= 1, natom+5
    1160        50490 :        do idir1= 1, 3
    1161        37026 :          irow= (ipert1-1)*3 + idir1
    1162        37026 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1163              : 
    1164        37026 :          if (fs2rs_==0) then
    1165              :            !Extract the penalized second-order derivatives
    1166         4356 :            val_ps= cmplx(ddb%val(1,index,iblok),ddb%val(2,index,iblok),kind=dpc)
    1167              :            !Calculate the fixed-spin flavor
    1168              :            val_fs= val_ps + &
    1169       139392 :          & sum( zfield_tr(irow,:) * matmul( barmagsus,zfield(:,icol) ) )
    1170         4356 :            ddb%val_fs(1,index,iblok)= real(val_fs)
    1171         4356 :            ddb%val_fs(2,index,iblok)= aimag(val_fs)
    1172        32670 :          else if (fs2rs_==1) then
    1173              :            val_fs= &
    1174              :          & cmplx(blkval_fs(1,idir1,ipert1,idir2,ipert2,iblok), &
    1175        32670 :          & blkval_fs(2,idir1,ipert1,idir2,ipert2,iblok),kind=dpc)
    1176              :          end if
    1177              : 
    1178        49368 :          if (mpopt==2) then
    1179              :            !Calculate the relaxed-spin flavor
    1180              :            val_rs= val_fs - &
    1181      1184832 :          & sum( zfield_tr(irow,:) * matmul( magsus,zfield(:,icol) ) )
    1182        37026 :            if (fs2rs_==0) then
    1183         4356 :              ddb%val_rs(1,index,iblok)= real(val_rs)
    1184         4356 :              ddb%val_rs(2,index,iblok)= aimag(val_rs)
    1185        32670 :            else if (fs2rs_==1) then
    1186        32670 :              blkval_rs(1,idir1,ipert1,idir2,ipert2,iblok)=real(val_rs)
    1187        32670 :              blkval_rs(2,idir1,ipert1,idir2,ipert2,iblok)=aimag(val_rs)
    1188              :            end if
    1189              :          end if
    1190              : 
    1191              :        end do
    1192              :      end do
    1193              :    end do
    1194              :  end do
    1195              : 
    1196           64 :  end subroutine mp_d2etot
    1197              : !!***
    1198              : 
    1199              : !!****f* m_ddb_magpen/mp_d2etot_print
    1200              : !! NAME
    1201              : !! mp_d2etot_print
    1202              : !!
    1203              : !! FUNCTION
    1204              : !! Write on output file the fixed- and relaxed-spin susceptibilities
    1205              : !!
    1206              : !! INPUTS
    1207              : !! blkval= 2nd-order susceptibilities matrix
    1208              : !! kblok= index of the current block
    1209              : !! opt= 1 write the frozen-spin second-order quantities
    1210              : !!      2 write the relaxed-spin second-order quantities
    1211              : !! omega= frequency of the perturbation
    1212              : !! qphon= momentum wave-vector
    1213              : !! ucvol= unit-cell volume
    1214              : !!
    1215              : !! OUTPUT
    1216              : !!
    1217              : !! SOURCE
    1218              : 
    1219           16 :  subroutine mp_d2etot_print(ddb,blkval,kblok,mpert,natom,nblok,opt,omega,qeq0,qphnrm,qphon,msize)
    1220              : 
    1221              : !Arguments -------------------------------
    1222              : !scalars
    1223              :  class(ddb_type),intent(in) :: ddb
    1224              :  integer,intent(in) :: kblok,mpert,natom,nblok,opt,msize
    1225              :  logical,intent(in) :: qeq0
    1226              : !arrays
    1227              :  real(dp),intent(in) :: omega(3)
    1228              :  real(dp),intent(in) :: blkval(2,msize,nblok)
    1229              :  real(dp),intent(inout) :: qphnrm(3),qphon(3,3)
    1230              : 
    1231              : !Local variables -------------------------
    1232              : !scalars
    1233              :  integer :: iblok,idir1,idir2,ipert1,ipert2,irow,icol
    1234              :  integer :: rftyp,index
    1235              :  character(len=1000) :: msg
    1236              : !arrays
    1237              :  integer :: rfelfd(4),rfmagn(4),rfphon(4),rfstrs(4)
    1238              :  real(dp) :: val(2)
    1239              :  character(len=1) :: cart(3)=(/'x','y','z'/)
    1240              : 
    1241              : ! *********************************************************************
    1242              : 
    1243            4 :  rfelfd(:)=0
    1244            4 :  rfphon(:)=0
    1245            4 :  rfstrs(:)=0
    1246            4 :  rfmagn(:)=0
    1247            4 :  rftyp = 1
    1248              : 
    1249              :  !IFCs
    1250           12 :  rfphon(1:2)=1
    1251            4 :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
    1252            4 :  if (iblok/=0.and.iblok==kblok) then
    1253            4 :    if (opt==1) then
    1254            0 :      call wrtout([ab_out,std_out], ' Frozen-spin interatomic force constants')
    1255            4 :    else if (opt==2) then
    1256           12 :      call wrtout([ab_out,std_out], ' Relaxed-spin interatomic force constants')
    1257              :    end if
    1258           12 :    call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
    1259           28 :    do ipert1= 1, natom
    1260          100 :      do idir1= 1, 3
    1261           72 :        irow=( ipert1-1)*3 + idir1
    1262          504 :        do ipert2= 1, natom
    1263         1800 :          do idir2= 1, 3
    1264         1296 :            icol=( ipert2-1)*3 + idir2
    1265         1296 :            index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1266         3888 :            val(:)=blkval(:,index,kblok)
    1267              :            write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)') &
    1268         1296 :          & ipert1, cart(idir1), ipert2, cart(idir2), val(1), val(2)
    1269         4320 :            call wrtout([ab_out,std_out], msg)
    1270              :          end do
    1271              :        end do
    1272          240 :        call wrtout([ab_out,std_out], ' ')
    1273              :      end do
    1274              :    end do
    1275              :  end if
    1276              : 
    1277            4 :  if (qeq0) then
    1278              : 
    1279              :    !Born charges
    1280            9 :    rfphon(1:2)=1
    1281            9 :    rfelfd(1:2)=2
    1282            3 :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
    1283            3 :    if (iblok/=0.and.iblok==kblok) then
    1284            3 :      if (opt==1) then
    1285            0 :        call wrtout([ab_out,std_out], ' Frozen-spin Born effective charges')
    1286            3 :      else if (opt==2) then
    1287            9 :        call wrtout([ab_out,std_out], ' Relaxed-spin Born effective charges')
    1288              :      end if
    1289            9 :      call wrtout([ab_out,std_out], ' E-dir      atom   dir        Real              Imag')
    1290            3 :      ipert1= natom + 2
    1291           12 :      do idir1= 1, 3
    1292           63 :        do ipert2= 1, natom
    1293          225 :          do idir2= 1, 3
    1294          162 :            index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1295          486 :            val(:)=blkval(:,index,kblok)
    1296              :            write(msg,'(3x,a2,7x,i3,4x,a2,2x,2es18.9)') &
    1297          162 :          & cart(idir1), ipert2, cart(idir2), val(1), val(2)
    1298          540 :            call wrtout([ab_out,std_out], msg)
    1299              :          end do
    1300              :        end do
    1301           30 :        call wrtout([ab_out,std_out], ' ')
    1302              :      end do
    1303              :    end if
    1304              : 
    1305              :    !Dielectric tensor
    1306              :    iblok=0
    1307            3 :    rfphon(:)=0
    1308            9 :    rfelfd(1:2)=2
    1309            3 :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
    1310            3 :    if (iblok/=0.and.iblok==kblok) then
    1311            3 :      if (opt==1) then
    1312            0 :        call wrtout([ab_out,std_out], ' Frozen-spin clamped-ion dielectric tensor')
    1313            3 :      else if (opt==2) then
    1314            9 :        call wrtout([ab_out,std_out], ' Relaxed-spin clamped-ion dielectric tensor')
    1315              :      end if
    1316            9 :      call wrtout([ab_out,std_out], '  dir  dir        Real              Imag')
    1317            3 :      ipert1= ddb%natom + 2
    1318            3 :      ipert2= ddb%natom + 2
    1319           12 :      do idir2= 1, 3
    1320           36 :        do idir1= 1, 3
    1321           27 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1322           81 :          val(:)=blkval(:,index,kblok)
    1323           27 :          write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    1324           54 :        & val(1), val(2)
    1325           90 :          call wrtout([ab_out,std_out], msg)
    1326              :        end do
    1327           30 :        call wrtout([ab_out,std_out], ' ')
    1328              :      end do
    1329              :    end if
    1330              : 
    1331              :    !Magnetoelectric susceptibility
    1332              :    iblok=0
    1333            3 :    rfphon(:)=0
    1334            3 :    rfelfd(1)=0
    1335            3 :    rfelfd(2)=2
    1336            3 :    rfmagn(1)=1
    1337              :    rfmagn(2)=0
    1338              :    call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    1339            3 :  & rfmagn=rfmagn)
    1340            3 :    if (iblok/=0.and.iblok==kblok) then
    1341            3 :      if (opt==1) then
    1342            0 :        call wrtout([ab_out,std_out], ' Frozen-spin clamped-ion magnetoelectric susceptibility')
    1343            3 :      else if (opt==2) then
    1344            9 :        call wrtout([ab_out,std_out], ' Relaxed-spin clamped-ion magnetoelectric susceptibility')
    1345              :      end if
    1346            9 :      call wrtout([ab_out,std_out], ' M-dir E-dir        Real              Imag')
    1347            3 :      ipert1= ddb%natom + 5
    1348            3 :      ipert2= ddb%natom + 2
    1349           12 :      do idir2= 1, 3
    1350           36 :        do idir1= 1, 3
    1351           27 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1352           81 :          val(:)=blkval(:,index,kblok)
    1353           27 :          write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    1354           54 :        & val(1), val(2)
    1355           90 :          call wrtout([ab_out,std_out], msg)
    1356              :        end do
    1357           30 :        call wrtout([ab_out,std_out], ' ')
    1358              :      end do
    1359            9 :      call wrtout([ab_out,std_out], ' P-dir H-dir        Real              Imag')
    1360            3 :      ipert1= ddb%natom + 2
    1361            3 :      ipert2= ddb%natom + 5
    1362           12 :      do idir2= 1, 3
    1363           36 :        do idir1= 1, 3
    1364           27 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1365           81 :          val(:)=blkval(:,index,kblok)
    1366           27 :          write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    1367           54 :        & val(1), val(2)
    1368           90 :          call wrtout([ab_out,std_out], msg)
    1369              :        end do
    1370           30 :        call wrtout([ab_out,std_out], ' ')
    1371              :      end do
    1372              :    end if
    1373              : 
    1374              :  end if
    1375              : 
    1376              :  !Magnetic susceptibility
    1377              :  iblok=0
    1378            4 :  rfphon(:)=0
    1379            4 :  rfelfd(:)=0
    1380            4 :  rfmagn(1)=1
    1381            4 :  rfmagn(2)=1
    1382              :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    1383            4 : & rfmagn=rfmagn)
    1384            4 :  if (iblok/=0.and.iblok==kblok) then
    1385            4 :    if (opt==1) then
    1386            0 :      call wrtout([ab_out,std_out], ' Frozen-spin clamped-ion magnetic susceptibility')
    1387            4 :    else if (opt==2) then
    1388           12 :      call wrtout([ab_out,std_out], ' Relaxed-spin clamped-ion magnetic susceptibility')
    1389              :    end if
    1390           12 :    call wrtout([ab_out,std_out], '  dir  dir        Real              Imag')
    1391            4 :    ipert1= ddb%natom + 5
    1392            4 :    ipert2= ddb%natom + 5
    1393           16 :    do idir2= 1, 3
    1394           48 :      do idir1= 1, 3
    1395           36 :        index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1396          108 :        val(:)=blkval(:,index,kblok)
    1397           36 :        write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    1398           72 :      & val(1), val(2)
    1399          120 :        call wrtout([ab_out,std_out], msg)
    1400              :      end do
    1401           40 :      call wrtout([ab_out,std_out], ' ')
    1402              :    end do
    1403              :  end if
    1404              : 
    1405              :  !Magnetic Born effective charges
    1406              :  iblok=0
    1407            4 :  rfphon(1)=1
    1408            4 :  rfelfd(:)=0
    1409            4 :  rfmagn(1)=0
    1410              :  rfmagn(2)=1
    1411              :  call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    1412            4 : & rfmagn=rfmagn)
    1413            4 :  if (iblok/=0.and.iblok==kblok) then
    1414            4 :    if (opt==1) then
    1415            0 :      call wrtout([ab_out,std_out], ' Frozen-spin magnetic Born effective charges')
    1416            4 :    else if (opt==2) then
    1417           12 :      call wrtout([ab_out,std_out], ' Relaxed-spin magnetic Born effective charges')
    1418              :    end if
    1419           12 :    call wrtout([ab_out,std_out], ' B-dir      atom   dir        Real              Imag')
    1420              : 
    1421            4 :    ipert1= ddb%natom + 5
    1422           16 :    do idir1= 1, 3
    1423           84 :      do ipert2= 1, natom
    1424          300 :        do idir2= 1, 3
    1425          216 :          index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
    1426          648 :          val(:)=blkval(:,index,kblok)
    1427              :          write(msg,'(3x,a2,7x,i3,4x,a2,2x,2es18.9)') &
    1428          216 :        & cart(idir1), ipert2, cart(idir2), val(1), val(2)
    1429          720 :          call wrtout([ab_out,std_out], msg)
    1430              :        end do
    1431              :      end do
    1432           40 :      call wrtout([ab_out,std_out], ' ')
    1433              :    end do
    1434              :  end if
    1435              : 
    1436            4 :  end subroutine mp_d2etot_print
    1437              : !!***
    1438              : 
    1439              : !!****f* m_ddb_magpen/asrw0
    1440              : !! NAME
    1441              : !! asrw0
    1442              : !!
    1443              : !! FUNCTION
    1444              : !! Impose the Acoustic Sum Rule from the w=0 IFCs
    1445              : !!
    1446              : !! INPUTS
    1447              : !! natom= namber of atoms
    1448              : !! option= if 0, this is the w=0 case, calculate delta_asrw0
    1449              : !          if 1, use the previously calculated delta_asrw0
    1450              : !!
    1451              : !! OUTPUT
    1452              : !! ifcmat(3*natom,3*natom)= IFC matrix after ASR has been applied.
    1453              : !! delta_asrw0(3*natom,3)= Amount to remove in order to enforce ASR.
    1454              : !!
    1455              : !! SOURCE
    1456              : 
    1457            0 :  subroutine asrw0(delta_asrw0,ifcmat,natom,option)
    1458              : 
    1459              : !Arguments -------------------------------
    1460              : !scalars
    1461              :  integer,intent(in) :: natom,option
    1462              : !arrays
    1463              :  real(dp),intent(inout) :: delta_asrw0(3*natom,3)
    1464              :  complex(dpc),intent(inout) :: ifcmat(3*natom,3*natom)
    1465              : !Local variables -------------------------
    1466              : !scalars
    1467              :  integer :: icol,idir1,idir2,ipert1,ipert2,irow
    1468              : !arrays
    1469              : 
    1470              : ! *********************************************************************
    1471              : 
    1472              : !Calculate the ASR correction
    1473            0 :  if (option == 0) then
    1474            0 :    delta_asrw0= zero
    1475            0 :    do idir1= 1, 3
    1476            0 :      do ipert1= 1, natom
    1477            0 :        irow= (ipert1-1)*3 + idir1
    1478            0 :        do idir2= 1, 3
    1479            0 :          do ipert2= 1, natom
    1480            0 :            icol= (ipert2-1)*3 + idir2
    1481              :            delta_asrw0(irow,idir2)=delta_asrw0(irow,idir2) + &
    1482            0 :          & real(ifcmat(irow,icol))
    1483              :          end do
    1484              :        end do
    1485              :      end do
    1486              :    end do
    1487              :  end if
    1488              : 
    1489              : !Apply the ASR
    1490            0 :  do idir1= 1, 3
    1491            0 :    do ipert1= 1, natom
    1492            0 :      irow= (ipert1-1)*3 + idir1
    1493            0 :      do idir2= 1, 3
    1494            0 :        icol= (ipert1-1)*3 + idir2
    1495            0 :        ifcmat(irow,icol)= ifcmat(irow,icol) - delta_asrw0(irow,idir2)
    1496              :      end do
    1497              :    end do
    1498              :  end do
    1499              : 
    1500            0 :  end subroutine asrw0
    1501              : !!***
    1502              : 
    1503              : !!****f* m_ddb_magpen/berrycurv_ss
    1504              : !! NAME
    1505              : !! berrycurv_ss
    1506              : !!
    1507              : !! FUNCTION
    1508              : !! Calculate the Berry curvature of the inverse magnetic susceptibility
    1509              : !! (this is equivalent to the G^(ss) matrix of S.Ren et al.)
    1510              : !!
    1511              : !! INPUTS
    1512              : !! blkval(2,3*mpert*3*mpert*3*mpert,nblok)=  Third-order derivative matrices
    1513              : !!  In our case, the nblok is restricted to iblok
    1514              : !! iblok= index of the current block
    1515              : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
    1516              : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
    1517              : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
    1518              : !! mpert =maximum number of ipert
    1519              : !! natom= number of atoms in unit cell
    1520              : !! nblok= number of blocks in the DDB
    1521              : !! nmdir= number of directions along which the magnetic penalty was applied
    1522              : !! ndim= dimension of the square susceptibilities
    1523              : !! prtvol= control the volume of information written on output
    1524              : !!
    1525              : !! OUTPUT
    1526              : !! bc_ss(ndim,ndim)= Berry-curvature of the inverse local-spin susceptibility
    1527              : !!
    1528              : !! SOURCE
    1529              : 
    1530            2 :  subroutine berrycurv_ss(bc_barmagsus,bc_ss,ddb_lw,iblok,invbarmagsus,&
    1531            2 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtvol,qphon,xred)
    1532              : 
    1533              : !Arguments -------------------------------
    1534              : !scalars
    1535              :  integer,intent(in) :: iblok,mpert,natom,ndim,nmdir,prtvol
    1536              : !arrays
    1537              :  type(ddb_type),intent(inout) :: ddb_lw
    1538              :  integer,intent(in) :: mpatpol(2),mpdir(3)
    1539              :  real(dp),intent(in) :: qphon(3),xred(3,natom)
    1540              :  complex(dpc),intent(in) :: invbarmagsus(ndim,ndim)
    1541              :  complex(dpc),intent(out) :: bc_ss(ndim,ndim)
    1542              :  complex(dpc),intent(out) :: bc_barmagsus(ndim,ndim)
    1543              : !Local variables -------------------------
    1544              : !scalars
    1545              :  integer :: iat1,iat2,icol,idir1,idir2,idir3,index
    1546              :  integer :: ipert1,ipert2,ipert3,irow
    1547              :  integer :: ipert1_red,ipert2_red,idir1_red,idir2_red
    1548              :  complex(dpc), parameter :: ione=(0.d0,1.d0)
    1549              :  character(len=1000) :: msg
    1550              : !arrays
    1551            4 :  complex(dpc) :: idty(ndim,ndim)
    1552            2 :  integer :: indexat(ndim),indexdir(ndim)
    1553              :  character(len=1) :: cart(3)=(/'x','y','z'/)
    1554              : 
    1555              : ! *********************************************************************
    1556              : 
    1557              :  !Extract the Berry-curvature of the penalized susceptibility
    1558           42 :  idty=(zero,zero)
    1559            2 :  ipert3= natom + 9
    1560            2 :  idir3= 1
    1561            2 :  ipert2_red= 0
    1562            6 :  do iat2= mpatpol(1), mpatpol(2)
    1563            4 :    ipert2= natom + 11 + iat2
    1564            4 :    ipert2_red= ipert2_red + 1
    1565            4 :    idir2_red= 0
    1566           18 :    do idir2= 1, 3
    1567           12 :      if (mpdir(idir2)==0) cycle
    1568            8 :      idir2_red= idir2_red + 1
    1569            8 :      icol=idir2_red+(ipert2_red-1)*nmdir
    1570            8 :      indexat(icol)=iat2
    1571            8 :      indexdir(icol)=idir2
    1572            8 :      idty(icol,icol)=(one,zero)
    1573            8 :      ipert1_red=0
    1574           28 :      do iat1= mpatpol(1), mpatpol(2)
    1575           16 :        ipert1= natom + 11 + iat1
    1576           16 :        ipert1_red= ipert1_red + 1
    1577           16 :        idir1_red= 0
    1578           76 :        do idir1= 1, 3
    1579           48 :          if (mpdir(idir1)==0) cycle
    1580           32 :          idir1_red=idir1_red+1
    1581           32 :          irow=idir1_red+(ipert1_red-1)*nmdir
    1582              :          index = idir1 + &
    1583              :        & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    1584           32 :        & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    1585              : 
    1586              :          !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
    1587              :          !displacements at finite q (See M. Stengel PRB 2013).
    1588              :          bc_barmagsus(irow,icol)= -one* & !To convert from d3etot to local susc.
    1589              :        & cmplx(ddb_lw%val(1,index,iblok),ddb_lw%val(2,index,iblok),kind=dpc) &
    1590          160 :        & * exp(two_pi*(0.d0,1.d0)*dot_product(qphon,xred(:,iat1)-xred(:,iat2)))
    1591              : 
    1592              :        end do
    1593              :      end do
    1594              :    end do
    1595              :  end do
    1596              : 
    1597              : !Calculate the Berry-curvature of the inverse magnetic susceptibility
    1598          600 :  bc_ss=-matmul(invbarmagsus,matmul(bc_barmagsus,invbarmagsus))
    1599              : 
    1600            2 :  if (prtvol>1) then
    1601            6 :    call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the inverse spin susceptibility ')
    1602            6 :    call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
    1603           10 :    do irow=1, ndim
    1604           42 :      do icol=1, ndim
    1605              :        write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
    1606           32 :      & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
    1607           64 :      & real(bc_ss(irow,icol)), aimag(bc_ss(irow,icol))
    1608          104 :        call wrtout([ab_out,std_out], msg)
    1609              :      end do
    1610              :    end do
    1611            6 :    call wrtout([ab_out,std_out], '   ')
    1612              :  end if
    1613              : 
    1614              : !Store the FM flavor in the DDB object
    1615              :  ipert2_red= 0
    1616            6 :  do iat2= mpatpol(1), mpatpol(2)
    1617            4 :    ipert2= natom + 11 + iat2
    1618            4 :    ipert2_red= ipert2_red + 1
    1619            4 :    idir2_red= 0
    1620           18 :    do idir2= 1, 3
    1621           12 :      if (mpdir(idir2)==0) cycle
    1622            8 :      idir2_red= idir2_red + 1
    1623            8 :      icol=idir2_red+(ipert2_red-1)*nmdir
    1624            8 :      ipert1_red=0
    1625           28 :      do iat1= mpatpol(1), mpatpol(2)
    1626           16 :        ipert1= natom + 11 + iat1
    1627           16 :        ipert1_red= ipert1_red + 1
    1628           16 :        idir1_red= 0
    1629           76 :        do idir1= 1, 3
    1630           48 :          if (mpdir(idir1)==0) cycle
    1631           32 :          idir1_red=idir1_red+1
    1632           32 :          irow=idir1_red+(ipert1_red-1)*nmdir
    1633              :          index = idir1 + &
    1634              :        & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    1635           32 :        & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    1636              : 
    1637           32 :          ddb_lw%val_fs(1,index,iblok)= real(bc_ss(irow,icol))
    1638           64 :          ddb_lw%val_fs(2,index,iblok)= aimag(bc_ss(irow,icol))
    1639              :        end do
    1640              :      end do
    1641              :    end do
    1642              :  end do
    1643              : 
    1644            2 :  end subroutine berrycurv_ss
    1645              : !!***
    1646              : 
    1647              : !!****f* m_ddb_magpen/berrycurv_sp
    1648              : !! NAME
    1649              : !! berrycurv_sp
    1650              : !!
    1651              : !! FUNCTION
    1652              : !! Calculate the Berry curvature of the spin-phonon Hessian
    1653              : !! (equivalent to the Berry curvature of the induced Zeeman fields at constrained
    1654              : !! magnetic moments)
    1655              : !!
    1656              : !! INPUTS
    1657              : !! ddb_lw=  Third-order derivative ddb
    1658              : !!  In our case, the nblok is restricted to iblok
    1659              : !! iblok= index of the current block
    1660              : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
    1661              : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
    1662              : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
    1663              : !! mpert =maximum number of ipert
    1664              : !! natom= number of atoms in unit cell
    1665              : !! nblok= number of blocks in the DDB
    1666              : !! nmdir= number of directions along which the magnetic penalty was applied
    1667              : !! ndim= dimension of the square susceptibilities
    1668              : !! prtvol= control the volume of information written on output
    1669              : !!
    1670              : !! OUTPUT
    1671              : !!
    1672              : !! SOURCE
    1673              : 
    1674            2 :  subroutine berrycurv_sp(barmmom,bc_sp,bc_ss,ddb_lw,iblok,invbarmagsus,&
    1675            2 : & jblok,lblok,mpatpol,mpdir,mpert,natom,ndim,nmdir,prtvol,qphon,xred)
    1676              : 
    1677              : !Arguments -------------------------------
    1678              : !scalars
    1679              :  integer,intent(in) :: iblok,jblok,lblok,mpert,natom,ndim,nmdir,prtvol
    1680              : !arrays
    1681              :  type(ddb_type),intent(inout) :: ddb_lw
    1682              :  integer,intent(in) :: mpatpol(2),mpdir(3)
    1683              :  real(dp),intent(in) :: qphon(3),xred(3,natom)
    1684              :  complex(dpc),intent(in) :: barmmom(ndim,(natom+5)*3)
    1685              :  complex(dpc),intent(in) :: bc_ss(ndim,ndim)
    1686              :  complex(dpc),intent(in) :: invbarmagsus(ndim,ndim)
    1687              :  complex(dpc),intent(out) :: bc_sp(ndim,(natom+5)*3)
    1688              : !Local variables -------------------------
    1689              : !scalars
    1690              :  integer :: iat1,icol,idir1,idir2,idir3,index,ipert1,ipert2,ipert3,irow
    1691              :  integer :: ipert1_red,idir1_red,jndex
    1692              :  complex(dpc), parameter :: ione=(0.d0,1.d0)
    1693              :  complex(dpc) :: qfac
    1694              :  character(len=1000) :: msg
    1695              : !arrays
    1696            4 :  integer :: indexat1(ndim),indexdir1(ndim)
    1697            4 :  integer :: indexat2((natom+5)*3),indexdir2((natom+5)*3)
    1698            2 :  complex(dpc) :: bc_barsp(ndim,(natom+5)*3)
    1699              : ! complex(dpc) :: bc_ps((natom+2)*3,ndim)
    1700              :  character(len=1) :: cart(3)=(/'x','y','z'/)
    1701              : 
    1702              : ! *********************************************************************
    1703              : 
    1704              : !Extract the berry curvature of the penalized moments
    1705          332 :  bc_barsp=(zero,zero)
    1706              :  ipert3= natom + 9
    1707              :  idir3= 1
    1708           24 :  do ipert2=1,natom+5
    1709           90 :    do idir2=1,3
    1710           66 :      icol=idir2+(ipert2-1)*3
    1711           66 :      indexat2(icol)=ipert2
    1712           66 :      indexdir2(icol)=idir2
    1713              : 
    1714           66 :      ipert1_red= 0
    1715          220 :      do iat1= mpatpol(1), mpatpol(2)
    1716          132 :        ipert1= natom + 11 + iat1
    1717          132 :        ipert1_red= ipert1_red + 1
    1718          132 :        idir1_red= 0
    1719              : 
    1720              :        !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
    1721              :        !displacements at finite q (See M. Stengel PRB 2013).
    1722          528 :        qfac= exp(two_pi*(0.d0,1.d0)* dot_product(qphon,xred(:,iat1)))
    1723          594 :        do idir1= 1, 3
    1724          396 :          if (mpdir(idir1)==0) cycle
    1725          264 :          idir1_red= idir1_red + 1
    1726          264 :          irow=idir1_red+(ipert1_red-1)*nmdir
    1727          264 :          indexat1(irow)=iat1
    1728          264 :          indexdir1(irow)=idir1
    1729              :          index = idir1 + &
    1730              :        & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    1731          264 :        & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    1732              : 
    1733          396 :          if (iblok /=0 .and. ipert2 <= natom) then
    1734              :            bc_barsp(irow,icol)= -one* &  !To go from d3etot to induced local field
    1735          144 :          & cmplx(ddb_lw%val(1,index,iblok),ddb_lw%val(2,index,iblok),kind=dpc) * qfac
    1736          120 :          else if (jblok /=0 .and. ipert2 == natom+2) then
    1737              :            bc_barsp(irow,icol)= -one* &
    1738           12 :          & cmplx(ddb_lw%val(1,index,jblok),ddb_lw%val(2,index,jblok),kind=dpc)
    1739          108 :          else if (lblok /=0 .and. ipert2 == natom+5) then
    1740              :            bc_barsp(irow,icol)= -one* &
    1741           12 :          & cmplx(ddb_lw%val(1,index,lblok),ddb_lw%val(2,index,lblok),kind=dpc) * qfac
    1742              :          end if
    1743              : 
    1744              :        end do
    1745              :      end do
    1746              :    end do
    1747              :  end do
    1748              : 
    1749              :  !Calculate the Berry curvature of the induced Zeeman fields
    1750         3774 :  bc_sp= -matmul(bc_ss,barmmom) - matmul(invbarmagsus,bc_barsp)
    1751              : 
    1752            2 :  if (prtvol > 1) then
    1753            2 :    if (iblok /= 0) then
    1754            6 :      call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the Zeeman fields induced by atomic displacements')
    1755            6 :      call wrtout([ab_out,std_out], '  atom1  dir  E-dir            Real              Imag')
    1756           10 :      do irow=1, ndim
    1757          154 :        do icol=1, natom*3
    1758              :          write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
    1759          144 :        & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
    1760          288 :        & real(bc_sp(irow,icol)), aimag(bc_sp(irow,icol))
    1761          440 :          call wrtout([ab_out,std_out], msg)
    1762              :        end do
    1763              :      end do
    1764            6 :      call wrtout([ab_out,std_out], '   ')
    1765              :    end if
    1766            2 :    if (jblok /= 0) then
    1767            3 :      call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the Zeeman fields induced by electric field')
    1768            3 :      call wrtout([ab_out,std_out], '  atom1  dir  E-dir            Real              Imag')
    1769            5 :      do irow=1, ndim
    1770           17 :        do icol=(natom+1)*3+1, (natom+2)*3
    1771              :          write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
    1772           12 :        & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
    1773           24 :        & real(bc_sp(irow,icol)), aimag(bc_sp(irow,icol))
    1774           40 :          call wrtout([ab_out,std_out], msg)
    1775              :        end do
    1776              :      end do
    1777            3 :      call wrtout([ab_out,std_out], '   ')
    1778              :    end if
    1779            2 :    if (lblok /= 0) then
    1780            3 :      call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the Zeeman fields induced by macroscopic Zeeman field')
    1781            3 :      call wrtout([ab_out,std_out], '  atom1  dir  B-dir            Real              Imag')
    1782            5 :      do irow=1, ndim
    1783           17 :        do icol=(natom+4)*3+1, (natom+5)*3
    1784              :          write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
    1785           12 :        & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
    1786           24 :        & real(bc_sp(irow,icol)), aimag(bc_sp(irow,icol))
    1787           40 :          call wrtout([ab_out,std_out], msg)
    1788              :        end do
    1789              :      end do
    1790            3 :      call wrtout([ab_out,std_out], '   ')
    1791              :    end if
    1792              :  end if
    1793              : 
    1794              : !Store the FM flavor in the DDB object
    1795           24 :  do ipert2=1,natom+5
    1796           90 :    do idir2=1,3
    1797           66 :      icol=idir2+(ipert2-1)*3
    1798           66 :      indexat2(icol)=ipert2
    1799           66 :      indexdir2(icol)=idir2
    1800              : 
    1801           66 :      ipert1_red= 0
    1802          220 :      do iat1= mpatpol(1), mpatpol(2)
    1803          132 :        ipert1= natom + 11 + iat1
    1804          132 :        ipert1_red= ipert1_red + 1
    1805          132 :        idir1_red= 0
    1806          594 :        do idir1= 1, 3
    1807          396 :          if (mpdir(idir1)==0) cycle
    1808          264 :          idir1_red= idir1_red + 1
    1809          264 :          irow=idir1_red+(ipert1_red-1)*nmdir
    1810              :          index = idir1 + &
    1811              :        & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    1812          264 :        & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    1813              :          jndex = idir2 + &
    1814              :        & 3*((ipert2 - 1) + mpert*((idir1 - 1) + &
    1815          264 :        & 3*((ipert1 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    1816              : 
    1817          396 :          if (iblok /=0 .and. ipert2 <= natom) then
    1818          144 :            ddb_lw%val_fs(1,index,iblok)=real(bc_sp(irow,icol))
    1819          144 :            ddb_lw%val_fs(2,index,iblok)=aimag(bc_sp(irow,icol))
    1820          144 :            ddb_lw%val_fs(1,jndex,iblok)=real(bc_sp(irow,icol))
    1821          144 :            ddb_lw%val_fs(2,jndex,iblok)=-aimag(bc_sp(irow,icol))
    1822          120 :          else if (jblok /=0 .and. ipert2 == natom+2) then
    1823           12 :            ddb_lw%val_fs(1,index,jblok)=real(bc_sp(irow,icol))
    1824           12 :            ddb_lw%val_fs(2,index,jblok)=aimag(bc_sp(irow,icol))
    1825           12 :            ddb_lw%val_fs(1,jndex,jblok)=real(bc_sp(irow,icol))
    1826           12 :            ddb_lw%val_fs(2,jndex,jblok)=-aimag(bc_sp(irow,icol))
    1827          108 :          else if (lblok /=0 .and. ipert2 == natom+5) then
    1828           12 :            ddb_lw%val_fs(1,index,lblok)=real(bc_sp(irow,icol))
    1829           12 :            ddb_lw%val_fs(2,index,lblok)=aimag(bc_sp(irow,icol))
    1830           12 :            ddb_lw%val_fs(1,jndex,lblok)=real(bc_sp(irow,icol))
    1831           12 :            ddb_lw%val_fs(2,jndex,lblok)=-aimag(bc_sp(irow,icol))
    1832              :          end if
    1833              : 
    1834              :        end do
    1835              :      end do
    1836              :    end do
    1837              :  end do
    1838              : 
    1839            2 :  end subroutine berrycurv_sp
    1840              : !!***
    1841              : 
    1842              : !!****f* m_ddb_magpen/berrycurv_pp
    1843              : !! NAME
    1844              : !! berrycurv_pp
    1845              : !!
    1846              : !! FUNCTION
    1847              : !! Calculate the Berry curvature of the phonon-phonon Hessian
    1848              : !! (at constrained magnetic moments)
    1849              : !!
    1850              : !! INPUTS
    1851              : !! blkval(2,3*mpert*3*mpert*3*mpert,nblok)=  Third-order derivative matrices
    1852              : !!  In our case, the nblok is restricted to iblok
    1853              : !! kblok= index of the current block
    1854              : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
    1855              : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
    1856              : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
    1857              : !! mpert =maximum number of ipert
    1858              : !! natom= number of atoms in unit cell
    1859              : !! nblok= number of blocks in the DDB
    1860              : !! nmdir= number of directions along which the magnetic penalty was applied
    1861              : !! ndim= dimension of the square susceptibilities
    1862              : !! prtvol= control the volume of information written on output
    1863              : !!
    1864              : !! OUTPUT
    1865              : !!
    1866              : !! SOURCE
    1867              : 
    1868            2 :  subroutine berrycurv_pp(barmagsus,bc_barmagsus,bc_sp,ddb_lw,kblok,&
    1869            2 : & mpert,natom,ndim,qeq0,ucvol,zfield)
    1870              : 
    1871              : !Arguments -------------------------------
    1872              : !scalars
    1873              :  integer,intent(in) :: kblok,mpert,natom,ndim
    1874              :  real(dp),intent(in) :: ucvol
    1875              :  logical,intent(in) :: qeq0
    1876              : !arrays
    1877              :  type(ddb_type),intent(inout) :: ddb_lw
    1878              :  complex(dpc),intent(in) :: barmagsus(ndim,ndim)
    1879              :  complex(dpc),intent(in) :: bc_barmagsus(ndim,ndim)
    1880              :  complex(dpc),intent(in) :: bc_sp(ndim,(natom+5)*3)
    1881              :  complex(dpc),intent(in) :: zfield(ndim,(natom+5)*3)
    1882              : !Local variables -------------------------
    1883              : !scalars
    1884              :  integer :: icol,idir1,idir2,idir3,index,ipert1,ipert2,ipert3,irow
    1885              :  complex(dpc), parameter :: ione=(0.d0,1.d0)
    1886              :  complex(dpc) :: cval
    1887              : !arrays
    1888            4 :  complex(dpc) :: bc_barpp((natom+5)*3,(natom+5)*3), bc_pp((natom+5)*3,(natom+5)*3)
    1889            4 :  complex(dpc) :: term((natom+5)*3,(natom+5)*3,3)
    1890              : 
    1891              : ! *********************************************************************
    1892              : 
    1893              : !Extract the frequency derivative of the penalized 2nd order nonmagnetic quantities
    1894            2 :  ipert3= natom + 9
    1895            2 :  idir3= 1
    1896           24 :  do ipert2= 1, natom+5
    1897           90 :    do idir2= 1, 3
    1898           66 :      icol=( ipert2-1)*3 + idir2
    1899          814 :      do ipert1= 1, natom+5
    1900         2970 :        do idir1= 1, 3
    1901         2178 :          irow=( ipert1-1)*3 + idir1
    1902              :          index = idir1 + &
    1903              :        & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    1904         2178 :        & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    1905              : 
    1906         2904 :          bc_barpp(irow,icol)= cmplx(ddb_lw%val(1,index,kblok),ddb_lw%val(2,index,kblok),kind=dpc)
    1907              : 
    1908              :        end do
    1909              :      end do
    1910              :    end do
    1911              :  end do
    1912              : 
    1913              : !Calculate the different terms entering the Berry curvature
    1914        23646 :  term(:,:,1)=matmul(transpose(conjg(bc_sp)),matmul(barmagsus,zfield))
    1915        23644 :  term(:,:,2)=matmul(transpose(conjg(zfield)),matmul(bc_barmagsus,zfield))
    1916        23644 :  term(:,:,3)=matmul(transpose(conjg(zfield)),matmul(barmagsus,bc_sp))
    1917              : 
    1918         2246 :  bc_pp(:,:)= bc_barpp(:,:) + term(:,:,1) + term(:,:,2) + term(:,:,3)
    1919              : 
    1920              : !Apply factors to convert derivatives of energy into susceptibilities
    1921              : !Born charges
    1922            2 :  if (qeq0) then
    1923            7 :    ipert1= natom + 2
    1924            7 :    do ipert2= 1, natom
    1925           25 :      do idir2= 1, 3
    1926           18 :        icol=(ipert2-1)*3 + idir2
    1927           78 :        do idir1= 1, 3
    1928           54 :          irow=(ipert1-1)*3 + idir1
    1929           54 :          cval=bc_pp(irow,icol)
    1930           54 :          bc_pp(irow,icol)=-one*cval
    1931           54 :          cval=bc_pp(icol,irow)
    1932           72 :          bc_pp(icol,irow)=-one*cval
    1933              :        end do
    1934              :      end do
    1935              :    end do
    1936              :  end if
    1937              : 
    1938              : !MR: Not sure why this is different from the electrical charges,                 |  --------------------------------------------------------------------------------
    1939              : !but is needed to reproduce freqflag=3 numbers
    1940              : !Magnetic charges induced by atomic displacement
    1941              : ! ipert1= natom + 5
    1942              : ! do ipert2= 1, natom
    1943              : !   do idir2= 1, 3
    1944              : !     icol=( ipert2-1)*3 + idir2
    1945              : !     do idir1= 1, 3
    1946              : !       irow=( ipert1-1)*3 + idir1
    1947              : !       cval=bc_pp(irow,icol)
    1948              : !       bc_pp(irow,icol)=-cval
    1949              : !       cval=bc_pp(icol,irow)
    1950              : !       bc_pp(icol,irow)=-cval
    1951              : !     end do
    1952              : !   end do
    1953              : ! end do
    1954              : 
    1955              : !Dielectric tensor
    1956            2 :  if (qeq0) then
    1957            4 :    ipert1= natom + 2
    1958            4 :    ipert2= natom + 2
    1959            4 :    do idir2= 1, 3
    1960            3 :      icol=( ipert2-1)*3 + idir2
    1961           13 :      do idir1= 1, 3
    1962            9 :        irow=( ipert1-1)*3 + idir1
    1963            9 :        cval=bc_pp(irow,icol)
    1964           12 :        bc_pp(irow,icol)=-four_pi/ucvol*cval
    1965              :      end do
    1966              :    end do
    1967              :  end if
    1968              : 
    1969              : !Magnetoelectric susceptibility
    1970            2 :  if (qeq0) then
    1971            4 :    ipert1= natom + 5
    1972            4 :    ipert2= natom + 2
    1973            4 :    do idir2= 1, 3
    1974            3 :      icol=( ipert2-1)*3 + idir2
    1975           13 :      do idir1= 1, 3
    1976            9 :        irow=( ipert1-1)*3 + idir1
    1977            9 :        cval=bc_pp(irow,icol)
    1978            9 :        bc_pp(irow,icol)=-cval/ucvol
    1979            9 :        cval=bc_pp(icol,irow)
    1980           12 :        bc_pp(icol,irow)=-cval/ucvol
    1981              :      end do
    1982              :    end do
    1983              :  end if
    1984              : 
    1985              : !Magnetic susceptibility
    1986            8 :   ipert1= natom + 5
    1987            8 :   ipert2= natom + 5
    1988            8 :   do idir2= 1, 3
    1989            6 :     icol=( ipert2-1)*3 + idir2
    1990           26 :     do idir1= 1, 3
    1991           18 :       irow=( ipert1-1)*3 + idir1
    1992           18 :       cval=bc_pp(irow,icol)
    1993           24 :       bc_pp(irow,icol)=-cval/ucvol
    1994              :     end do
    1995              :   end do
    1996              : 
    1997              : !Store the FM flavor in the DDB object
    1998           24 :  do ipert2= 1, natom+5
    1999           90 :    do idir2= 1, 3
    2000           66 :      icol=( ipert2-1)*3 + idir2
    2001          814 :      do ipert1= 1, natom+5
    2002         2970 :        do idir1= 1, 3
    2003         2178 :          irow=( ipert1-1)*3 + idir1
    2004              :          index = idir1 + &
    2005              :        & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2006         2178 :        & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2007         2178 :          ddb_lw%val_fs(1,index,kblok)=real(bc_pp(irow,icol))
    2008         2904 :          ddb_lw%val_fs(2,index,kblok)=aimag(bc_pp(irow,icol))
    2009              :        end do
    2010              :      end do
    2011              :    end do
    2012              :  end do
    2013              : 
    2014            2 :  end subroutine berrycurv_pp
    2015              : !!***
    2016              : 
    2017              : !!****f* m_ddb_magpen/mp_d3etot_print
    2018              : !! NAME
    2019              : !! mp_d3etot_print
    2020              : !!
    2021              : !! FUNCTION
    2022              : !! Write on output file the fixed- and relaxed-spin susceptibilities
    2023              : !! Only macroscopic quantities are printed if prtvol=1
    2024              : !!
    2025              : !! INPUTS
    2026              : !! blkval= 2nd-order susceptibilities matrix
    2027              : !! kblok= index of the current block
    2028              : !! opt= 1 write the frozen-spin second-order quantities
    2029              : !!      2 write the relaxed-spin second-order quantities
    2030              : !! omega= frequency of the perturbation
    2031              : !! qphon= momentum wave-vector
    2032              : !! ucvol= unit-cell volume
    2033              : !!
    2034              : !! OUTPUT
    2035              : !!
    2036              : !! SOURCE
    2037              : 
    2038            6 :  subroutine mp_d3etot_print(ddb_lw,blkval,kblok,mpert,natom,nblok,opt,omega,prtvol,qeq0,qphnrm,qphon,ucvol,msize)
    2039              : 
    2040              : !Arguments -------------------------------
    2041              : !scalars
    2042              :  class(ddb_type),intent(in) :: ddb_lw
    2043              :  integer,intent(in) :: kblok,mpert,natom,nblok,opt,prtvol,msize
    2044              :  logical,intent(in) :: qeq0
    2045              :  real(dp),intent(in) :: ucvol
    2046              : !arrays
    2047              :  real(dp),intent(in) :: omega(3)
    2048              :  real(dp),intent(in) :: blkval(2,msize,nblok)
    2049              :  real(dp),intent(inout) :: qphnrm(3),qphon(3,3)
    2050              : 
    2051              : !Local variables -------------------------
    2052              : !scalars
    2053              :  integer :: iblok,idir1,idir2,idir3,ipert1,ipert2,ipert3,irow,icol
    2054              :  integer :: rftyp,index,tmp
    2055              :  character(len=1000) :: msg
    2056              : !arrays
    2057              :  integer :: rfelfd(4),rfmagn(4),rfphon(4),rfstrs(4),rffreq(4)
    2058              :  real(dp) :: val(2)
    2059              :  character(len=1) :: cart(3)=(/'x','y','z'/)
    2060              : 
    2061              : ! *********************************************************************
    2062              : 
    2063            2 :  rfelfd(:)=0
    2064            2 :  rfphon(:)=0
    2065            2 :  rfstrs(:)=0
    2066            2 :  rfmagn(:)=0
    2067            2 :  rffreq(:)=0
    2068            2 :  rffreq(3)=1
    2069            2 :  rftyp = 33
    2070              : 
    2071            2 :  ipert3= natom + 9
    2072            2 :  idir3= 1
    2073            2 :  tmp=opt !
    2074              :  !IFCs
    2075            2 :  if (prtvol>1) then
    2076            6 :    rfphon(1:2)=1
    2077              :    call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    2078            2 :   & rffreq=rffreq)
    2079            2 :    if (iblok/=0.and.iblok==kblok) then
    2080              : !     if (opt==1) then
    2081            6 :        call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of interatomic force constants')
    2082              : !     else if (opt==2) then
    2083              : !       call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of interatomic force constants')
    2084              : !     end if
    2085            6 :      call wrtout([ab_out,std_out], '  atom1  dir  atom2  dir        Real              Imag')
    2086           14 :      do ipert1= 1, natom
    2087           50 :        do idir1= 1, 3
    2088           36 :          irow=( ipert1-1)*3 + idir1
    2089          252 :          do ipert2= 1, natom
    2090          900 :            do idir2= 1, 3
    2091          648 :              icol=( ipert2-1)*3 + idir2
    2092              :              index = idir1 + &
    2093              :                & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2094          648 :                & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2095         1944 :              val(:)=blkval(:,index,kblok)
    2096              :              write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)') &
    2097          648 :            & ipert1, cart(idir1), ipert2, cart(idir2), val(1), val(2)
    2098         2160 :              call wrtout([ab_out,std_out], msg)
    2099              :            end do
    2100              :          end do
    2101          120 :          call wrtout([ab_out,std_out], ' ')
    2102              :        end do
    2103              :      end do
    2104              :    end if
    2105              :  end if
    2106              : 
    2107            2 :  if (qeq0) then
    2108              : 
    2109              :    !Born charges
    2110            3 :    rfphon(1:2)=1
    2111            3 :    rfelfd(1:2)=2
    2112              :    call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    2113            1 :  & rffreq=rffreq)
    2114            1 :    if (iblok/=0.and.iblok==kblok) then
    2115              : !     if (opt==1) then
    2116            3 :        call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of Born effective charges')
    2117              : !     else if (opt==2) then
    2118              : !       call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of Born effective charges')
    2119              : !     end if
    2120            3 :      call wrtout([ab_out,std_out], ' E-dir      atom   dir        Real              Imag')
    2121            1 :      ipert1= natom + 2
    2122            4 :      do idir1= 1, 3
    2123           21 :        do ipert2= 1, natom
    2124           75 :          do idir2= 1, 3
    2125              :            index = idir1 + &
    2126              :              & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2127           54 :              & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2128          162 :            val(:)=blkval(:,index,kblok)
    2129              :            write(msg,'(3x,a2,7x,i3,4x,a2,2x,2es18.9)') &
    2130           54 :          & cart(idir1), ipert2, cart(idir2), val(1), val(2)
    2131          180 :            call wrtout([ab_out,std_out], msg)
    2132              :          end do
    2133              :        end do
    2134           10 :        call wrtout([ab_out,std_out], ' ')
    2135              :      end do
    2136              :    end if
    2137              : 
    2138              :    !Dielectric tensor
    2139              :    iblok=0
    2140            1 :    rfphon(:)=0
    2141            3 :    rfelfd(1:2)=2
    2142              :    call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    2143            1 :  & rffreq=rffreq)
    2144            1 :    if (iblok/=0.and.iblok==kblok) then
    2145              : !     if (opt==1) then
    2146            3 :        call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of clamped-ion dielectric tensor')
    2147              : !     else if (opt==2) then
    2148              : !       call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of clamped-ion dielectric tensor')
    2149              : !     end if
    2150            3 :      call wrtout([ab_out,std_out], '  dir  dir        Real              Imag')
    2151            1 :      ipert1= ddb_lw%natom + 2
    2152            1 :      ipert2= ddb_lw%natom + 2
    2153            4 :      do idir2= 1, 3
    2154           12 :        do idir1= 1, 3
    2155              :          index = idir1 + &
    2156              :            & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2157            9 :            & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2158           27 :          val(:)=blkval(:,index,kblok)
    2159            9 :          write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    2160           18 :        & val(1), val(2)
    2161           30 :          call wrtout([ab_out,std_out], msg)
    2162              :        end do
    2163           10 :        call wrtout([ab_out,std_out], ' ')
    2164              :      end do
    2165              :    end if
    2166              : 
    2167              :    !Magnetoelectric susceptibility
    2168              :    iblok=0
    2169            1 :    rfphon(:)=0
    2170            1 :    rfelfd(1)=0
    2171            1 :    rfelfd(2)=2
    2172            1 :    rfmagn(1)=1
    2173              :    rfmagn(2)=0
    2174              :    call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    2175            1 :  & rfmagn=rfmagn,rffreq=rffreq)
    2176            1 :    if (iblok/=0.and.iblok==kblok) then
    2177              : !     if (opt==1) then
    2178            3 :        call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of clamped-ion magnetoelectric susceptibility')
    2179              : !     else if (opt==2) then
    2180              : !       call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of clamped-ion magnetoelectric susceptibility')
    2181              : !     end if
    2182            3 :      call wrtout([ab_out,std_out], ' M-dir E-dir        Real              Imag')
    2183            1 :      ipert1= ddb_lw%natom + 5
    2184            1 :      ipert2= ddb_lw%natom + 2
    2185            4 :      do idir2= 1, 3
    2186           12 :        do idir1= 1, 3
    2187              :          index = idir1 + &
    2188              :            & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2189            9 :            & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2190           27 :          val(:)=blkval(:,index,kblok)/ucvol
    2191            9 :          write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    2192           18 :        & val(1), val(2)
    2193           30 :          call wrtout([ab_out,std_out], msg)
    2194              :        end do
    2195           10 :        call wrtout([ab_out,std_out], ' ')
    2196              :      end do
    2197              :    end if
    2198              : 
    2199              :  end if
    2200              : 
    2201              :  !Magnetic susceptibility
    2202              :  iblok=0
    2203            2 :  rfphon(:)=0
    2204            2 :  rfelfd(:)=0
    2205            2 :  rfmagn(1)=1
    2206            2 :  rfmagn(2)=1
    2207              :  call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    2208            2 : & rfmagn=rfmagn,rffreq=rffreq)
    2209            2 :  if (iblok/=0.and.iblok==kblok) then
    2210              : !   if (opt==1) then
    2211            6 :      call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of clamped-ion magnetic susceptibility')
    2212              : !   else if (opt==2) then
    2213              : !     call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of clamped-ion magnetic susceptibility')
    2214              : !   end if
    2215            6 :    call wrtout([ab_out,std_out], '  dir  dir        Real              Imag')
    2216            2 :    ipert1= ddb_lw%natom + 5
    2217            2 :    ipert2= ddb_lw%natom + 5
    2218            8 :    do idir2= 1, 3
    2219           24 :      do idir1= 1, 3
    2220              :        index = idir1 + &
    2221              :          & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2222           18 :          & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2223           54 :        val(:)=blkval(:,index,kblok)/ucvol
    2224           18 :        write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
    2225           36 :      & val(1), val(2)
    2226           60 :        call wrtout([ab_out,std_out], msg)
    2227              :      end do
    2228           20 :      call wrtout([ab_out,std_out], ' ')
    2229              :    end do
    2230              :  end if
    2231              : 
    2232              :  !Magnetic Born effective charges
    2233              :  iblok=0
    2234            2 :  rfphon(1)=1
    2235            2 :  rfelfd(:)=0
    2236            2 :  rfmagn(1)=0
    2237              :  rfmagn(2)=1
    2238              :  call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
    2239            2 : & rfmagn=rfmagn,rffreq=rffreq)
    2240            2 :  if (iblok/=0.and.iblok==kblok) then
    2241              : !   if (opt==1) then
    2242            6 :      call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of magnetic Born effective charges')
    2243              : !   else if (opt==2) then
    2244              : !     call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of magnetic Born effective charges')
    2245              : !   end if
    2246            6 :    call wrtout([ab_out,std_out], ' atom   dir     B-dir        Real              Imag')
    2247              : 
    2248            2 :    ipert2= ddb_lw%natom + 5
    2249           14 :    do ipert1= 1, natom
    2250           48 :      do idir1= 1, 3
    2251          156 :        do idir2= 1, 3
    2252              :          index = idir1 + &
    2253              :            & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
    2254          108 :            & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
    2255          324 :          val(:)=blkval(:,index,kblok)
    2256              :          write(msg,'(i3,4x,a2,7x,a2,2x,2es18.9)') &
    2257          108 :        & ipert1, cart(idir1), cart(idir2), val(1), val(2)
    2258          360 :          call wrtout([ab_out,std_out], msg)
    2259              :        end do
    2260              :      end do
    2261           38 :      call wrtout([ab_out,std_out], ' ')
    2262              :    end do
    2263              :  end if
    2264              : 
    2265            2 :  end subroutine mp_d3etot_print
    2266              : !!***
    2267              : 
    2268        41464 : end module m_ddb_magpen
    2269              : !!***
        

Generated by: LCOV version 2.3-1