LCOV - code coverage report
Current view: top level - shared/common/src/33_xc_lowlevel - m_xc_noncoll.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 57.9 % 413 239
Test Date: 2026-11-12 07:43:35 Functions: 75.0 % 4 3
Branches: 50.0 % 216 108

             Branch data     Line data    Source code
       1                 :             : !!****f* ABINIT/m_xc_noncoll
       2                 :             : !! NAME
       3                 :             : !! m_xc_noncoll
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  This module provides several routines used in non-collinear XC routines
       7                 :             : !!  (rotation of the magnetization in order to align it)
       8                 :             : !!
       9                 :             : !! COPYRIGHT
      10                 :             : !! Copyright (C) 2001-2026 ABINIT group (EB, MT, FR, SPr)
      11                 :             : !! This file is distributed under the terms of the
      12                 :             : !! GNU General Public License, see ~abinit/COPYING
      13                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      14                 :             : !!
      15                 :             : !! INPUTS
      16                 :             : !!
      17                 :             : !! OUTPUT
      18                 :             : !!
      19                 :             : !! SOURCE
      20                 :             : 
      21                 :             : #if defined HAVE_CONFIG_H
      22                 :             : #include "config.h"
      23                 :             : #endif
      24                 :             : 
      25                 :             : #include "abi_common.h"
      26                 :             : 
      27                 :             : MODULE m_xc_noncoll
      28                 :             : 
      29                 :             :  use defs_basis
      30                 :             :  use m_abicore
      31                 :             :  use m_errors
      32                 :             : 
      33                 :             :  implicit none
      34                 :             : 
      35                 :             :  private
      36                 :             : 
      37                 :             : ! public procedures
      38                 :             :  public :: rotate_mag           ! Rotate a non-collinear density wrt a magnetization
      39                 :             :  public :: rotate_back_mag      ! Rotate back a collinear XC potential wrt a magnetization
      40                 :             :  public :: rotate_back_mag_dfpt ! Rotate back a collinear 1st-order XC potential wrt a magnetization
      41                 :             :  public :: test_rotations       ! test whether methods in rotate_back_mag_dfpt give similar results
      42                 :             : 
      43                 :             : !Tolerance on magnetization norm
      44                 :             :  real(dp),parameter :: m_norm_min=tol8
      45                 :             : 
      46                 :             : !Default rotation method for DFPT
      47                 :             :  integer,parameter :: rotation_method_default=3
      48                 :             : 
      49                 :             : CONTAINS
      50                 :             : 
      51                 :             : !===========================================================
      52                 :             : !!***
      53                 :             : 
      54                 :             : !!****t* m_xc_noncoll/rotate_mag
      55                 :             : !! NAME
      56                 :             : !!  rotate_mag
      57                 :             : !!
      58                 :             : !! FUNCTION
      59                 :             : !!  Project (rotate) a non-collinear density (stored as density+magn.)
      60                 :             : !!  on a magnetization and give a collinear density (stored as [up,dn] or [up+dn,up]).
      61                 :             : !!  Align both z-axis.
      62                 :             : !!
      63                 :             : !!
      64                 :             : !! INPUTS
      65                 :             : !!  rho_in(vectsize,4)=input non-collinear density and magnetization (1st or 0th order)
      66                 :             : !!  mag(vectsize,3)=gs magnetization used for projection (0th order magnetization)
      67                 :             : !!  vectsize=size of vector fields
      68                 :             : !!  [mag_norm_in(vectsize)]= --optional-- norm of mag(:) at each point of the grid
      69                 :             : !!  [rho_out_format]= 1=rho_out is stored as [up,dn]
      70                 :             : !!                    2=rho_out is stored as [up+dn,up]
      71                 :             : !!                    Default=1
      72                 :             : ! OUTPUT
      73                 :             : !!  rho_out(vectsize,2)=output (projected, collinear) (1st order if rho_in is 1st order NC density matrix)
      74                 :             : !!  [mag_norm_out(vectsize)]= --optional-- norm of mag(:) at each point of the grid
      75                 :             : !!
      76                 :             : !!     Explicit formulae:
      77                 :             : !!     rho_out_format=1
      78                 :             : !!       rho_out(1) = half*( rho_in(1) + (mag,rho_in(2:4))/|mag|) // where (*,*) is scalar product
      79                 :             : !!       rho_out(2) = half*( rho_in(1) - (mag,rho_in(2:4))/|mag|)
      80                 :             : !!
      81                 :             : !!     rho_out_format=2
      82                 :             : !!       rho_out(1) = rho_in(1)
      83                 :             : !!       rho_out(2) = half*( rho_in(1) + (mag,rho_in(2:4))/|mag|)
      84                 :             : !!
      85                 :             : !!
      86                 :             : !! SOURCE
      87                 :             : 
      88                 :       34746 : subroutine rotate_mag(rho_in,rho_out,mag,vectsize,cplex,&
      89                 :             : &                     mag_norm_in,mag_norm_out,rho_out_format) ! optional arguments
      90                 :             : 
      91                 :             : !Arguments ------------------------------------
      92                 :             : !scalars
      93                 :             :  integer,intent(in) :: vectsize
      94                 :             :  integer,intent(in) :: cplex
      95                 :             :  integer,intent(in),optional :: rho_out_format
      96                 :             : !arrays
      97                 :             :  real(dp),intent(in) ::  rho_in(cplex*vectsize,4),mag(vectsize,3)
      98                 :             :  real(dp),intent(out) :: rho_out(cplex*vectsize,2)
      99                 :             :  real(dp),intent(in),optional :: mag_norm_in(vectsize)
     100                 :             :  real(dp),intent(out),optional :: mag_norm_out(vectsize)
     101                 :             : 
     102                 :             : !Local variables-------------------------------
     103                 :             : !scalars
     104                 :             :  integer :: ipt
     105                 :             :  logical :: has_mag_norm,out_mag_norm
     106                 :             :  real(dp) :: m_norm,mm,rho_up,rhoin_dot_mag
     107                 :             :  real(dp) :: rhoin_dot_mag_re,rhoin_dot_mag_im
     108                 :             : !arrays
     109                 :             : 
     110                 :             : ! *************************************************************************
     111                 :             : 
     112                 :             : !DBG_ENTER("COLL")
     113                 :             : 
     114                 :       34746 :  has_mag_norm=present(mag_norm_in)
     115                 :       34746 :  out_mag_norm=present(mag_norm_out)
     116                 :             : 
     117         [ +  + ]:       34746 :  if(cplex==1) then
     118         [ +  + ]:    38745009 :    do ipt=1,vectsize
     119         [ -  + ]:    38710776 :      if (has_mag_norm) then
     120                 :           0 :        m_norm=mag_norm_in(ipt)
     121                 :             :      else
     122                 :    38710776 :        m_norm=dsqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     123                 :             :      end if
     124                 :             : 
     125                 :             :      rhoin_dot_mag=rho_in(ipt,2)*mag(ipt,1)+rho_in(ipt,3)*mag(ipt,2) &
     126                 :    38710776 : &                 +rho_in(ipt,4)*mag(ipt,3)
     127                 :             : 
     128         [ +  + ]:    38710776 :      if(m_norm>m_norm_min)then
     129                 :    17924622 :        mm=rhoin_dot_mag/m_norm
     130                 :    17924622 :        rho_out(ipt,1)=half*(rho_in(ipt,1)+mm)
     131                 :    17924622 :        rho_out(ipt,2)=half*(rho_in(ipt,1)-mm)
     132                 :             :      else
     133                 :    20786154 :        rho_out(ipt,1)=half*rho_in(ipt,1)
     134                 :    20786154 :        rho_out(ipt,2)=half*rho_in(ipt,1)
     135                 :             :      end if
     136                 :             : 
     137         [ +  + ]:    38745009 :      if (out_mag_norm) then
     138         [ +  + ]:     5880576 :        if (m_norm >m_norm_min) mag_norm_out(ipt)=m_norm
     139         [ +  + ]:     5880576 :        if (m_norm<=m_norm_min) mag_norm_out(ipt)=zero
     140                 :             :      end if
     141                 :             : 
     142                 :             :    end do
     143                 :             : 
     144                 :             :  else ! cplex==2
     145                 :             : 
     146         [ +  + ]:     2345473 :    do ipt=1,vectsize
     147         [ -  + ]:     2344960 :      if (has_mag_norm) then
     148                 :           0 :        m_norm=mag_norm_in(ipt)
     149                 :             :      else
     150                 :     2344960 :        m_norm=dsqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     151                 :             :      end if
     152                 :             : 
     153                 :             :      ! real part of m.m^(1)
     154                 :             :      rhoin_dot_mag_re=rho_in(2*ipt-1,2)*mag(ipt,1)+rho_in(2*ipt-1,3)*mag(ipt,2) &
     155                 :     2344960 : &                    +rho_in(2*ipt-1,4)*mag(ipt,3)
     156                 :             :      ! imaginary part of m.m^(1)
     157                 :             :      rhoin_dot_mag_im=rho_in(2*ipt  ,2)*mag(ipt,1)+rho_in(2*ipt  ,3)*mag(ipt,2) &
     158                 :     2344960 : &                    +rho_in(2*ipt  ,4)*mag(ipt,3)
     159         [ +  + ]:     2344960 :      if(m_norm>m_norm_min)then
     160                 :     1684571 :        mm=rhoin_dot_mag_re/m_norm
     161                 :     1684571 :        rho_out(2*ipt-1,1)=half*(rho_in(2*ipt-1,1)+mm)
     162                 :     1684571 :        rho_out(2*ipt-1,2)=half*(rho_in(2*ipt-1,1)-mm)
     163                 :     1684571 :        mm=rhoin_dot_mag_im/m_norm
     164                 :     1684571 :        rho_out(2*ipt  ,1)=half*(rho_in(2*ipt ,1)+mm)
     165                 :     1684571 :        rho_out(2*ipt  ,2)=half*(rho_in(2*ipt ,1)-mm)
     166                 :             :      else
     167                 :      660389 :        rho_out(2*ipt-1,1)=half*rho_in(2*ipt-1,1)
     168                 :             : !MR: BUG FIXED HERE
     169                 :             : !       rho_out(2*ipt-1,2)=half*rho_in(2*ipt-1,2)
     170                 :      660389 :        rho_out(2*ipt-1,2)=half*rho_in(2*ipt-1,1)
     171                 :      660389 :        rho_out(2*ipt  ,1)=half*rho_in(2*ipt  ,1)
     172                 :             : !MR: BUG FIXED HERE
     173                 :             : !       rho_out(2*ipt  ,2)=half*rho_in(2*ipt  ,2)
     174                 :      660389 :        rho_out(2*ipt  ,2)=half*rho_in(2*ipt  ,1)
     175                 :             :      end if
     176                 :             : 
     177         [ +  - ]:     2345473 :      if (out_mag_norm) then
     178         [ +  + ]:     2344960 :        if (m_norm >m_norm_min) mag_norm_out(ipt)=m_norm
     179         [ +  + ]:     2344960 :        if (m_norm<=m_norm_min) mag_norm_out(ipt)=zero
     180                 :             :      end if
     181                 :             : 
     182                 :             :    end do
     183                 :             : 
     184                 :             :  end if
     185                 :             : 
     186         [ +  + ]:       34746 :  if (present(rho_out_format)) then
     187         [ +  - ]:        1086 :    if (rho_out_format==2) then
     188         [ +  + ]:     8009388 :      do ipt=1,cplex*vectsize
     189                 :     8008302 :        rho_up=rho_out(ipt,1)
     190                 :     8008302 :        rho_out(ipt,1)=rho_up+rho_out(ipt,2)
     191                 :     8009388 :        rho_out(ipt,2)=rho_up
     192                 :             :      end do
     193                 :             :    end if
     194                 :             :  end if
     195                 :             : 
     196                 :             : !DBG_EXIT("COLL")
     197                 :             : 
     198                 :       34746 : end subroutine rotate_mag
     199                 :             : !!***
     200                 :             : 
     201                 :             : !----------------------------------------------------------------------
     202                 :             : 
     203                 :             : !!****t* m_xc_noncoll/rotate_back_mag
     204                 :             : !! NAME
     205                 :             : !!  rotate_back_mag
     206                 :             : !!
     207                 :             : !! FUNCTION
     208                 :             : !!  Rotate back a collinear XC potential (stored as up+dn) with respect to
     209                 :             : !!   a magnetization and give a non-collinear XC potential
     210                 :             : !!   (stored as up_up, dn_dn, Re[up_dn], Im[up_dn])
     211                 :             : !!  Note: works only for cplex=1
     212                 :             : !!
     213                 :             : !! INPUTS
     214                 :             : !!  vxc_in(vectsize,2)=input collinear XC potential
     215                 :             : !!  mag(vectsize,3)=gs magnetization used for projection
     216                 :             : !!  vectsize=size of vector fields
     217                 :             : !!  [mag_norm_in(vectsize)]= --optional-- norm of mag(:) at each point of the grid
     218                 :             : !!
     219                 :             : !! OUTPUT
     220                 :             : !!  vxc_out(vectsize,4)=output non-collinear XC potential
     221                 :             : !!
     222                 :             : !! SOURCE
     223                 :             : 
     224                 :       71459 : subroutine rotate_back_mag(vxc_in,vxc_out,mag,vectsize,&
     225                 :             : &                          mag_norm_in) ! optional argument
     226                 :             : 
     227                 :             : !Arguments ------------------------------------
     228                 :             : !scalars
     229                 :             :  integer,intent(in) :: vectsize
     230                 :             : !arrays
     231                 :             :  real(dp),intent(in)  :: vxc_in(vectsize,2),mag(vectsize,3)
     232                 :             :  real(dp),intent(out) :: vxc_out(vectsize,4)
     233                 :             :  real(dp),intent(in),optional :: mag_norm_in(vectsize)
     234                 :             : 
     235                 :             : !Local variables-------------------------------
     236                 :             : !scalars
     237                 :             :  integer :: ipt
     238                 :             :  logical :: has_mag_norm
     239                 :             :  real(dp) :: dvdn,dvdz,m_norm
     240                 :             : !arrays
     241                 :             : 
     242                 :             : ! *************************************************************************
     243                 :             : 
     244                 :             : !DBG_ENTER("COLL")
     245                 :             : 
     246                 :       71459 :  has_mag_norm=present(mag_norm_in)
     247                 :             : 
     248         [ +  + ]:    98818060 :  do ipt=1,vectsize
     249         [ +  + ]:    98746601 :    if (has_mag_norm) then
     250                 :      908847 :      m_norm=mag_norm_in(ipt)
     251                 :             :    else
     252                 :    97837754 :      m_norm=dsqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     253                 :             :    end if
     254                 :             : 
     255                 :    98746601 :    dvdn=half*(vxc_in(ipt,1)+vxc_in(ipt,2))
     256                 :             : 
     257         [ +  + ]:    98818060 :    if (m_norm>m_norm_min) then
     258                 :    59374648 :      dvdz=half*(vxc_in(ipt,1)-vxc_in(ipt,2))/m_norm
     259                 :    59374648 :      vxc_out(ipt,1)=dvdn+mag(ipt,3)*dvdz
     260                 :    59374648 :      vxc_out(ipt,2)=dvdn-mag(ipt,3)*dvdz
     261                 :    59374648 :      vxc_out(ipt,3)= mag(ipt,1)*dvdz
     262                 :    59374648 :      vxc_out(ipt,4)=-mag(ipt,2)*dvdz
     263                 :             :    else
     264         [ +  + ]:   118115859 :      vxc_out(ipt,1:2)=dvdn
     265         [ +  + ]:   118115859 :      vxc_out(ipt,3:4)=zero
     266                 :             :    end if
     267                 :             :  end do
     268                 :             : 
     269                 :             : !DBG_EXIT("COLL")
     270                 :             : 
     271                 :       71459 : end subroutine rotate_back_mag
     272                 :             : !!***
     273                 :             : 
     274                 :             : !!****t* m_xc_noncoll/rotate_back_mag_dfpt
     275                 :             : !! NAME
     276                 :             : !!  rotate_back_mag_dfpt
     277                 :             : !!
     278                 :             : !! FUNCTION
     279                 :             : !!  Rotate back a 1st-order collinear XC potential (stored as up+dn) with respect to
     280                 :             : !!   a magnetization and give a 1st-order non-collinear XC potential
     281                 :             : !!   (stored as up_up, dn_dn, Re{up_dn}, Im{up_dn}).
     282                 :             : !!
     283                 :             : !! INPUTS
     284                 :             : !!  mag(vectsize,3)=0-order magnetization used for projection
     285                 :             : !!  rho1(vectsize,4)=1st-order non-collinear density and magnetization
     286                 :             : !!  vxc(vectsize,4)=0-order non-collinear XC potential
     287                 :             : !!  kxc(vectsize,nkxc)=0-order XC kernel (associated to vxc)
     288                 :             : !!  vxc1_in(vectsize,2)=input 1st-order collinear XC potential
     289                 :             : !!  vectsize=size of vector fields
     290                 :             : !!  [mag_norm_in(vectsize)]= --optional-- norm of 0-order mag(:) at each point of the grid
     291                 :             : !!  [rot_method]=Select method used to compute rotation matrix (1, 2 or 3)
     292                 :             : !!  option=if 0, compute only the U^0 vxc^(1) U^0 part
     293                 :             : !!         if 1, full first order xc potential
     294                 :             : !!
     295                 :             : !! NOTES
     296                 :             : !!   cplex=1:
     297                 :             : !!     V is stored as : V^11, V^22, Re[V^12], Im[V^12] (complex, hermitian)
     298                 :             : !!     N is stored as : n, m_x, m_y, m_z               (real)
     299                 :             : !!   cplex=2:
     300                 :             : !!     V is stored as : V^11, V^22, V^12, i.V^21 (complex)
     301                 :             : !!     N is stored as : n, m_x, m_y, mZ          (complex)
     302                 :             : !!
     303                 :             : !! OUTPUT
     304                 :             : !!  vxc1_out(vectsize,4)=output 1st-order non-collinear XC potential
     305                 :             : !!
     306                 :             : !! SOURCE
     307                 :             : 
     308         [ -  + ]:         997 : subroutine rotate_back_mag_dfpt(option,vxc1_in,vxc1_out,vxc,kxc,rho1,mag,vectsize,cplex,&
     309                 :             : &                               mag_norm_in,rot_method) ! optional arguments
     310                 :             : 
     311                 :             : !Arguments ------------------------------------
     312                 :             : !scalars
     313                 :             :  integer,intent(in) :: vectsize
     314                 :             :  integer,intent(in) :: cplex
     315                 :             :  integer,intent(in) :: option
     316                 :             :  integer,intent(in),optional  :: rot_method
     317                 :             : !arrays
     318                 :             :  real(dp),intent(in)          :: kxc(:,:),mag(vectsize,3),vxc(vectsize,4)
     319                 :             :  real(dp),intent(in)          :: rho1(cplex*vectsize,4)
     320                 :             :  real(dp),intent(in)          :: vxc1_in(cplex*vectsize,2)
     321                 :             :  real(dp),intent(in),optional :: mag_norm_in(vectsize)
     322                 :             :  real(dp),intent(out)         :: vxc1_out(cplex*vectsize,4)
     323                 :             : 
     324                 :             : !Local variables-------------------------------
     325                 :             : !scalars
     326                 :             :  integer  :: ipt,rotation_method
     327                 :             :  logical  :: has_mag_norm
     328                 :             :  logical  :: small_angle
     329                 :             :  real(dp) :: bxc_over_m,d1,d2,dvdn,dvdz,fact,m_dot_m1,m_norm
     330                 :             :  ! d3 and d4 were computed below but never used, and caused test
     331                 :             :  ! fail problems
     332                 :             :  !real(dp) :: d3,d4
     333                 :             :  real(dp) :: dvdn_re,dvdn_im,dvdz_re,dvdz_im
     334                 :             :  complex(dp) :: rho_updn
     335                 :             :  real(dp) :: mdirx,mdiry,mdirz,mxy,mx1,my1,mz1,wx,wy,wx1,wy1
     336                 :             :  real(dp) :: theta0,theta1,theta1_re,theta1_im
     337                 :             :  real(dp) :: wx1_re,wx1_im
     338                 :             :  real(dp) :: wy1_re,wy1_im
     339                 :             :  real(dp) :: mx1_re,mx1_im,my1_re,my1_im,mz1_re,mz1_im
     340                 :             :  real(dp) :: m_dot_m1_re,m_dot_m1_im
     341                 :             :  real(dp) :: bxc
     342                 :             : !arrays
     343                 :             :  real(dp)     :: vxc_diag(2),v21tmp(2)
     344                 :             :  complex(dp) :: r1tmp(2,2),u0(2,2),u0_1(2,2),u0_1r1(2,2),u0v1(2,2)
     345                 :             :  complex(dp) :: rho1_updn(2,2),v1tmp(2,2),vxc1tmp(2,2)
     346                 :             :  complex(dp) :: rho1_offdiag(2)
     347                 :             : ! *************************************************************************
     348                 :             : 
     349                 :             : !DBG_ENTER("COLL")
     350                 :             : 
     351                 :             : !Optional arguments
     352                 :         997 :  has_mag_norm=present(mag_norm_in)
     353                 :         997 :  rotation_method=rotation_method_default
     354         [ +  - ]:         997 :  if (present(rot_method)) rotation_method=rot_method
     355                 :             : 
     356                 :             : !Check Kxc
     357   [ +  +  -  + ]:        2991 :  if (size(kxc)>3*vectsize) then
     358                 :           0 :      ABI_ERROR('Cannot use Kxc from GGA!')
     359                 :             :  end if
     360                 :             : 
     361   [ +  +  -  + ]:         997 :  if((rotation_method==1.or.rotation_method==2).and.cplex==2) then
     362                 :           0 :      ABI_ERROR('rotation_method=1 and 2 are not available for cplex=2 case! use ixcrot=3')
     363                 :             :  endif
     364                 :             : 
     365                 :             : 
     366                 :             :  select case (rotation_method)
     367                 :             : 
     368                 :             : !----------------------------------------
     369                 :             : ! Taylor expansion of U rotation matrix
     370                 :             : !----------------------------------------
     371                 :             :  case (1)
     372                 :             : 
     373         [ +  + ]:      743583 :    do ipt=1,vectsize
     374                 :             : 
     375         [ +  - ]:      743445 :      if (has_mag_norm) then
     376                 :      743445 :        m_norm=mag_norm_in(ipt)
     377                 :             :      else
     378                 :           0 :        m_norm=sqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     379                 :             :      end if
     380                 :             : 
     381         [ +  + ]:      743583 :      if(m_norm>m_norm_min) then
     382                 :             : 
     383                 :             : !      Define the U^(0) transformation matrix
     384                 :      701352 :        rho_updn=(mag(ipt,1)+(zero,one)*mag(ipt,2))
     385                 :      701352 :        d1=sqrt(( m_norm+mag(ipt,3))**2+abs(rho_updn)**2)
     386                 :      701352 :        d2=sqrt((-m_norm+mag(ipt,3))**2+abs(rho_updn)**2)
     387                 :             :        ! d3 and d4 are computed here but never used
     388                 :             :        !d3=sqrt(( m_norm-mag(ipt,3))**2+abs(rho_updn)**2)
     389                 :             :        !d4=sqrt(( m_norm+mag(ipt,3))**2-abs(rho_updn)**2)
     390                 :      701352 :        u0(1,1)=( m_norm+mag(ipt,3))/d1  ! ( m  + mz)/d1
     391                 :      701352 :        u0(2,2)=rho_updn/d2              ! ( mx +imy)/d2
     392                 :      701352 :        u0(1,2)=(-m_norm+mag(ipt,3))/d2  ! (-m  + mz)/d2
     393                 :      701352 :        u0(2,1)=rho_updn/d1              ! ( mx +imy)/d1
     394                 :             : 
     395                 :             : !      Define the inverse of U^(0): U^(0)^-1
     396         [ +  + ]:      701352 :        if (abs(rho_updn) > m_norm_min) then
     397                 :      674325 :          u0_1(1,1)= half*d1/m_norm
     398                 :      674325 :          u0_1(2,2)= half*d2*(m_norm+mag(ipt,3))/(m_norm*rho_updn)
     399                 :      674325 :          u0_1(1,2)= half*d1*(m_norm-mag(ipt,3))/(m_norm*rho_updn)
     400                 :      674325 :          u0_1(2,1)=-half*d2/m_norm
     401                 :             :        else
     402                 :       27027 :          u0 = zero
     403                 :       27027 :          u0(1,1) = one
     404                 :       27027 :          u0(2,2) = one
     405                 :       27027 :          u0_1 = zero
     406                 :       27027 :          u0_1(1,1) = one
     407                 :       27027 :          u0_1(2,2) = one
     408                 :             :        end if
     409                 :             : 
     410                 :             : !      Diagonalize the GS Vxc^(0): U^(0)^-1 Vxc^(0) U^(0)
     411                 :             : !        (Remember the abinit notation for vxc!)
     412                 :             :        vxc_diag(1)=half*(vxc(ipt,1)+vxc(ipt,2) &
     413                 :             : &                 -sqrt((vxc(ipt,1)-vxc(ipt,2))**2 &
     414                 :      701352 : &                 +four*(vxc(ipt,3)**2+vxc(ipt,4)**2)))
     415                 :             :        vxc_diag(2)=half*(vxc(ipt,1)+vxc(ipt,2) &
     416                 :             : &                 +sqrt((vxc(ipt,1)-vxc(ipt,2))**2 &
     417                 :      701352 : &                 +four*(vxc(ipt,3)**2+vxc(ipt,4)**2)))
     418                 :      701352 :        v1tmp(1,1)=cmplx(real(vxc1_in(ipt,1),kind=dp),zero)
     419                 :      701352 :        v1tmp(2,2)=cmplx(real(vxc1_in(ipt,2),kind=dp),zero)
     420                 :             : 
     421                 :             :        !Transforming the rhor1 with U0
     422                 :      701352 :        rho1_updn(1,1)=half*(rho1(ipt,1)+rho1(ipt,4))
     423                 :      701352 :        rho1_updn(2,2)=half*(rho1(ipt,1)-rho1(ipt,4))
     424                 :      701352 :        rho1_updn(1,2)=half*(rho1(ipt,2)-(zero,one)*rho1(ipt,3))
     425                 :      701352 :        rho1_updn(2,1)=half*(rho1(ipt,2)+(zero,one)*rho1(ipt,3))
     426   [ +  +  +  +  :    10520280 :        u0_1r1=matmul(u0_1,rho1_updn)
                   +  + ]
     427   [ +  +  +  +  :    10520280 :        r1tmp=matmul(u0_1r1,u0)
                   +  + ]
     428                 :      701352 :        rho1_offdiag(1)=r1tmp(1,2) ; rho1_offdiag(2)=r1tmp(2,1)
     429                 :             : 
     430         [ +  + ]:      701352 :        if (option==0) then ! for xccc alone
     431                 :      449412 :          v1tmp(1,2)=cmplx(zero,zero)
     432                 :      449412 :          v1tmp(2,1)=cmplx(zero,zero)
     433                 :             :        else
     434                 :      251940 :          v1tmp(1,2)=-(rho1_offdiag(1)/m_norm)*(vxc_diag(2)-vxc_diag(1))
     435                 :      251940 :          v1tmp(2,1)= (rho1_offdiag(2)/m_norm)*(vxc_diag(1)-vxc_diag(2))
     436                 :             :        endif
     437                 :             : 
     438                 :             :        !Rotate back the "diagonal" xc computing the term U^(0) Vxc1_^(1) U^(0)^-1
     439   [ +  +  +  +  :    10520280 :        u0v1=matmul(u0,v1tmp)
                   +  + ]
     440   [ +  +  +  +  :    10520280 :        vxc1tmp=matmul(u0v1,u0_1)
                   +  + ]
     441                 :      701352 :        vxc1_out(ipt,1)=real(vxc1tmp(1,1),kind=dp)
     442                 :      701352 :        vxc1_out(ipt,2)=real(vxc1tmp(2,2),kind=dp)
     443                 :      701352 :        vxc1_out(ipt,3)=real( real(vxc1tmp(1,2)),kind=dp)
     444                 :      701352 :        vxc1_out(ipt,4)=real(aimag(vxc1tmp(1,2)),kind=dp)
     445                 :             : 
     446                 :             :      else ! Magnetization is zero
     447                 :       42093 :        dvdn=(vxc1_in(ipt,1)+vxc1_in(ipt,2))*half
     448                 :       42093 :        mx1=rho1(ipt,2) ; my1=rho1(ipt,3) ; mz1=rho1(ipt,4)
     449                 :             : !      Compute Bxc/|m| from Kxc (zero limit)
     450                 :       42093 :        bxc_over_m = half*(half*(kxc(ipt,1)+kxc(ipt,3))-kxc(ipt,2))
     451                 :       42093 :        vxc1_out(ipt,1)= dvdn + bxc_over_m*mz1
     452                 :       42093 :        vxc1_out(ipt,2)= dvdn - bxc_over_m*mz1
     453                 :       42093 :        vxc1_out(ipt,3)= bxc_over_m*mx1
     454                 :       42093 :        vxc1_out(ipt,4)=-bxc_over_m*my1
     455                 :             :      end if
     456                 :             : 
     457                 :             :    end do ! ipt
     458                 :             : 
     459                 :             : !----------------------------------------
     460                 :             : ! Analytical expression of U rotation matrix
     461                 :             : !----------------------------------------
     462                 :             :  case (2)
     463                 :             :    !Alternative method (explicitly calculated rotation matrices)
     464                 :             :    !Vxc^(1) =   phixc^(1).Id +                                               // <= change of "electrostatic" XC potential  (phixc^(1) is denoted dvdn)
     465                 :             :    !          + bxc^(1)*( Udag^(0).sigma_z.U^(0) )  +                        // <= this part describes the change of XC magnetic field magnitude bxc^(1)
     466                 :             :    !          + bxc^(0)*( Udag^(1).sigma_z.U^(0) + Udag^(0).sigma_z.U^(1) )  // <= remaining terms describe the cost of magnetization rotation
     467                 :             : 
     468                 :         748 :    select case(cplex)
     469                 :             :    case(1)
     470         [ +  + ]:      674436 :      do ipt=1,vectsize
     471                 :             : 
     472         [ +  - ]:      674325 :        if (has_mag_norm) then
     473                 :      674325 :          m_norm=mag_norm_in(ipt)
     474                 :             :        else
     475                 :           0 :          m_norm=dsqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     476                 :             :        end if
     477                 :             : 
     478                 :             : 
     479                 :      674325 :        mx1 =rho1(ipt,2);
     480                 :      674325 :        my1 =rho1(ipt,3);
     481                 :      674325 :        mz1 =rho1(ipt,4)
     482                 :             : 
     483                 :      674325 :        dvdn=(vxc1_in(ipt,1)+vxc1_in(ipt,2))*half  !phixc^(1)
     484                 :      674325 :        dvdz=(vxc1_in(ipt,1)-vxc1_in(ipt,2))*half  !bxc^(1)
     485                 :             : 
     486         [ +  - ]:      674436 :        if (m_norm>m_norm_min) then
     487                 :             : 
     488                 :      674325 :          mxy = dsqrt(mag(ipt,1)**2+mag(ipt,2)**2)
     489                 :      674325 :          small_angle=(mxy/m_norm<tol8)            !condition for sin(x)~x to be valid
     490                 :             :                                                   !even possible to set to tol6
     491                 :      674325 :          mdirx=mag(ipt,1)/m_norm
     492                 :      674325 :          mdiry=mag(ipt,2)/m_norm
     493                 :      674325 :          mdirz=mag(ipt,3)/m_norm
     494                 :             : 
     495                 :             : !        dvdn is phixc^(1) (density only part)
     496                 :             : !        dvdz is bxc^(1)   (magnetization magnitude part)
     497                 :             : 
     498                 :             :          !U^(0)*.Vxc1.U^(0) part
     499                 :      674325 :          vxc1_out(ipt,1)= dvdn+dvdz*mdirz
     500                 :      674325 :          vxc1_out(ipt,2)= dvdn-dvdz*mdirz
     501                 :      674325 :          vxc1_out(ipt,3)= dvdz*mdirx   ! Real part
     502                 :      674325 :          vxc1_out(ipt,4)=-dvdz*mdiry   ! Imaginary part, minus sign comes from sigma_y
     503                 :             : 
     504                 :             :          !U^(1)*.Vxc0.U^(0) + U^(0)*.Vxc0.U^(1) part
     505                 :             : 
     506                 :             :          !bxc = dsqrt(((vxc(ipt,1)-vxc(ipt,2))*half)**2+vxc(ipt,3)**2+vxc(ipt,4)**2) !bxc^(0)
     507                 :      674325 :          bxc = (vxc(ipt,1)-vxc(ipt,2))*half/mag(ipt,3)*m_norm
     508         [ +  - ]:      674325 :          if (.not.small_angle) then
     509                 :      674325 :            wx     = mag(ipt,2)/mxy
     510                 :      674325 :            wy     =-mag(ipt,1)/mxy
     511                 :      674325 :            theta0 = dacos(mag(ipt,3)/m_norm)
     512                 :             : 
     513                 :      674325 :            theta1 = (mdirz*(mdirx*mx1+mdiry*my1))/mxy - mz1*mxy/m_norm**2
     514                 :      674325 :            wx1    = (+mag(ipt,1)**2*my1 - mag(ipt,1)*mag(ipt,2)*mx1)/mxy**2/m_norm  ! wx1 multiplied by sin(theta)=mxy/m_norm
     515                 :      674325 :            wy1    = (-mag(ipt,2)**2*mx1 + mag(ipt,1)*mag(ipt,2)*my1)/mxy**2/m_norm  ! wx1 multiplied by sin(theta)=mxy/m_norm
     516                 :             : 
     517                 :      674325 :            vxc1_out(ipt,1) = vxc1_out(ipt,1) - bxc*dsin(theta0)*theta1
     518                 :      674325 :            vxc1_out(ipt,2) = vxc1_out(ipt,2) + bxc*dsin(theta0)*theta1
     519                 :      674325 :            vxc1_out(ipt,3) = vxc1_out(ipt,3) - bxc*(wy1+dcos(theta0)*wy*theta1)
     520                 :      674325 :            vxc1_out(ipt,4) = vxc1_out(ipt,4) - bxc*(wx1+dcos(theta0)*wx*theta1)
     521                 :             :          else
     522                 :             :            !zero order terms O(1)
     523                 :           0 :            vxc1_out(ipt,3) = vxc1_out(ipt,3) + bxc*mx1/abs(mag(ipt,3))
     524                 :           0 :            vxc1_out(ipt,4) = vxc1_out(ipt,4) - bxc*my1/abs(mag(ipt,3))
     525                 :             :            !first order terms O(theta)
     526                 :           0 :            fact = bxc/(mag(ipt,3)*abs(mag(ipt,3)))
     527                 :           0 :            vxc1_out(ipt,1) = vxc1_out(ipt,1) - (mag(ipt,1)*mx1+mag(ipt,2)*my1)*fact
     528                 :           0 :            vxc1_out(ipt,2) = vxc1_out(ipt,2) + (mag(ipt,1)*mx1+mag(ipt,2)*my1)*fact
     529                 :           0 :            vxc1_out(ipt,3) = vxc1_out(ipt,3) -  mag(ipt,1)*mz1*fact
     530                 :           0 :            vxc1_out(ipt,4) = vxc1_out(ipt,4) +  mag(ipt,2)*mz1*fact
     531                 :             :          endif
     532                 :             : 
     533                 :             :        else ! Magnetization is zero
     534                 :             : !        Compute Bxc/|m| from Kxc (zero limit)
     535                 :           0 :          bxc_over_m = half*(half*(kxc(ipt,1)+kxc(ipt,3))-kxc(ipt,2))
     536                 :           0 :          vxc1_out(ipt,1)= dvdn + bxc_over_m*mz1
     537                 :           0 :          vxc1_out(ipt,2)= dvdn - bxc_over_m*mz1
     538                 :           0 :          vxc1_out(ipt,3)= bxc_over_m*mx1
     539                 :           0 :          vxc1_out(ipt,4)=-bxc_over_m*my1
     540                 :             :        end if
     541                 :             :      end do ! ipt
     542                 :             : 
     543                 :             :    case(2) !cplex=2
     544                 :             : 
     545   [ +  -  -  -  :         111 :      do ipt=1,vectsize
                      - ]
     546                 :             : 
     547         [ #  # ]:           0 :        if (has_mag_norm) then
     548                 :           0 :          m_norm=mag_norm_in(ipt)
     549                 :             :        else
     550                 :           0 :          m_norm=dsqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     551                 :             :        end if
     552                 :             : 
     553                 :           0 :        mx1_re= rho1(2*ipt-1,2); mx1_im= rho1(2*ipt,2)
     554                 :           0 :        my1_re= rho1(2*ipt-1,3); my1_im= rho1(2*ipt,3)
     555                 :           0 :        mz1_re= rho1(2*ipt-1,4); mz1_im= rho1(2*ipt,4)
     556                 :             : 
     557                 :           0 :        dvdn_re=(vxc1_in(2*ipt-1,1)+vxc1_in(2*ipt-1,2))*half
     558                 :           0 :        dvdz_re=(vxc1_in(2*ipt-1,1)-vxc1_in(2*ipt-1,2))*half
     559                 :           0 :        dvdn_im=(vxc1_in(2*ipt  ,1)+vxc1_in(2*ipt  ,2))*half
     560                 :           0 :        dvdz_im=(vxc1_in(2*ipt  ,1)-vxc1_in(2*ipt  ,2))*half
     561                 :             : 
     562         [ #  # ]:           0 :        if (m_norm>m_norm_min) then
     563                 :             : 
     564                 :           0 :          mdirx=mag(ipt,1)/m_norm
     565                 :           0 :          mdiry=mag(ipt,2)/m_norm
     566                 :           0 :          mdirz=mag(ipt,3)/m_norm
     567                 :             : 
     568                 :           0 :          mxy = dsqrt(mag(ipt,1)**2+mag(ipt,2)**2)
     569                 :           0 :          small_angle=(mxy/m_norm<tol8)            !condition for sin(x)~x to be valid
     570                 :             :                                                   !
     571                 :           0 :          mdirx=mag(ipt,1)/m_norm
     572                 :           0 :          mdiry=mag(ipt,2)/m_norm
     573                 :           0 :          mdirz=mag(ipt,3)/m_norm
     574                 :             : 
     575                 :             : !        dvdn is phixc^(1) (density only part)
     576                 :             : !        dvdz is bxc^(1)   (magnetization magnitude part)
     577                 :             : 
     578                 :             :          !U^(0)*.Vxc1.U^(0) part
     579                 :           0 :          vxc1_out(2*ipt-1,1)= dvdn_re+dvdz_re*mdirz
     580                 :           0 :          vxc1_out(2*ipt  ,1)= dvdn_im+dvdz_im*mdirz
     581                 :           0 :          vxc1_out(2*ipt-1,2)= dvdn_re-dvdz_re*mdirz
     582                 :           0 :          vxc1_out(2*ipt  ,2)= dvdn_im-dvdz_im*mdirz
     583                 :             :          !NOTE: change of definition of the potential matrix components
     584                 :             :          !      vxc1_out(:,3) =   V_updn
     585                 :             :          !      vxc1_out(:,4) = i.V_updn
     586                 :           0 :          vxc1_out(2*ipt-1,3)= dvdz_re*mdirx + dvdz_im*mdiry   !Re[  V^12]
     587                 :           0 :          vxc1_out(2*ipt  ,3)= dvdz_im*mdirx - dvdz_re*mdiry   !Im[  V^12]
     588                 :             : 
     589                 :             :          !U^(1)*.Vxc0.U^(0) + U^(0)*.Vxc0.U^(1) part
     590                 :             :          !bxc = dsqrt(((vxc(ipt,1)-vxc(ipt,2))*half)**2+vxc(ipt,3)**2+vxc(ipt,4)**2) !bxc^(0)
     591                 :           0 :          bxc = (vxc(ipt,1)-vxc(ipt,2))*half/mag(ipt,3)*m_norm
     592         [ #  # ]:           0 :          if (.not.small_angle) then
     593                 :           0 :            wx     = mag(ipt,2)/mxy
     594                 :           0 :            wy     =-mag(ipt,1)/mxy
     595                 :           0 :            theta0 = dacos(mag(ipt,3)/m_norm)
     596                 :             : 
     597                 :             : 
     598                 :           0 :            theta1_re = (mdirz*(mdirx*mx1_re+mdiry*my1_re))/mxy - mz1_re*mxy/m_norm**2
     599                 :           0 :            theta1_im = (mdirz*(mdirx*mx1_im+mdiry*my1_im))/mxy - mz1_im*mxy/m_norm**2
     600                 :             : 
     601                 :           0 :            wx1_re = (+mag(ipt,1)**2*my1_re - mag(ipt,1)*mag(ipt,2)*mx1_re)/mxy**2/m_norm  ! wx1 multiplied by sin(theta)=mxy/m_norm
     602                 :           0 :            wx1_im = (+mag(ipt,1)**2*my1_im - mag(ipt,1)*mag(ipt,2)*mx1_im)/mxy**2/m_norm
     603                 :           0 :            wy1_re = (-mag(ipt,2)**2*mx1_re + mag(ipt,1)*mag(ipt,2)*my1_re)/mxy**2/m_norm  ! wy1 multiplied by sin(theta)=mxy/m_norm
     604                 :           0 :            wy1_im = (-mag(ipt,2)**2*mx1_im + mag(ipt,1)*mag(ipt,2)*my1_im)/mxy**2/m_norm
     605                 :             : 
     606                 :             :            !U^(1)*.Vxc0.U^(0) + U^(0)*.Vxc0.U^(1)
     607                 :           0 :            vxc1_out(2*ipt-1,1) = vxc1_out(2*ipt-1,1) - bxc*dsin(theta0)*theta1_re
     608                 :           0 :            vxc1_out(2*ipt  ,1) = vxc1_out(2*ipt  ,1) - bxc*dsin(theta0)*theta1_im
     609                 :           0 :            vxc1_out(2*ipt-1,2) = vxc1_out(2*ipt-1,2) + bxc*dsin(theta0)*theta1_re
     610                 :           0 :            vxc1_out(2*ipt  ,2) = vxc1_out(2*ipt  ,2) + bxc*dsin(theta0)*theta1_im
     611                 :             :            !cplex=1 part:
     612                 :             :            !v12 +=   -(bxc)*(wy1+dcos(theta0)*wy*theta1)-
     613                 :             :            !       -i.(bxc)*(wx1+dcos(theta0)*wx*theta1)
     614                 :           0 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) - bxc*(wy1_re+dcos(theta0)*wy*theta1_re)
     615                 :           0 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) + bxc*(wx1_im+dcos(theta0)*wx*theta1_im)
     616                 :           0 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) - bxc*(wy1_im+dcos(theta0)*wy*theta1_im)
     617                 :           0 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) - bxc*(wx1_re+dcos(theta0)*wx*theta1_re)
     618                 :             :          else
     619                 :             :            !small theta case:
     620                 :             :            !zero order terms O(1)
     621                 :           0 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) + bxc*mx1_re/abs(mag(ipt,3))
     622                 :           0 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) + bxc*my1_im/abs(mag(ipt,3))
     623                 :           0 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) + bxc*mx1_im/abs(mag(ipt,3))
     624                 :           0 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) - bxc*my1_re/abs(mag(ipt,3))
     625                 :             :            !first order terms:
     626                 :           0 :            fact = bxc/(mag(ipt,3)*abs(mag(ipt,3)))
     627                 :           0 :            vxc1_out(2*ipt-1,1) = vxc1_out(2*ipt-1,1) - (mag(ipt,1)*mx1_re+mag(ipt,2)*my1_re)*fact
     628                 :           0 :            vxc1_out(2*ipt-1,2) = vxc1_out(2*ipt-1,2) + (mag(ipt,1)*mx1_re+mag(ipt,2)*my1_re)*fact
     629                 :           0 :            vxc1_out(2*ipt  ,1) = vxc1_out(2*ipt  ,1) - (mag(ipt,1)*mx1_im+mag(ipt,2)*my1_im)*fact
     630                 :           0 :            vxc1_out(2*ipt  ,2) = vxc1_out(2*ipt  ,2) + (mag(ipt,1)*mx1_im+mag(ipt,2)*my1_im)*fact
     631                 :             : 
     632                 :           0 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) -  mag(ipt,1)*mz1_re*fact
     633                 :           0 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) -  mag(ipt,2)*mz1_im*fact
     634                 :           0 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) +  mag(ipt,2)*mz1_re*fact
     635                 :           0 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) -  mag(ipt,1)*mz1_im*fact
     636                 :             :          endif
     637                 :             : 
     638                 :             :        else ! Magnetization is practically zero
     639                 :             : !        Compute Bxc/|m| from Kxc (zero limit)
     640                 :           0 :          bxc_over_m = half*(half*(kxc(ipt,1)+kxc(ipt,3))-kxc(ipt,2))
     641                 :           0 :          vxc1_out(2*ipt-1,1)= dvdn_re + bxc_over_m*mz1_re
     642                 :           0 :          vxc1_out(2*ipt  ,1)= dvdn_im + bxc_over_m*mz1_im
     643                 :           0 :          vxc1_out(2*ipt-1,2)= dvdn_re - bxc_over_m*mz1_re
     644                 :           0 :          vxc1_out(2*ipt  ,2)= dvdn_im - bxc_over_m*mz1_im
     645                 :           0 :          vxc1_out(2*ipt-1,3)= bxc_over_m*( mx1_re+my1_im)
     646                 :           0 :          vxc1_out(2*ipt  ,3)= bxc_over_m*(-my1_re+mx1_im)
     647                 :             :        end if
     648                 :             :        !finally reconstruct i.V^12 from V^12
     649                 :           0 :        vxc1_out(2*ipt-1,4) =  vxc1_out(2*ipt  ,3)  ! Re[i.V^21] = Im[V^12]
     650                 :           0 :        vxc1_out(2*ipt  ,4) =  vxc1_out(2*ipt-1,3)  ! Im[i.V^21] = Re[V^12]
     651                 :             : 
     652                 :             :      end do ! ipt
     653                 :             : 
     654                 :             :    end select
     655                 :             : 
     656                 :             : !----------------------------------------
     657                 :             : ! Explicit derivative of the rotated XC functional
     658                 :             : !----------------------------------------
     659                 :             :  case (3)
     660                 :             :    ! Brute-force derivative of Vxc
     661                 :             :    ! Explicit calculation of the rotated xc functional
     662                 :             :    ! (derivatives of the analytical expression) (Eq. A)
     663                 :             :    ! Vxc^(1) =   phixc^(1).Id +                    // <= change of "electrostatic" XC potential  (phixc^(1) is denoted dvdn)
     664                 :             :    !           + bxc^(1)*(sigma,m^(0))/|m^(0)|  +  // <= this term is equivalent to ( Udag^(0).sigma_z.U^(0) ) term in rotation_method=2
     665                 :             :    !           + bxc^(0)*(sigma,m^(1)))/|m^(0)| -  // <= the last terms are equivalent to ( Udag^(1).sigma_z.U^(0) + Udag^(0).sigma_z.U^(1) )
     666                 :             :    !           - bxc^(0)*(sigma,m^(0))*(m^(1),m^(0))/|m^(0)|**3
     667   [ +  +  +  - ]:         997 :    select case(cplex)
     668                 :             :    case(1)
     669                 :             : 
     670         [ +  + ]:      992000 :      do ipt=1,vectsize
     671                 :             : 
     672         [ +  - ]:      991765 :        if (has_mag_norm) then
     673                 :      991765 :          m_norm=mag_norm_in(ipt)
     674                 :             :        else
     675                 :           0 :          m_norm=sqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     676                 :             :        end if
     677                 :             : 
     678                 :             : !      dvdn is phixc^(1) (density only part)
     679                 :             : !      dvdz is bxc^(1)   (magnetization magnitude part)
     680                 :      991765 :        dvdn=(vxc1_in(ipt,1)+vxc1_in(ipt,2))*half
     681                 :      991765 :        dvdz=(vxc1_in(ipt,1)-vxc1_in(ipt,2))*half
     682                 :             : 
     683                 :      991765 :        mx1=rho1(ipt,2) ; my1=rho1(ipt,3) ; mz1=rho1(ipt,4)
     684                 :             : 
     685         [ +  + ]:      992000 :        if(m_norm>m_norm_min) then
     686                 :             : 
     687                 :      798449 :          mdirx=mag(ipt,1)/m_norm; mdiry=mag(ipt,2)/m_norm; mdirz=mag(ipt,3)/m_norm
     688                 :             : 
     689                 :             :          !This part describes the change of the magnitude of the xc magnetic field
     690                 :             :          !and the change of the scalar part of the xc electrostatic potential, 1st + 2nd term in Eq.A
     691                 :             :          !phixc^(1).Id + bxc^(1) (sigma,m^(0))/|m^(0)|
     692                 :      798449 :          vxc1_out(ipt,1)= dvdn+dvdz*mdirz
     693                 :      798449 :          vxc1_out(ipt,2)= dvdn-dvdz*mdirz
     694                 :      798449 :          vxc1_out(ipt,3)= dvdz*mdirx   ! Real part
     695                 :      798449 :          vxc1_out(ipt,4)=-dvdz*mdiry   ! Imaginary part, minus sign comes from sigma_y
     696                 :             : 
     697         [ +  + ]:      798449 :          if (option/=0) then
     698                 :             :            !Add remaining contributions coming from the change of magnetization direction
     699                 :             :            !projection of m^(1) on gs magnetization direction
     700                 :      255944 :            m_dot_m1=(mdirx*rho1(ipt,2)+mdiry*rho1(ipt,3)+mdirz*rho1(ipt,4))
     701                 :             : 
     702                 :      255944 :            bxc_over_m =-dsqrt(((vxc(ipt,1)-vxc(ipt,2))*half)**2+vxc(ipt,3)**2+vxc(ipt,4)**2) !this is bxc^(0)
     703                 :      255944 :            bxc_over_m = bxc_over_m/m_norm
     704                 :      255944 :            vxc1_out(ipt,1) = vxc1_out(ipt,1) + bxc_over_m*( mz1 - mdirz*m_dot_m1 ) !
     705                 :      255944 :            vxc1_out(ipt,2) = vxc1_out(ipt,2) + bxc_over_m*(-mz1 + mdirz*m_dot_m1 ) !
     706                 :      255944 :            vxc1_out(ipt,3) = vxc1_out(ipt,3) + bxc_over_m*( mx1 - mdirx*m_dot_m1 ) !
     707                 :      255944 :            vxc1_out(ipt,4) = vxc1_out(ipt,4) + bxc_over_m*(-my1 + mdiry*m_dot_m1 ) !
     708                 :             :          endif
     709                 :             : 
     710                 :             :        else
     711         [ +  + ]:      193316 :          if (option/=0) then
     712                 :             :            !Compute bxc^(0)/|m| from kxc (|m^(0)| -> zero limit)
     713                 :       29621 :            bxc_over_m = half*(half*(kxc(ipt,1)+kxc(ipt,3))-kxc(ipt,2))
     714                 :       29621 :            vxc1_out(ipt,1)= dvdn + bxc_over_m*mz1
     715                 :       29621 :            vxc1_out(ipt,2)= dvdn - bxc_over_m*mz1
     716                 :       29621 :            vxc1_out(ipt,3)= bxc_over_m*mx1
     717                 :       29621 :            vxc1_out(ipt,4)=-bxc_over_m*my1
     718                 :             :          else
     719                 :      163695 :            vxc1_out(ipt,1)= dvdn
     720                 :      163695 :            vxc1_out(ipt,2)= dvdn
     721                 :      163695 :            vxc1_out(ipt,3)= zero
     722                 :      163695 :            vxc1_out(ipt,4)= zero
     723                 :             :          endif
     724                 :             :        end if
     725                 :             : 
     726                 :             :      end do ! ipt
     727                 :             : 
     728                 :             :    case(2)
     729                 :             :      !cplex=2 case
     730                 :             : 
     731   [ +  +  -  +  :     2345708 :      do ipt=1,vectsize
                      + ]
     732                 :             : 
     733         [ +  - ]:     2344960 :        if (has_mag_norm) then
     734                 :     2344960 :          m_norm=mag_norm_in(ipt)
     735                 :             :        else
     736                 :           0 :          m_norm=sqrt(mag(ipt,1)**2+mag(ipt,2)**2+mag(ipt,3)**2)
     737                 :             :        end if
     738                 :             : 
     739                 :             : !      see cplex=1 case for details
     740                 :     2344960 :        dvdn_re=(vxc1_in(2*ipt-1,1)+vxc1_in(2*ipt-1,2))*half
     741                 :     2344960 :        dvdn_im=(vxc1_in(2*ipt  ,1)+vxc1_in(2*ipt  ,2))*half
     742                 :     2344960 :        dvdz_re=(vxc1_in(2*ipt-1,1)-vxc1_in(2*ipt-1,2))*half
     743                 :     2344960 :        dvdz_im=(vxc1_in(2*ipt  ,1)-vxc1_in(2*ipt  ,2))*half
     744                 :             : 
     745                 :     2344960 :        mx1_re=rho1(2*ipt-1,2); mx1_im=rho1(2*ipt,2)
     746                 :     2344960 :        my1_re=rho1(2*ipt-1,3); my1_im=rho1(2*ipt,3)
     747                 :     2344960 :        mz1_re=rho1(2*ipt-1,4); mz1_im=rho1(2*ipt,4)
     748                 :             : 
     749         [ +  + ]:     2344960 :        if(m_norm>m_norm_min) then
     750                 :             : 
     751                 :     1684571 :          mdirx=mag(ipt,1)/m_norm; mdiry=mag(ipt,2)/m_norm; mdirz=mag(ipt,3)/m_norm
     752                 :             : 
     753                 :             :          !first two terms:
     754                 :     1684571 :          vxc1_out(2*ipt-1,1)= dvdn_re+dvdz_re*mdirz
     755                 :     1684571 :          vxc1_out(2*ipt  ,1)= dvdn_im+dvdz_im*mdirz
     756                 :     1684571 :          vxc1_out(2*ipt-1,2)= dvdn_re-dvdz_re*mdirz
     757                 :     1684571 :          vxc1_out(2*ipt  ,2)= dvdn_im-dvdz_im*mdirz
     758                 :             :          !NOTE: change of definition of the potential matrix components
     759                 :             :          !      vxc1_out(:,3) =   V_updn
     760                 :             :          !      vxc1_out(:,4) = i.V_dnup
     761                 :             : 
     762                 :             :          !  V^12 =   dvdz*mx/|m| - i.dvdz*my/|m| = (Re[dvdz]*mx/|m| + Im[dvdz]*my/|m|) + i.(Im[dvdz]*mx/|m| - Re[dvdz]*my/|m|) => vxc1(:,3)
     763                 :             :          !  V^21 =   dvdz*mx/|m| + i.dvdz*my/|m| = (Re[dvdz]*mx/|m| - Im[dvdz]*my/|m|) + i.(Im[dvdz]*mx/|m| + Re[dvdz]*my/|m|)
     764                 :     1684571 :          vxc1_out(2*ipt-1,3)= dvdz_re*mdirx + dvdz_im*mdiry   !Re[V^12]
     765                 :     1684571 :          vxc1_out(2*ipt  ,3)= dvdz_im*mdirx - dvdz_re*mdiry   !Im[V^12]
     766                 :     1684571 :          vxc1_out(2*ipt-1,4)= dvdz_re*mdirx - dvdz_im*mdiry   !Re[V^21]
     767                 :     1684571 :          vxc1_out(2*ipt  ,4)= dvdz_im*mdirx + dvdz_re*mdiry   !Im[V^21]
     768         [ +  + ]:     1684571 :          if (option/=0) then
     769                 :             : 
     770                 :             :            !remaining contributions:
     771                 :      571295 :            m_dot_m1_re= mdirx*mx1_re + mdiry*my1_re + mdirz*mz1_re
     772                 :      571295 :            m_dot_m1_im= mdirx*mx1_im + mdiry*my1_im + mdirz*mz1_im
     773                 :             : 
     774                 :      571295 :            bxc_over_m =-dsqrt(((vxc(ipt,1)-vxc(ipt,2))*half)**2+vxc(ipt,3)**2+vxc(ipt,4)**2) !this is bxc^(0)
     775                 :      571295 :            bxc_over_m = bxc_over_m/m_norm
     776                 :             :           !bxc_over_m = (vxc(ipt,1)-vxc(ipt,2))*half/mag(ipt,3)
     777                 :             : 
     778                 :      571295 :            vxc1_out(2*ipt-1,1) = vxc1_out(2*ipt-1,1) + bxc_over_m*( mz1_re - mdirz*m_dot_m1_re ) ! Re[V^11]
     779                 :      571295 :            vxc1_out(2*ipt  ,1) = vxc1_out(2*ipt  ,1) + bxc_over_m*( mz1_im - mdirz*m_dot_m1_im ) ! Im[V^11]
     780                 :      571295 :            vxc1_out(2*ipt-1,2) = vxc1_out(2*ipt-1,2) + bxc_over_m*(-mz1_re + mdirz*m_dot_m1_re ) ! Re[V^22]
     781                 :      571295 :            vxc1_out(2*ipt  ,2) = vxc1_out(2*ipt  ,2) + bxc_over_m*(-mz1_im + mdirz*m_dot_m1_im ) ! Im[V^22]
     782                 :             : 
     783                 :             :            !    v12  += bxc_over_m*(   (mx1    - mdirx*m_dot_m1   ) - i.( my1    - mdiry*m_dot_m1   )   )  <= see cplex=1
     784                 :             :            ! Re[v12] += bxc_over_m*(   (mx1_re - mdirx*m_dot_m1_re) +   ( my1_im - mdiry*m_dot_m1_im)   )
     785                 :             :            ! Im[v12] += bxc_over_m*(   (mx1_im - mdirx*m_dot_m1_im) +   (-my1_re + mdiry*m_dot_m1_re)   )
     786                 :      571295 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) + bxc_over_m*( mx1_re - mdirx*m_dot_m1_re ) ! Re[V^12]
     787                 :      571295 :            vxc1_out(2*ipt-1,3) = vxc1_out(2*ipt-1,3) + bxc_over_m*( my1_im - mdiry*m_dot_m1_im ) ! Re[V^12]
     788                 :      571295 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) + bxc_over_m*( mx1_im - mdirx*m_dot_m1_im ) ! Im[V^12]
     789                 :      571295 :            vxc1_out(2*ipt  ,3) = vxc1_out(2*ipt  ,3) + bxc_over_m*(-my1_re + mdiry*m_dot_m1_re ) ! Im[V^12]
     790                 :             : 
     791                 :             :            !    v21  += bxc_over_m*(   (mx1    - mdirx*m_dot_m1   ) + i.( my1    - mdiry*m_dot_m1   )   )
     792                 :             :            ! Re[v21] += bxc_over_m*(   (mx1_re - mdirx*m_dot_m1_re) +   (-my1_im + mdiry*m_dot_m1_im)   )
     793                 :             :            ! Im[v21] += bxc_over_m*(   (mx1_im - mdirx*m_dot_m1_im) +   ( my1_re - mdiry*m_dot_m1_re)   )
     794                 :             :            ! the 4th component is actually not v21, but rather i.v21, this will be adjusted later
     795                 :      571295 :            vxc1_out(2*ipt-1,4) = vxc1_out(2*ipt-1,4) + bxc_over_m*( mx1_re - mdirx*m_dot_m1_re ) ! Re[V^21]
     796                 :      571295 :            vxc1_out(2*ipt-1,4) = vxc1_out(2*ipt-1,4) + bxc_over_m*(-my1_im + mdiry*m_dot_m1_im ) ! Re[V^21]
     797                 :      571295 :            vxc1_out(2*ipt  ,4) = vxc1_out(2*ipt  ,4) + bxc_over_m*( mx1_im - mdirx*m_dot_m1_im ) ! Im[V^21]
     798                 :      571295 :            vxc1_out(2*ipt  ,4) = vxc1_out(2*ipt  ,4) + bxc_over_m*( my1_re - mdiry*m_dot_m1_re ) ! Im[V^21]
     799                 :             :          endif
     800                 :             :        else
     801         [ +  + ]:      660389 :          if(option/=0) then
     802                 :             :            !Compute Bxc/|m| from Kxc (|m^(0)| -> zero limit)
     803                 :       84065 :            bxc_over_m = half*(half*(kxc(ipt,1)+kxc(ipt,3))-kxc(ipt,2))
     804                 :       84065 :            vxc1_out(2*ipt-1,1)= dvdn_re + bxc_over_m*mz1_re
     805                 :       84065 :            vxc1_out(2*ipt-1,2)= dvdn_re - bxc_over_m*mz1_re
     806                 :       84065 :            vxc1_out(2*ipt  ,1)= dvdn_im + bxc_over_m*mz1_im
     807                 :       84065 :            vxc1_out(2*ipt  ,2)= dvdn_im - bxc_over_m*mz1_im
     808                 :             : 
     809                 :       84065 :            vxc1_out(2*ipt-1,3)= bxc_over_m*(mx1_re+my1_im)
     810                 :       84065 :            vxc1_out(2*ipt  ,3)= bxc_over_m*(mx1_im-my1_re)
     811                 :       84065 :            vxc1_out(2*ipt-1,4)= bxc_over_m*(mx1_re-my1_im)
     812                 :       84065 :            vxc1_out(2*ipt  ,4)= bxc_over_m*(mx1_im+my1_re)
     813                 :             :          else
     814                 :      576324 :            vxc1_out(2*ipt-1,1)= dvdn_re
     815                 :      576324 :            vxc1_out(2*ipt-1,2)= dvdn_re
     816                 :      576324 :            vxc1_out(2*ipt  ,1)= dvdn_im
     817                 :      576324 :            vxc1_out(2*ipt  ,2)= dvdn_im
     818                 :             : 
     819                 :      576324 :            vxc1_out(2*ipt-1,3)= zero
     820                 :      576324 :            vxc1_out(2*ipt  ,3)= zero
     821                 :      576324 :            vxc1_out(2*ipt-1,4)= zero
     822                 :      576324 :            vxc1_out(2*ipt  ,4)= zero
     823                 :             :          endif
     824                 :             :        end if
     825                 :             : 
     826                 :             :        !finally reconstruct i.V^21 from V^21
     827                 :     2344960 :        v21tmp(1) = vxc1_out(2*ipt-1,4) !Re[V^21]
     828                 :     2344960 :        v21tmp(2) = vxc1_out(2*ipt  ,4) !Im[V^21]
     829                 :             : 
     830                 :     2344960 :        vxc1_out(2*ipt-1,4) =-v21tmp(2) ! Re[i.V^21]=-Im[V^21]
     831                 :     2345473 :        vxc1_out(2*ipt  ,4) = v21tmp(1) ! Im[i.V^21]= Re[V^21]
     832                 :             : 
     833                 :             :      end do ! ipt
     834                 :             : 
     835                 :             :    end select !cplex
     836                 :             : 
     837                 :             :  end select ! rotation_method
     838                 :             : 
     839                 :             : !DBG_EXIT("COLL")
     840                 :             : 
     841                 :         997 : end subroutine rotate_back_mag_dfpt
     842                 :             : !!***
     843                 :             : 
     844                 :             : 
     845                 :             : !!****f* ABINIT/m_xc_noncoll/test_rotations
     846                 :             : !! NAME
     847                 :             : !!  test_rotations
     848                 :             : !!
     849                 :             : !! FUNCTION
     850                 :             : !!  Test three different methods in rotate_back_mag_dfpt
     851                 :             : !!
     852                 :             : !! INPUTS
     853                 :             : !!  option= types of tests to perform
     854                 :             : !!          0=> only quick tests
     855                 :             : !!          1=> quick and slow tests
     856                 :             : !!  cplex = complex or real potential and first order magnetization
     857                 :             : !!
     858                 :             : !! OUTPUT
     859                 :             : !!
     860                 :             : !! SIDE EFFECTS
     861                 :             : !!
     862                 :             : !! NOTES
     863                 :             : !!
     864                 :             : !!  For debug purposes
     865                 :             : !!
     866                 :             : !! SOURCE
     867                 :             : 
     868                 :           0 : subroutine test_rotations(option,cplex)
     869                 :             : 
     870                 :             : !Arguments ------------------------------------
     871                 :             :  integer , intent(in)  :: option
     872                 :             :  integer , intent(in)  :: cplex
     873                 :             : 
     874                 :             : !Local variables-------------------------------
     875                 :             :  real(dp) :: m0(1,3),vxc0(1,4),kxc(1,3)
     876                 :           0 :  real(dp) :: n1(cplex,4),vxc1_in(cplex,4),vxc1_out(cplex,4)
     877                 :           0 :  real(dp) :: delta_23(cplex,4) !,delta_12(cplex,4)
     878                 :             :  real(dp) :: m0_norm,dvdn,dvdz,err23 !,wrong_comp!,err12
     879                 :             :  real(dp) :: theta0,phi0,theta1,phi1,err,m1_norm
     880                 :             :  integer  :: dir0,dir1
     881                 :             : ! *************************************************************************
     882                 :             : 
     883                 :             :  DBG_ENTER("COLL")
     884                 :             : 
     885                 :             : ! if (option/=1 .and. option/=2 ) then
     886                 :             : !  write(msg,'(3a,i0)')&
     887                 :             : !&  'The argument option should be 1 or 2,',ch10,&
     888                 :             : !&  'however, option=',option
     889                 :             : !  ABI_BUG(msg)
     890                 :             : ! end if
     891                 :             : !
     892                 :             : ! if (sizein<1) then
     893                 :             : !  write(msg,'(3a,i0)')&
     894                 :             : !&  '  The argument sizein should be a positive number,',ch10,&
     895                 :             : !&  '  however, sizein=',sizein
     896                 :             : !  ABI_ERROR(msg)
     897                 :             : ! end if
     898                 :             : 
     899                 :             :  DBG_EXIT("COLL")
     900                 :             : 
     901                 :             :  !write(*,*)    'VXC_NONCOLL TESTS================================================================'
     902         [ #  # ]:           0 :  if (cplex==1) then
     903                 :             :     !write(*,*) '  cplex=1------------------------------------------------------------------------'
     904                 :             : 
     905                 :             :     !write(*,*) '    TEST: simple  m* orietnations, bxc^(1) part'
     906                 :             :     dvdn=zero;dvdz=1.0!
     907                 :             :     err23=zero
     908         [ #  # ]:           0 :     do dir0=1,3
     909   [ #  #  #  # ]:           0 :     m0=zero; n1=zero
     910         [ #  # ]:           0 :       do dir1=2,4
     911                 :           0 :         m0(1,dir0)=0.1
     912                 :           0 :         m0_norm=sqrt(m0(1,1)**2+m0(1,2)**2+m0(1,3)**2)
     913                 :           0 :         n1(1,dir1)=0.8     ! any number would do here
     914                 :             : 
     915                 :           0 :         vxc0=zero;     ! no bxc^(0) part at all
     916                 :             : 
     917                 :           0 :         vxc1_in(1,1)= dvdn+dvdz
     918                 :           0 :         vxc1_in(1,2)= dvdn-dvdz
     919                 :             : 
     920                 :           0 :         call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=1)
     921                 :           0 :         call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=2)
     922   [ #  #  #  # ]:           0 :         delta_23=vxc1_out
     923                 :           0 :         call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=3)
     924   [ #  #  #  # ]:           0 :         delta_23=abs(delta_23-vxc1_out)
     925                 :           0 :         err=max(delta_23(1,1),delta_23(1,2),delta_23(1,3),delta_23(1,4))
     926                 :           0 :         if (err23<err) err23=err;
     927                 :             : 
     928                 :             :       enddo
     929                 :             :     enddo
     930                 :             :     !write(*,*) '    maximum mismatch between methods 2 and 3:',err23
     931                 :             : 
     932                 :             :     !write(*,*) '    TEST: simple  m* orietnations, bxc^(0) part'
     933                 :             : 
     934                 :             :     err23=zero
     935                 :             :     dvdn=zero;dvdz=1.0
     936         [ #  # ]:           0 :     do dir0=1,3
     937   [ #  #  #  # ]:           0 :     m0=zero; n1=zero
     938         [ #  # ]:           0 :       do dir1=2,4
     939                 :           0 :         m0(1,dir0)=0.1
     940                 :           0 :         m0_norm=sqrt(m0(1,1)**2+m0(1,2)**2+m0(1,3)**2)
     941                 :           0 :         n1(1,dir1)=0.8     ! =m^1, any number would do here
     942                 :             : 
     943                 :           0 :         vxc0(1,1) = dvdn+dvdz*m0(1,3)/m0_norm
     944                 :           0 :         vxc0(1,2) = dvdn-dvdz*m0(1,3)/m0_norm
     945                 :           0 :         vxc0(1,3) = dvdz*m0(1,1)/m0_norm
     946                 :           0 :         vxc0(1,4) =-dvdz*m0(1,2)/m0_norm
     947                 :             : 
     948   [ #  #  #  # ]:           0 :         vxc1_in=zero !vxc^(1) collinear is zero
     949                 :             : 
     950                 :           0 :         call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=1)
     951                 :           0 :         call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=2)
     952   [ #  #  #  # ]:           0 :         delta_23=vxc1_out
     953                 :           0 :         call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=3)
     954   [ #  #  #  # ]:           0 :         delta_23=abs(delta_23-vxc1_out)
     955                 :           0 :         err=maxval(abs(delta_23(1,:)))
     956                 :           0 :         if (err23<err) err23=err;
     957                 :             :       enddo
     958                 :             :     enddo
     959                 :             :     !write(*,*) '    maximum mismatch between methods 2 and 3:',err23
     960                 :             : 
     961                 :             :     !write(*,*) '    TEST: general m0 orietnations, bxc^(0) part'
     962                 :             : 
     963                 :             :     theta0=zero
     964                 :             :     err23=zero
     965                 :           0 :     m0_norm=0.3
     966         [ #  # ]:           0 :     do while(theta0<=pi)
     967                 :             :       phi0=zero
     968         [ #  # ]:           0 :       do while(phi0<=2*pi)
     969                 :           0 :         m0(1,1)=m0_norm*sin(theta0)*cos(phi0)
     970                 :           0 :         m0(1,2)=m0_norm*sin(theta0)*sin(phi0)
     971                 :           0 :         m0(1,3)=m0_norm*cos(theta0)
     972                 :             : 
     973         [ #  # ]:           0 :         do  dir1=2,4
     974   [ #  #  #  # ]:           0 :           n1=zero
     975                 :           0 :           n1(1,dir1)=0.8     ! =m^1, any number would do here
     976                 :             : 
     977                 :             :           !vxc0=zero;     !
     978                 :           0 :           vxc0(1,1) = dvdn+dvdz*m0(1,3)/m0_norm
     979                 :           0 :           vxc0(1,2) = dvdn-dvdz*m0(1,3)/m0_norm
     980                 :           0 :           vxc0(1,3) = dvdz*m0(1,1)/m0_norm
     981                 :           0 :           vxc0(1,4) =-dvdz*m0(1,2)/m0_norm
     982                 :             : 
     983   [ #  #  #  # ]:           0 :           vxc1_in=zero
     984                 :             : 
     985                 :             :           !call rotate_back_mag_dfpt(vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=1)
     986                 :           0 :           call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=2)
     987   [ #  #  #  # ]:           0 :           delta_23=vxc1_out
     988                 :           0 :           call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=3)
     989   [ #  #  #  # ]:           0 :           delta_23=abs(delta_23-vxc1_out)
     990                 :           0 :           err=maxval(abs(delta_23(1,:)))
     991                 :           0 :           if (err23<err) err23=err;
     992                 :             :         enddo
     993                 :           0 :         phi0=phi0+2*pi/100.0
     994                 :             :       enddo
     995                 :           0 :       theta0=theta0+pi/100.0
     996                 :             :     enddo
     997                 :             :     !write(*,*) '    maximum mismatch between methods 2 and 3:',err23
     998                 :             : 
     999         [ #  # ]:           0 :     if(option==2) then
    1000                 :             :     !write(*,*) '    TEST: general m* orietnations, bxc^(0) part'
    1001                 :             :     dvdn=zero;dvdz=1.0
    1002                 :             : 
    1003                 :             :     theta0=zero
    1004                 :             :     err23=zero
    1005                 :           0 :     m0_norm=0.3
    1006                 :             :     m1_norm=10.5
    1007         [ #  # ]:           0 :     do while(theta0<=pi) !loops on orientation of m^(0)
    1008                 :             :       phi0=zero
    1009         [ #  # ]:           0 :       do while(phi0<=2*pi)
    1010                 :           0 :         m0(1,1)=m0_norm*sin(theta0)*cos(phi0)
    1011                 :           0 :         m0(1,2)=m0_norm*sin(theta0)*sin(phi0)
    1012                 :           0 :         m0(1,3)=m0_norm*cos(theta0)
    1013                 :             : 
    1014                 :           0 :         vxc0(1,1) = dvdn+dvdz*m0(1,3)/m0_norm
    1015                 :           0 :         vxc0(1,2) = dvdn-dvdz*m0(1,3)/m0_norm
    1016                 :           0 :         vxc0(1,3) = dvdz*m0(1,1)/m0_norm
    1017                 :           0 :         vxc0(1,4) =-dvdz*m0(1,2)/m0_norm
    1018                 :             : 
    1019   [ #  #  #  # ]:           0 :         vxc1_in=zero
    1020                 :             : 
    1021                 :             :         theta1=zero
    1022         [ #  # ]:           0 :         do while(theta1<=pi) !loops on orientation of m^(1)
    1023                 :             :           phi1=zero
    1024         [ #  # ]:           0 :           do while(phi1<=2*pi)
    1025                 :           0 :             n1(1,1)=zero
    1026                 :           0 :             n1(1,2)=m1_norm*sin(theta1)*cos(phi1)
    1027                 :           0 :             n1(1,3)=m1_norm*sin(theta1)*sin(phi1)
    1028                 :           0 :             n1(1,4)=m1_norm*cos(theta1)
    1029                 :             : 
    1030                 :             :             !vxc0=zero;     !
    1031                 :             :             !call rotate_back_mag_dfpt(vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=1)
    1032                 :           0 :             call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=2)
    1033   [ #  #  #  # ]:           0 :             delta_23=vxc1_out
    1034                 :           0 :             call rotate_back_mag_dfpt(1,vxc1_in,vxc1_out,vxc0,kxc,n1,m0,1,1,rot_method=3)
    1035   [ #  #  #  # ]:           0 :             delta_23=abs(delta_23-vxc1_out)
    1036                 :           0 :             err=maxval(abs(delta_23(1,:)))
    1037                 :             :             if (err23<err) err23=err;
    1038                 :           0 :             phi1=phi1+2*pi/100.0
    1039                 :             :           enddo
    1040                 :           0 :           theta1=theta1+pi/100.0
    1041                 :             :         enddo
    1042                 :             : 
    1043                 :           0 :         phi0=phi0+2*pi/100.0
    1044                 :             :       enddo
    1045                 :           0 :       theta0=theta0+pi/100.0
    1046                 :             :     enddo
    1047                 :             :     !write(*,*) '    maximum mismatch between methods 2 and 3:',err23
    1048                 :             :     endif
    1049                 :             : 
    1050                 :             :  !else !cplex=2
    1051                 :             : 
    1052                 :             :  endif
    1053                 :             : 
    1054                 :           0 : end subroutine test_rotations
    1055                 :             : !!***
    1056                 :             : 
    1057                 :             : 
    1058                 :             : !----------------------------------------------------------------------
    1059                 :             : 
    1060                 :             : END MODULE m_xc_noncoll
    1061                 :             : !!***
        

Generated by: LCOV version 2.3-1