Line data Source code
1 : !!****m* ABINIT/m_dens
2 : !! NAME
3 : !! m_dens
4 : !!
5 : !! FUNCTION
6 : !! Module containing the definition of the constrained_dft_t data type and methods used to handle it,
7 : !! and also includes the computation of integrated atomic charge and magnetization, as well as Hirshfeld charges.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 1998-2026 ABINIT group (MT,ILuk,MVer,EB,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 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : MODULE m_dens
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_xmpi
29 : use m_splines
30 :
31 : use defs_abitypes, only : MPI_type
32 : use m_fft, only : fourdp,fftpac
33 : use m_time, only : timab
34 : use m_numeric_tools, only : wrap2_zero_one, geteuler
35 : use m_io_tools, only : open_file
36 : use m_geometry, only : dist2, xcart2xred, metric, vcart2ylm, cart2spinaxis
37 : use m_mpinfo, only : ptabs_fourdp
38 : use m_atomdata
39 : use m_dtset
40 :
41 : implicit none
42 :
43 : private
44 :
45 : public :: dens_hirsh ! Compute the Hirshfeld charges
46 : public :: add_atomic_fcts ! Add atomic functions to real space function
47 : public :: constrained_dft_ini ! Initialize the constrained_dft datastructure
48 : public :: constrained_dft_free ! Free the constrained_dft datastructure
49 : public :: constrained_residual ! Recompute the potential residual, to account for constraints
50 : public :: mag_penalty ! Compute the potential corresponding to constrained magnetic moments (using add_atomic_fcts) with the penalty function.
51 : public :: mag_penalty_e ! Compute the energy corresponding to constrained magnetic moments.
52 : public :: calcdenmagsph ! Compute integral of total density and magnetization inside spheres around atoms.
53 : public :: prtdenmagsph ! Print integral of total density and magnetization inside spheres around atoms.
54 : public :: magmom_to_d2 ! Integrates the magnetic moments (total & local ones) into the ddb array.
55 : public :: fatsph_recip ! Compute atom centered spheres in reciprocal space
56 : public :: calmaxdifmag ! Compute the maximum magnetization and the maximum change in magnetization between two steps.
57 : !!***
58 :
59 : !----------------------------------------------------------------------
60 :
61 : !!****t* m_dens/constrained_dft_t
62 : !! NAME
63 : !! constrained_dft_t
64 : !!
65 : !! FUNCTION
66 : !! Structure gathering the relevant information for constrained DFT calculations
67 : !!
68 : !! SOURCE
69 :
70 : type,public :: constrained_dft_t
71 :
72 : !scalars
73 : integer :: natom ! Number of atoms
74 : integer :: nfftf ! Number of FFT grid points (for this processor) for the "fine" grid
75 : integer :: nspden ! Number of spin-density components
76 : integer :: ntypat ! Number of type of atoms
77 :
78 : real(dp) :: magcon_lambda ! Strength of the atomic spherical constraint
79 : real(dp) :: ratsm ! Smearing width for ratsph
80 :
81 : integer :: magconon ! Turn on the penalty function constraint instead of the more powerful constrainedDFT algorithm
82 :
83 : !arrays
84 :
85 : integer :: ngfftf(18) ! Number of FFT grid points (for this processor) for the "fine" grid
86 :
87 : integer,allocatable :: typat(:)
88 : ! typat(natom)
89 : ! Type of each natom
90 :
91 : integer,allocatable :: constraint_kind(:)
92 : ! constraint_kind(ntypat)
93 : ! Constraint kind to be applied to each type of atom. See corresponding input variable
94 :
95 : real(dp) :: rprimd(3,3)
96 : ! Direct lattice vectors, Bohr units.
97 :
98 : real(dp),allocatable :: chrgat(:)
99 : ! chrgat(natom)
100 : ! Target charge for each atom. Not always used, it depends on the value of constraint_kind
101 :
102 : real(dp),allocatable :: intgf2(:,:)
103 : ! intgf2(natom,natom)
104 : ! Overlap of the spherical integrating functions, for each atom.
105 : ! Initialized using some xred values, will not change during the SCF cycles, except for exotic algorithms, not in production,
106 :
107 : real(dp),allocatable :: ratsph(:)
108 : ! ratsph(ntypat)
109 : ! Radius of the atomic sphere for each type of atom
110 :
111 : real(dp),allocatable :: spinat(:,:)
112 : ! spinat(3,natom)
113 : ! Target magnetization for each atom. Possibly only the direction or the magnitude, depending on constraint_kind
114 :
115 : real(dp),allocatable :: ziontypat(:)
116 : ! ziontypat(ntypat)
117 : ! Ionic charge, per type of atom
118 :
119 : real(dp),allocatable :: znucl(:)
120 : ! znucl(ntypat)
121 : !
122 :
123 : real(dp) :: spinaxis(3)
124 : ! spinaxis(3)
125 : ! Spin quantization axis
126 :
127 : end type constrained_dft_t
128 :
129 : !!***
130 :
131 : CONTAINS
132 :
133 : !----------------------------------------------------------------------
134 :
135 : !!****f* m_dens/dens_hirsh
136 : !! NAME
137 : !! dens_hirsh
138 : !!
139 : !! FUNCTION
140 : !! Compute the Hirshfeld charges
141 : !!
142 : !! INPUTS
143 : !! mpoint=Maximum number of points in radial meshes.
144 : !! radii(mpoint, ntypat)=Radial meshes for each type
145 : !! aeden(mpoint, nytpat)=All-electron densities.
146 : !! npoint(ntypat)=The number of the last point with significant density is stored in npoint(itypat)
147 : !! minimal_den=Tolerance on the minum value of the density
148 : !! grid_den(nrx,nry,nrz)= density on the grid
149 : !! natom = number of atoms in the unit cell
150 : !! nrx,nry,nrz= number of points in the grid for the three directions
151 : !! ntypat=number of types of atoms in unit cell.
152 : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
153 : !! typat(natom)=type of each atom
154 : !! xcart(3,natom) = different positions of the atoms in the unit cell
155 : !! zion=(ntypat)gives the ionic charge for each type of atom
156 : !! prtcharge=1 to write the Hirshfeld charge decomposition
157 : !!
158 : !! OUTPUT
159 : !! hcharge(natom), hden(natom), hweight(natom)= Hirshfeld charges, densities, weights.
160 : !!
161 : !! SOURCE
162 :
163 1 : subroutine dens_hirsh(mpoint,radii,aeden,npoint,minimal_den,grid_den, &
164 1 : natom,nrx,nry,nrz,ntypat,rprimd,xcart,typat,zion,prtcharge,hcharge,hden,hweight)
165 :
166 : !Arguments ------------------------------------
167 : !scalars
168 : integer,intent(in) :: natom,nrx,nry,nrz,ntypat,prtcharge,mpoint
169 : real(dp),intent(in) :: minimal_den
170 : !arrays
171 : integer,intent(in) :: typat(natom),npoint(ntypat)
172 : real(dp),intent(in) :: grid_den(nrx,nry,nrz),rprimd(3,3),zion(ntypat)
173 : real(dp),intent(in) :: xcart(3,natom)
174 : real(dp),intent(in) :: radii(mpoint,ntypat),aeden(mpoint,ntypat)
175 : real(dp),intent(out) :: hcharge(natom),hden(natom),hweight(natom)
176 :
177 : !Local variables -------------------------
178 : !scalars
179 : integer :: i1,i2,i3,iatom,icell,igrid,ii,inmax,inmin,istep,itypat
180 : integer :: k1,k2,k3,mcells,nfftot,ngoodpoints,npt
181 : real(dp) :: aa,bb,coeff1,coeff2,coeff3,den,factor,h_inv,hh,maxrad
182 : real(dp) :: rr,rr2,total_charge,total_weight,total_zion,ucvol
183 : real(dp) :: yp1,ypn
184 : !arrays
185 : integer :: highest(3),lowest(3)
186 1 : integer,allocatable :: ncells(:)
187 : real(dp) :: coordat(3),coord23_1,coord23_2,coord23_3,diff1,diff2,diff3,gmet(3,3),gprimd(3,3),rmet(3,3)
188 : real(dp) :: vperp(3),width(3)
189 1 : real(dp),allocatable :: coord1(:,:),local_den(:,:,:,:)
190 1 : real(dp),allocatable :: step(:,:),sum_den(:,:,:)
191 1 : real(dp),allocatable :: xcartcells(:,:,:),xred(:,:),yder2(:)
192 : ! *********************************************************************
193 :
194 : !1. Read the 1D all-electron atomic files
195 : !Store the radii in radii(:,itypat), and the all-electron
196 : !densities in aeden(:,itypat). The number of the last
197 : !point with significant density is stored in npoint(itypat)
198 :
199 : !2. Compute the list of atoms that are sufficiently close to the cell
200 :
201 1 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
202 1 : nfftot=nrx*nry*nrz
203 :
204 3 : ABI_MALLOC(xred,(3,natom))
205 1 : call xcart2xred(natom,rprimd,xcart,xred)
206 :
207 : !Compute the widths of the cell
208 : !First width : perpendicular vector length
209 4 : vperp(:)=rprimd(:,1)-rprimd(:,2)*rmet(1,2)/rmet(2,2) -rprimd(:,3)*rmet(1,3)/rmet(3,3)
210 4 : width(1)=sqrt(dot_product(vperp,vperp))
211 : !Second width
212 4 : vperp(:)=rprimd(:,2)-rprimd(:,1)*rmet(2,1)/rmet(1,1) -rprimd(:,3)*rmet(2,3)/rmet(3,3)
213 4 : width(2)=sqrt(dot_product(vperp,vperp))
214 : !Third width
215 4 : vperp(:)=rprimd(:,3)-rprimd(:,1)*rmet(3,1)/rmet(1,1) -rprimd(:,2)*rmet(3,2)/rmet(2,2)
216 4 : width(3)=sqrt(dot_product(vperp,vperp))
217 :
218 : !Compute the number of cells that will make up the supercell
219 3 : ABI_MALLOC(ncells,(natom))
220 1 : mcells=0
221 3 : do iatom=1,natom
222 2 : itypat=typat(iatom)
223 2 : maxrad=radii(npoint(itypat),itypat)
224 : ! Compute the lower and higher indices of the supercell
225 : ! for this atom
226 8 : do ii=1,3
227 6 : lowest(ii)=floor(-xred(ii,iatom)-maxrad/width(ii))
228 8 : highest(ii)=ceiling(-xred(ii,iatom)+maxrad/width(ii)+1)
229 : ! Next coding, still incorrect
230 : ! lowest(ii)=floor(xred(ii,iatom)-maxrad/width(ii))-1
231 : ! highest(ii)=ceiling(xred(ii,iatom)+maxrad/width(ii))+1
232 : ! Old coding incorrect
233 : ! lowest(ii)=ceiling(-xred(ii,iatom)-maxrad/width(ii))
234 : ! highest(ii)=floor(-xred(ii,iatom)+maxrad/width(ii)+1)
235 : end do
236 : ncells(iatom)=(highest(1)-lowest(1)+1)* &
237 : & (highest(2)-lowest(2)+1)* &
238 3 : & (highest(3)-lowest(3)+1)
239 : ! DEBUG
240 : ! write(std_out,*)' maxrad=',maxrad
241 : ! write(std_out,*)' lowest(:)=',lowest(:)
242 : ! write(std_out,*)' highest(:)=',highest(:)
243 : ! write(std_out,*)' ncells(iatom)=',ncells(iatom)
244 : ! ENDDEBUG
245 : end do
246 3 : mcells=maxval(ncells(:))
247 :
248 : !Compute, for each atom, the set of image atoms in the whole supercell
249 4 : ABI_MALLOC(xcartcells,(3,mcells,natom))
250 3 : do iatom=1,natom
251 2 : itypat=typat(iatom)
252 2 : maxrad=radii(npoint(itypat),itypat)
253 : ! Compute the lower and higher indices of the supercell
254 : ! for this atom
255 :
256 8 : do ii=1,3
257 6 : lowest(ii)=floor(-xred(ii,iatom)-maxrad/width(ii))
258 8 : highest(ii)=ceiling(-xred(ii,iatom)+maxrad/width(ii)+1)
259 : end do
260 2 : icell=0
261 16 : do i1=lowest(1),highest(1)
262 104 : do i2=lowest(2),highest(2)
263 739 : do i3=lowest(3),highest(3)
264 637 : icell=icell+1
265 2637 : xcartcells(:,icell,iatom)=xcart(:,iatom)+i1*rprimd(:,1)+i2*rprimd(:,2)+i3*rprimd(:,3)
266 : end do
267 : end do
268 : end do
269 : end do
270 :
271 : !Compute, for each atom, the all-electron pro-atom density
272 : !at each point in the primitive cell
273 6 : ABI_MALLOC(local_den,(nrx,nry,nrz,natom))
274 3 : ABI_MALLOC(step,(2,mpoint))
275 3 : ABI_MALLOC(yder2,(mpoint))
276 3 : ABI_MALLOC(coord1,(3,nrx))
277 1 : coeff1=one/nrx
278 1 : coeff2=one/nry
279 1 : coeff3=one/nrz
280 :
281 3 : do iatom=1,natom
282 2 : itypat=typat(iatom)
283 2 : npt=npoint(itypat)
284 2 : maxrad=radii(npt,itypat)
285 : ! write(std_out,*)
286 : ! write(std_out,'(a,i4)' )' hirsh : accumulating density for atom ',iatom
287 : ! write(std_out,*)' ncells(iatom)=',ncells(iatom)
288 829 : do istep=1,npt-1
289 827 : step(1,istep)=radii(istep+1,itypat) - radii(istep,itypat)
290 829 : step(2,istep)=one/step(1,istep)
291 : end do
292 : ! Approximate first derivative for small radii
293 2 : yp1=(aeden(2,itypat)-aeden(1,itypat))/(radii(2,itypat)-radii(1,itypat))
294 2 : ypn=zero
295 2 : call spline(radii(1:npt,itypat),aeden(1:npt,itypat),npt,yp1,ypn,yder2)
296 :
297 95978 : local_den(:,:,:,iatom)=zero
298 :
299 : ! Big loop on the cells
300 640 : do icell=1,ncells(iatom)
301 : ! write(std_out,*)' icell=',icell
302 2548 : coordat(:)=xcartcells(:,icell,iatom)
303 :
304 : ! Big loop on the grid points
305 23569 : do k1 = 1,nrx
306 92365 : coord1(:,k1)=rprimd(:,1)*(k1-1)*coeff1
307 : end do
308 23571 : do k3 = 1, nrz
309 849121 : do k2 = 1, nry
310 825552 : coord23_1=rprimd(1,2)*(k2-1)*coeff2+rprimd(1,3)*(k3-1)*coeff3-coordat(1)
311 825552 : coord23_2=rprimd(2,2)*(k2-1)*coeff2+rprimd(2,3)*(k3-1)*coeff3-coordat(2)
312 825552 : coord23_3=rprimd(3,2)*(k2-1)*coeff2+rprimd(3,3)*(k3-1)*coeff3-coordat(3)
313 30568356 : do k1 = 1, nrx
314 29719872 : diff1=coord1(1,k1)+coord23_1
315 29719872 : diff2=coord1(2,k1)+coord23_2
316 29719872 : diff3=coord1(3,k1)+coord23_3
317 29719872 : rr2=diff1**2+diff2**2+diff3**2
318 30545424 : if(rr2<maxrad**2)then
319 :
320 2266812 : rr=sqrt(rr2)
321 : ! Find the index of the radius by bissection
322 2266812 : if (rr < radii(1,itypat)) then
323 : ! Linear extrapolation
324 : den=aeden(1,itypat)+(rr-radii(1,itypat))/(radii(2,itypat)-radii(1,itypat))&
325 2 : & *(aeden(2,itypat)-aeden(1,itypat))
326 : else
327 : ! Use the spline interpolation
328 : ! Find the index of the radius by bissection
329 : inmin=1
330 : inmax=npt
331 22255544 : igrid=1
332 : do
333 22255544 : if(inmax-inmin==1)exit
334 19988734 : igrid=(inmin+inmax)/2
335 22255544 : if(rr>=radii(igrid,itypat))then
336 : inmin=igrid
337 : else
338 6662810 : inmax=igrid
339 : end if
340 : end do
341 2266810 : igrid=inmin
342 : ! write(std_out,*)' igrid',igrid
343 :
344 2266810 : hh=step(1,igrid)
345 2266810 : h_inv=step(2,igrid)
346 2266810 : aa= (radii(igrid+1,itypat)-rr)*h_inv
347 2266810 : bb= (rr-radii(igrid,itypat))*h_inv
348 : den = aa*aeden(igrid,itypat) + bb*aeden(igrid+1,itypat) &
349 : & +( (aa*aa*aa-aa)*yder2(igrid) &
350 2266810 : & +(bb*bb*bb-bb)*yder2(igrid+1) ) *hh*hh*sixth
351 : end if ! Select small radius or spline
352 :
353 2266812 : local_den(k1,k2,k3,iatom)=local_den(k1,k2,k3,iatom)+den
354 : end if ! dist2<maxrad
355 :
356 : end do ! k1
357 : end do ! k2
358 : end do ! k3
359 :
360 : end do ! icell
361 : end do ! iatom
362 :
363 : !Compute, the total all-electron density at each point in the primitive cell
364 5 : ABI_MALLOC(sum_den,(nrx,nry,nrz))
365 47989 : sum_den(:,:,:)=zero
366 3 : do iatom=1,natom
367 95979 : sum_den(:,:,:)=sum_den(:,:,:)+local_den(:,:,:,iatom)
368 : end do
369 :
370 : !Accumulate the integral of the density, to get Hirshfeld charges
371 : !There is a minus sign because the electron has a negative charge
372 : ngoodpoints = 0
373 3 : hcharge(:)=zero
374 3 : hweight(:)=zero
375 37 : do k3=1,nrz
376 1333 : do k2=1,nry
377 47988 : do k1=1,nrx
378 : ! Use minimal_den in order to avoid divide by zero
379 47952 : if (abs(sum_den(k1,k2,k3)) > minimal_den) then
380 : ngoodpoints = ngoodpoints+1
381 46656 : factor=grid_den(k1,k2,k3)/(sum_den(k1,k2,k3)+minimal_den)
382 139968 : do iatom=1,natom
383 93312 : hden(iatom)=hden(iatom)+local_den(k1,k2,k3,iatom)
384 93312 : hcharge(iatom)=hcharge(iatom)-local_den(k1,k2,k3,iatom)*factor
385 139968 : hweight(iatom)=hweight(iatom)+local_den(k1,k2,k3,iatom)/(sum_den(k1,k2,k3)+minimal_den)
386 : end do
387 : end if
388 : end do
389 : end do
390 : end do
391 :
392 : !DEBUG
393 : !do iatom=1,natom
394 : !write(std_out,'(i9,3es17.6)' )iatom,hden(iatom),hcharge(iatom),hweight(iatom)
395 : !end do
396 : !ENDDEBUG
397 :
398 3 : hcharge(:)=hcharge(:)*ucvol/dble(nfftot)
399 3 : hweight(:)=hweight(:)/dble(nfftot)
400 :
401 : !Check on the total charge
402 3 : total_zion=sum(zion(typat(1:natom)))
403 3 : total_charge=sum(hcharge(1:natom))
404 : total_weight=sum(hweight(1:natom))
405 :
406 : !DEBUG
407 : !write(std_out,*)' ngoodpoints = ', ngoodpoints, ' out of ', nfftot
408 : !write(std_out,*)' total_weight=',total_weight
409 : !write(std_out,*)' total_weight=',total_weight
410 : !ENDDEBUG
411 :
412 : !Output
413 1 : if (prtcharge == 1) then
414 1 : write(std_out,*)
415 1 : write(std_out,*)' Hirshfeld analysis'
416 1 : write(std_out,*)' Atom Zion Electron Charge Net charge '
417 1 : write(std_out,*)
418 3 : do iatom=1,natom
419 : write(std_out,'(i9,3es17.6)' )&
420 3 : & iatom,zion(typat(iatom)),hcharge(iatom),hcharge(iatom)+zion(typat(iatom))
421 : end do
422 1 : write(std_out,*)
423 1 : write(std_out,'(a,3es17.6)')' Total',total_zion,total_charge,total_charge+total_zion
424 1 : write(std_out,*)
425 : end if
426 :
427 1 : ABI_FREE(coord1)
428 1 : ABI_FREE(local_den)
429 1 : ABI_FREE(ncells)
430 1 : ABI_FREE(step)
431 1 : ABI_FREE(sum_den)
432 1 : ABI_FREE(xcartcells)
433 1 : ABI_FREE(xred)
434 1 : ABI_FREE(yder2)
435 :
436 1 : end subroutine dens_hirsh
437 : !!***
438 :
439 : !!****f* m_dens/add_atomic_fcts
440 : !! NAME
441 : !! add_atomic_fcts
442 : !!
443 : !! FUNCTION
444 : !! This routine is called to assemble the atomic spherical functions, and, if option/=0,
445 : !! to add it to some input function (usually an input potential residual).
446 : !! The contributions from each atomic sphere are governed by parameters coeff_constr_dft, input to the present routine.
447 : !!
448 : !! INPUTS
449 : !! natom=number of atoms
450 : !! nspden = number of spin densities (1 2 or 4)
451 : !! option= if 0, the sum of the atomic spherical functions is returned in nv_constr_dft_r; if non-zero, they are added to nv_constr_dft_r
452 : !! rprimd=lattice vectors (dimensionful)
453 : !! mpi_enreg=mpi structure with communicator info
454 : !! nfft=number of points in standard fft grid
455 : !! ngfft=FFT grid dimensions
456 : !! ntypat=number of types of atoms
457 : !! ratsph(ntypat)=radii for muffin tin spheres of each atom
458 : !! typat(natom)=types of atoms
459 : !! xred(3,natom)=reduced atomic positions
460 : !!
461 : !! SIDE EFFECTS
462 : !! nv_constr_dft_r=the constrained potential or density in real space
463 : !!
464 : !! SOURCE
465 :
466 1413 : subroutine add_atomic_fcts(natom,nspden,rprimd,mpi_enreg,nfft,ngfft,ntypat,option,ratsph, &
467 1413 : ratsm, typat,coeffs_constr_dft,nv_constr_dft_r,xred)
468 :
469 : !Arguments ------------------------------------
470 : !scalars
471 : integer,intent(in) :: natom,nfft,nspden,ntypat,option
472 : type(MPI_type),intent(in) :: mpi_enreg
473 : !arrays
474 : integer,intent(in) :: typat(natom)
475 : integer,intent(in) :: ngfft(18)
476 : real(dp),intent(in) :: coeffs_constr_dft(nspden,natom)
477 : real(dp),intent(inout) :: nv_constr_dft_r(nfft,nspden)
478 : real(dp),intent(in) :: ratsph(ntypat)
479 : real(dp),intent(in) :: ratsm ! Ben change
480 : real(dp),intent(in) :: rprimd(3,3)
481 : real(dp),intent(in) :: xred(3,natom)
482 :
483 : !Local variables-------------------------------
484 : !scalars
485 : integer,parameter :: ishift=5
486 : integer :: iatom, ierr
487 : integer :: n1a, n1b, n3a, n3b, n2a, n2b
488 : integer :: n1, n2, n3
489 : integer :: ifft_local
490 : integer :: i1,i2,i3,ix,iy,iz,izloc
491 : real(dp) :: dfsm,dify,difz,fsm,r2atsph,rr1,rr2,rr3,ratsm2,rx23,ry23,rz23 !Ben change: remove ratsm
492 : real(dp) :: r2,r2_11,r2_123,r2_23
493 : real(dp) :: ucvol
494 : real(dp),parameter :: delta=0.99_dp
495 : !arrays
496 1413 : real(dp), allocatable :: difx(:)
497 : real(dp) :: gprimd(3,3),rmet(3,3),gmet(3,3)
498 : real(dp) :: tsec(2)
499 1413 : integer, contiguous, pointer :: fftn2_distrib(:),ffti2_local(:)
500 1413 : integer, contiguous, pointer :: fftn3_distrib(:),ffti3_local(:)
501 : ! ***********************************************************************************************
502 :
503 : !We need the metric because it is needed to compute the "box" around each atom
504 1413 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
505 :
506 1413 : n1 = ngfft(1)
507 1413 : n2 = ngfft(2)
508 1413 : n3 = ngfft(3)
509 :
510 : !Ben change: comment out ratsm line
511 : !ratsm = 0.05_dp ! default value for the smearing region radius - may become input variable later
512 :
513 1413 : if(option==0)then
514 1425865 : nv_constr_dft_r = zero
515 : endif
516 :
517 : !Get the distrib associated with this fft_grid
518 1413 : call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
519 :
520 : !Loop over atoms
521 : !-------------------------------------------
522 4664 : do iatom=1,natom
523 :
524 14517 : if(sum(coeffs_constr_dft(1:nspden,iatom)**2)<tol12)then
525 : cycle
526 : endif
527 :
528 : ! Define a "box" around the atom
529 3025 : r2atsph=1.0000001_dp*ratsph(typat(iatom))**2
530 3025 : rr1=sqrt(r2atsph*gmet(1,1))
531 3025 : rr2=sqrt(r2atsph*gmet(2,2))
532 3025 : rr3=sqrt(r2atsph*gmet(3,3))
533 :
534 3025 : n1a=int((xred(1,iatom)-rr1+ishift)*n1+delta)-ishift*n1
535 3025 : n1b=int((xred(1,iatom)+rr1+ishift)*n1 )-ishift*n1
536 3025 : n2a=int((xred(2,iatom)-rr2+ishift)*n2+delta)-ishift*n2
537 3025 : n2b=int((xred(2,iatom)+rr2+ishift)*n2 )-ishift*n2
538 3025 : n3a=int((xred(3,iatom)-rr3+ishift)*n3+delta)-ishift*n3
539 3025 : n3b=int((xred(3,iatom)+rr3+ishift)*n3 )-ishift*n3
540 :
541 3025 : ratsm2 = -(ratsm**2 - 2*ratsph(typat(iatom))*ratsm)
542 :
543 9075 : ABI_MALLOC(difx,(n1a:n1b))
544 30554 : do i1=n1a,n1b
545 30554 : difx(i1)=dble(i1)/dble(n1)-xred(1,iatom)
546 : enddo ! i1
547 :
548 29416 : do i3=n3a,n3b
549 26391 : iz=mod(i3+ishift*n3,n3)
550 29416 : if(fftn3_distrib(iz+1)==mpi_enreg%me_fft) then
551 26391 : izloc = ffti3_local(iz+1) - 1
552 26391 : difz=dble(i3)/dble(n3)-xred(3,iatom)
553 383456 : do i2=n2a,n2b
554 357065 : iy=mod(i2+ishift*n2,n2)
555 357065 : dify=dble(i2)/dble(n2)-xred(2,iatom)
556 357065 : rx23=dify*rprimd(1,2)+difz*rprimd(1,3)
557 357065 : ry23=dify*rprimd(2,2)+difz*rprimd(2,3)
558 357065 : rz23=dify*rprimd(3,2)+difz*rprimd(3,3)
559 357065 : r2_23=rx23**2+ry23**2+rz23**2
560 357065 : r2_11=rprimd(1,1)**2+rprimd(2,1)**2+rprimd(3,1)**2
561 357065 : r2_123=2*(rprimd(1,1)*rx23+rprimd(2,1)*ry23+rprimd(3,1)*rz23)
562 6713401 : do i1=n1a,n1b
563 6329945 : r2=(difx(i1)*r2_11+r2_123)*difx(i1)+r2_23
564 6329945 : if (r2 > r2atsph) cycle
565 3369523 : call radsmear(dfsm,fsm,r2,r2atsph,ratsm2)
566 3369523 : ix=mod(i1+ishift*n1,n1)
567 : ! Identify the fft indexes of the rectangular grid around the atom
568 3369523 : ifft_local=1+ix+n1*(iy+n2*izloc)
569 11585447 : nv_constr_dft_r(ifft_local,1:nspden)=nv_constr_dft_r(ifft_local,1:nspden) + fsm*coeffs_constr_dft(1:nspden,iatom)
570 :
571 : end do ! i1
572 : end do ! i2
573 : end if ! if this is my fft slice
574 : end do ! i3
575 4664 : ABI_FREE(difx)
576 :
577 : ! end loop over atoms
578 : end do
579 :
580 : !MPI parallelization
581 : !TODO: test if xmpi_sum does the correct stuff for a slice of nv_constr_dft_r
582 1413 : if(mpi_enreg%nproc_fft>1)then
583 0 : call timab(48,1,tsec)
584 0 : call xmpi_sum(nv_constr_dft_r,mpi_enreg%comm_fft,ierr)
585 0 : call timab(48,2,tsec)
586 : end if
587 :
588 : ! write (201,*) '# potential 1'
589 : ! write (201,*) nv_constr_dft_r(:,1)
590 :
591 : ! write (202,*) '# potential 2'
592 : ! write (202,*) nv_constr_dft_r(:,2)
593 :
594 : ! if (nspden > 2) then
595 : ! write (203,*) '# potential 3'
596 : ! write (203,*) nv_constr_dft_r(:,3)
597 :
598 : ! write (204,*) '# potential 4'
599 : ! write (204,*) nv_constr_dft_r(:,4)
600 : ! end if
601 :
602 1413 : end subroutine add_atomic_fcts
603 : !!***
604 :
605 : !!****f* m_dens/constrained_dft_ini
606 : !! NAME
607 : !! constrained_dft_ini
608 : !!
609 : !! FUNCTION
610 : !! Initialize the constrained_dft datastructure.
611 : !! Mostly copying already available (dtset) information, but also computing intgf2
612 :
613 : !!
614 : !! INPUTS
615 : !! chrgat(natom) = target charge for each atom. Not always used, it depends on the value of constraint_kind
616 : !! constraint_kind(ntypat)=for each type of atom, 0=no constraint,
617 : !! 1=fix only the magnetization direction, following spinat direction,
618 : !! 2=fix the magnetization vector to be the spinat one,
619 : !! 3=fix the magnetization amplitude to be the spinat one, but does not fix its direction
620 : !! other future values will constrain the local atomic charge and possibly mix constraints if needed.
621 : !! magconon=type of penalty function (so, not constrained DFT).
622 : !! magcon_lambda=strength of the atomic spherical constraint
623 : !! mpi_enreg=mpi structure with communicator info
624 : !! natom=number of atoms
625 : !! nfft=number of points in standard fft grid
626 : !! ngfft=FFT grid dimensions
627 : !! nspden = number of spin densities (1 2 or 4)
628 : !! ntypat=number of types of atoms
629 : !! ratsm=smearing width for ratsph
630 : !! ratsph(ntypat)=radii for muffin tin spheres of each atom
631 : !! rprimd=lattice vectors (dimensioned)
632 : !! spinat(3,natom)=magnetic moments vectors, possible targets according to the value of constraint_kind
633 : !! typat(natom)=types of atoms
634 : !! xred(3,natom)=reduced atomic positions
635 : !! ziontypat(ntypat)=ionic charge, per type of atom
636 : !!
637 : !! OUTPUT
638 : !! constrained_dft=datastructure that contain the needed information to enforce the density and magnetization constraints
639 : !! Most of the data are simply copied from dtset, but also constrained_dft%intgf2(natom,natom) is computed from the available data.
640 : !!
641 : !! SOURCE
642 :
643 64 : subroutine constrained_dft_ini(chrgat,constrained_dft,constraint_kind,&
644 : & magconon,magcon_lambda,mpi_enreg,natom,nfftf,ngfftf,nspden,ntypat,&
645 64 : & ratsm,ratsph,rprimd,spinat,typat,xred,ziontypat,znucl,qgbt,use_gbt,spinaxis)
646 :
647 : !Arguments ------------------------------------
648 : !scalars
649 : integer,intent(in) :: magconon,natom,nfftf,nspden,ntypat,use_gbt
650 : real(dp),intent(in) :: magcon_lambda,ratsm
651 : type(MPI_type),intent(in) :: mpi_enreg
652 : type(constrained_dft_t),intent(out):: constrained_dft
653 : !arrays
654 : integer,intent(in) :: constraint_kind(ntypat)
655 : integer,intent(in) :: ngfftf(18)
656 : integer,intent(in) :: typat(natom)
657 : real(dp),intent(in) :: chrgat(natom)
658 : real(dp),intent(in) :: ratsph(ntypat)
659 : real(dp),intent(in) :: rprimd(3,3)
660 : real(dp),intent(in) :: spinat(3,natom)
661 : real(dp),intent(in) :: xred(3,natom)
662 : real(dp),intent(in) :: ziontypat(ntypat)
663 : real(dp),intent(in) :: znucl(ntypat)
664 : real(dp),intent(in) :: qgbt(3)
665 : real(dp),intent(in) :: spinaxis(3)
666 :
667 : !Local variables-------------------------------
668 : !scalars
669 : integer,parameter :: cplex1=1
670 : real(dp) :: ucvol
671 : !arrays
672 64 : real(dp), allocatable :: intgf2(:,:) ! natom,natom
673 64 : real(dp), allocatable :: rhor_dum(:,:) ! nfftf,nspden
674 : real(dp) :: gprimd(3,3),rmet(3,3),gmet(3,3)
675 : ! ***********************************************************************************************
676 :
677 256 : ABI_MALLOC(intgf2,(natom,natom))
678 :
679 : !We need the metric because it is needed in calcdenmagsph.F90
680 64 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
681 :
682 75 : if(any(constraint_kind(:)/=0))then
683 : !We need to precompute intgf2
684 216 : ABI_MALLOC(rhor_dum,(nfftf,nspden))
685 2489335 : rhor_dum(:,:)=zero
686 : call calcdenmagsph(mpi_enreg,natom,nfftf,ngfftf,nspden,ntypat,&
687 54 : & ratsm,ratsph,rhor_dum,rprimd,typat,xred,0,cplex1,qgbt,use_gbt,intgf2=intgf2)
688 54 : ABI_FREE(rhor_dum)
689 : else
690 30 : intgf2=zero
691 : endif
692 :
693 64 : constrained_dft%magconon =magconon
694 64 : constrained_dft%magcon_lambda =magcon_lambda
695 64 : constrained_dft%natom =natom
696 64 : constrained_dft%nfftf =nfftf
697 1216 : constrained_dft%ngfftf =ngfftf
698 64 : constrained_dft%nspden =nspden
699 64 : constrained_dft%ntypat =ntypat
700 64 : constrained_dft%ratsm =ratsm
701 832 : constrained_dft%rprimd =rprimd
702 :
703 192 : ABI_MALLOC(constrained_dft%chrgat,(natom))
704 192 : ABI_MALLOC(constrained_dft%constraint_kind,(ntypat))
705 192 : ABI_MALLOC(constrained_dft%intgf2,(natom,natom))
706 192 : ABI_MALLOC(constrained_dft%ratsph,(ntypat))
707 192 : ABI_MALLOC(constrained_dft%spinat,(3,natom))
708 192 : ABI_MALLOC(constrained_dft%typat,(natom))
709 128 : ABI_MALLOC(constrained_dft%ziontypat,(ntypat))
710 128 : ABI_MALLOC(constrained_dft%znucl,(ntypat))
711 :
712 264 : constrained_dft%chrgat =chrgat
713 209 : constrained_dft%constraint_kind =constraint_kind
714 592 : constrained_dft%intgf2 =intgf2
715 209 : constrained_dft%ratsph =ratsph
716 672 : constrained_dft%spinat =spinat
717 264 : constrained_dft%typat =typat
718 209 : constrained_dft%ziontypat =ziontypat
719 209 : constrained_dft%znucl =znucl
720 256 : constrained_dft%spinaxis =spinaxis
721 :
722 64 : ABI_FREE(intgf2)
723 :
724 64 : end subroutine constrained_dft_ini
725 : !!***
726 :
727 :
728 : !!****f* m_dens/constrained_dft_free
729 : !! NAME
730 : !! constrained_dft_free
731 : !!
732 : !! FUNCTION
733 : !! Free the constrained_dft datastructure.
734 : !!
735 : !! SOURCE
736 :
737 6923 : subroutine constrained_dft_free(constrained_dft)
738 :
739 : !Arguments ------------------------------------
740 : type(constrained_dft_t),intent(inout):: constrained_dft
741 : ! ***********************************************************************************************
742 :
743 6923 : ABI_SFREE(constrained_dft%chrgat)
744 6923 : ABI_SFREE(constrained_dft%constraint_kind)
745 6923 : ABI_SFREE(constrained_dft%intgf2)
746 6923 : ABI_SFREE(constrained_dft%ratsph)
747 6923 : ABI_SFREE(constrained_dft%spinat)
748 6923 : ABI_SFREE(constrained_dft%typat)
749 6923 : ABI_SFREE(constrained_dft%ziontypat)
750 6923 : ABI_SFREE(constrained_dft%znucl)
751 :
752 6923 : end subroutine constrained_dft_free
753 : !!***
754 :
755 :
756 : !!****f* m_dens/constrained_residual
757 : !! NAME
758 : !! constrained_residual
759 : !!
760 : !! FUNCTION
761 : !! Recompute the residual to take into account the constraints, within constrained DFT.
762 : !! The kind of constraint is given by constraint_kind, and the target values are given by spinat, for the local atomic magnetization,
763 : !! and chrgat minus the ionic charge, for the local atomic charge.
764 :
765 : !!
766 : !! INPUTS
767 : !! c_dft <type(constrained_dft_t)>=datastructure for the information related to constrained DFT
768 : !! ! chrgat(natom) = target charge for each atom. Not always used, it depends on the value of constraint_kind
769 : !! ! constraint_kind(ntypat)=for each type of atom, 0=no constraint,
770 : !! ! 1=fix only the magnetization direction, following spinat direction,
771 : !! ! 2=fix the magnetization vector to be the spinat one,
772 : !! ! 3=fix the magnetization amplitude to be the spinat one, but does not fix its direction
773 : !! ! other future values will constrain the local atomic charge and possibly mix constraints if needed.
774 : !! ! intgf2(natom,natom)=(precomputed) overlap of the spherical integration functions for each atom in a sphere of radius ratsph.
775 : !! ! magcon_lambda=strength of the atomic spherical constraint
776 : !! ! natom=number of atoms
777 : !! ! nfftf=number of points in fine fft grid
778 : !! ! ngfftf=FFT grid dimensions
779 : !! ! nspden = number of spin densities (1 2 or 4)
780 : !! ! ntypat=number of types of atoms
781 : !! ! ratsm=smearing width for ratsph
782 : !! ! ratsph(ntypat)=radii for muffin tin spheres of each atom
783 : !! ! rprimd=lattice vectors (dimensioned)
784 : !! ! spinat(3,natom)=magnetic moments vectors, possible targets according to the value of constraint_kind
785 : !! ! typat(natom)=types of atoms
786 : !! ! ziontypat(ntypat)= ionic charge, per type of atom
787 : !! mpi_enreg=mpi structure with communicator info
788 : !! rhor(nfft,nspden)=array for electron density in el./bohr**3. At output it will be constrained.
789 : !! xred(3,natom)=reduced atomic positions
790 : !!
791 : !! OUTPUT
792 : !! e_constrained_dft=correction to the total energy, to make it variational
793 : !! grcondft(3,natom)=d(E_constrained_DFT)/d(xred) (hartree)
794 : !! intgres(nspden,natom)=integrated residuals from constrained DFT. They are also Lagrange parameters, or gradients with respect to constraints.
795 : !! strscondft(6)=stress due to constraints = -d(E_constrained_DFT)/d(strain) / ucvol (hartree/Bohr^3)
796 : !!
797 : !! SIDE EFFECTS
798 : !! vresid(nfft,nspden)==array for potential residual in real space
799 : !! At output it will be modified: projected onto the space orthogonal to the atomic spherical functions (if there is a related
800 : !! constrained, and augmented by such atomic spherical functions multiplied by the difference between the actual
801 : !! integrated charge or magnetization and the target ones.
802 : !!
803 : !! SOURCE
804 :
805 1304 : subroutine constrained_residual(c_dft,e_constrained_dft,grcondft,intgres,mpi_enreg,rhor,strscondft,vresid,xred,qgbt,use_gbt)
806 :
807 : !Arguments ------------------------------------
808 : !scalars
809 : class(constrained_dft_t),intent(in) :: c_dft
810 : integer, intent(in) :: use_gbt
811 : real(dp),intent(out) :: e_constrained_dft
812 : type(MPI_type),intent(in) :: mpi_enreg
813 : !arrays
814 : real(dp),intent(out) :: grcondft(:,:) ! 3,natom
815 : real(dp),intent(out) :: intgres(:,:) ! nspden,natom
816 : real(dp),intent(in) :: rhor(c_dft%nfftf,c_dft%nspden)
817 : real(dp),intent(out) :: strscondft(6)
818 : real(dp),intent(inout) :: vresid(c_dft%nfftf,c_dft%nspden)
819 : real(dp),intent(in) :: xred(3,c_dft%natom),qgbt(3)
820 :
821 : !Local variables-------------------------------
822 : !scalars
823 : integer :: conkind,iatom,ii,jatom,info,natom,nfftf,nspden,ntypat,option
824 : integer,parameter :: cplex1=1
825 : real(dp) :: intgd,intgden_norm,intgden_proj,intgres_proj,norm,scprod
826 : !arrays
827 2608 : integer :: ipiv(c_dft%natom)
828 : real(dp) :: corr_denmag(4),gr_intgd(3),strs_intgd(6)
829 1304 : real(dp), allocatable :: coeffs_constr_dft(:,:) ! nspden,natom
830 1304 : real(dp), allocatable :: gr_intgden(:,:,:) ! 3,nspden,natom
831 1304 : real(dp), allocatable :: intgden(:,:) ! nspden,natom
832 1304 : real(dp), allocatable :: intgden_delta(:,:) ! nspden,natom
833 1304 : real(dp), allocatable :: intgres_tmp(:,:) ! nspden,natom
834 1304 : real(dp), allocatable :: intgr(:,:) ! natom,nspden
835 1304 : real(dp), allocatable :: strs_intgden(:,:,:) ! 6,nspden,natom
836 2608 : real(dp) :: intgf2(c_dft%natom,c_dft%natom),rhomag(2,c_dft%nspden),work(2*c_dft%natom)
837 : real(dp) :: intgden_normed(3)
838 : real(dp) :: spinat_normed(3)
839 : ! ***********************************************************************************************
840 :
841 : !DEBUG
842 : !write(std_out,*) ' constrained_residual : enter '
843 : !ENDDEBUG
844 :
845 1304 : natom=c_dft%natom
846 1304 : nfftf=c_dft%nfftf
847 1304 : nspden=c_dft%nspden
848 1304 : ntypat=c_dft%ntypat
849 :
850 : !We need the integrated magnetic moments
851 5216 : ABI_MALLOC(intgden,(nspden,natom))
852 5216 : ABI_MALLOC(gr_intgden,(3,nspden,natom))
853 5216 : ABI_MALLOC(strs_intgden,(6,nspden,natom))
854 :
855 : call calcdenmagsph(mpi_enreg,natom,nfftf,c_dft%ngfftf,nspden,ntypat,c_dft%ratsm,c_dft%ratsph,rhor,c_dft%rprimd,c_dft%typat,&
856 1304 : xred,1,cplex1,qgbt,use_gbt,intgden=intgden,gr_intgden=gr_intgden,rhomag=rhomag,strs_intgden=strs_intgden)
857 2608 : call prtdenmagsph(cplex1,intgden,natom,nspden,ntypat,[std_out],1,qgbt,c_dft%ratsm,c_dft%ratsph,rhomag,c_dft%typat,c_dft%znucl,c_dft%spinaxis)
858 :
859 : !DEBUG
860 : !write(std_out,*) ' intgden(1:nspden,1:natom)=',intgden(1:nspden,1:natom)
861 : !ENDDEBUG
862 :
863 : !We need the integrated residuals
864 3912 : ABI_MALLOC(intgres_tmp,(nspden,natom))
865 15364 : intgres_tmp(:,:)=zero
866 : call calcdenmagsph(mpi_enreg,natom,nfftf,c_dft%ngfftf,nspden,ntypat,&
867 1304 : & c_dft%ratsm,c_dft%ratsph,vresid,c_dft%rprimd,c_dft%typat,xred,11,cplex1,qgbt,use_gbt,intgden=intgres_tmp,rhomag=rhomag)
868 :
869 : !DEBUG
870 : !write(std_out,*) ' intgres_tmp(1:nspden,1:natom)=',intgres_tmp(1:nspden,1:natom)
871 : !ENDDEBUG
872 :
873 : !Make the proper combination of intgres_tmp, to single out the scalar potential residual and the magnetic field potential residuals for x,y,z.
874 15364 : intgres(:,:)=zero
875 4446 : do iatom=1,natom
876 3142 : if(nspden==1)then
877 210 : intgres(1,iatom)=intgres_tmp(1,iatom)
878 2932 : else if(nspden==2)then
879 510 : intgres(1,iatom)=half*(intgres_tmp(1,iatom)+intgres_tmp(2,iatom))
880 510 : intgres(2,iatom)=half*(intgres_tmp(1,iatom)-intgres_tmp(2,iatom))
881 2422 : else if(nspden==4)then
882 : !Change the potential residual to the density+magnetization convention
883 2422 : intgres(1,iatom)=half*(intgres_tmp(1,iatom)+intgres_tmp(2,iatom))
884 2422 : intgres(2,iatom)= intgres_tmp(3,iatom)
885 2422 : intgres(3,iatom)=-intgres_tmp(4,iatom)
886 2422 : intgres(4,iatom)=half*(intgres_tmp(1,iatom)-intgres_tmp(2,iatom))
887 : endif
888 3142 : conkind=c_dft%constraint_kind(c_dft%typat(iatom))
889 3142 : if(conkind <10)intgres(1,iatom)=zero
890 4671 : if( mod(conkind,10)==0 .and. nspden>1)intgres(2:nspden,iatom)=zero
891 : enddo
892 : !Print the potential residuals
893 2608 : call prtdenmagsph(cplex1,intgres,natom,nspden,ntypat,[std_out],11,qgbt,c_dft%ratsm,c_dft%ratsph,rhomag,c_dft%typat,c_dft%znucl,c_dft%spinaxis)
894 1304 : ABI_FREE(intgres_tmp)
895 :
896 : !Also exchanges the spin and atom indices to prepare the solution of the linear system of equation
897 3912 : ABI_MALLOC(intgr,(natom,nspden))
898 4446 : do iatom=1,natom
899 15364 : intgr(iatom,1:nspden)=intgres(1:nspden,iatom)
900 : enddo
901 :
902 : !In case there is an overlap between spheres, must solve the linear system of equations
903 : !and take into account non-diagonal elements only for the set of atoms for which there is a constraint.
904 : !This can be different for the
905 : !charge residual or for the spin residual (but for the spin constraints, the set of atoms is inclusive of all constraints)
906 3912 : do ii=1,2 ! Charge, then spin
907 25448 : intgf2(:,:)=zero
908 8892 : do iatom=1,natom
909 8892 : intgf2(iatom,iatom)=c_dft%intgf2(iatom,iatom)
910 : enddo
911 6284 : do iatom=1,natom-1
912 15096 : do jatom=iatom,natom
913 12488 : if(c_dft%intgf2(iatom,jatom)>tol8)then
914 : !In the charge case, must have both atoms with constraints bigger than 10
915 5900 : if(ii==1)then
916 2950 : if(c_dft%constraint_kind(c_dft%typat(iatom))>=10 .and. &
917 : & c_dft%constraint_kind(c_dft%typat(jatom))>=10 )then
918 609 : intgf2(iatom,jatom)=c_dft%intgf2(iatom,jatom)
919 609 : intgf2(jatom,iatom)=c_dft%intgf2(iatom,jatom)
920 : endif
921 : endif
922 : !In the spin case, must have both atoms with constraints not ending with 0
923 5900 : if(ii==2)then
924 2950 : if(mod(c_dft%constraint_kind(c_dft%typat(iatom)),10)/=0 .and. &
925 : & mod(c_dft%constraint_kind(c_dft%typat(jatom)),10)/=0 )then
926 2738 : intgf2(iatom,jatom)=c_dft%intgf2(iatom,jatom)
927 2738 : intgf2(jatom,iatom)=c_dft%intgf2(iatom,jatom)
928 : endif
929 : endif
930 : endif
931 : enddo
932 : enddo
933 :
934 : !Solve the linear system of equation, for the different spins
935 2608 : call dsytrf('U',natom,intgf2,natom,ipiv,work,2*natom,info)
936 : ! call dsytri('U',natom,intgf2,natom,ipiv,work,info)
937 2608 : if(ii==1)then
938 1304 : call dsytrs('U',natom,1,intgf2,natom,ipiv,intgr,natom,info)
939 1304 : else if(ii==2 .and. nspden>1)then
940 1199 : call dsytrs('U',natom,nspden-1,intgf2,natom,ipiv,intgr(1:natom,2:nspden),natom,info)
941 : endif
942 :
943 : !Store the new residuals
944 10196 : do iatom=1,natom
945 6284 : if(ii==1)intgres(1,iatom)=intgr(iatom,1)
946 16668 : if(ii==2)intgres(2:nspden,iatom)=intgr(iatom,2:nspden)
947 : enddo
948 :
949 : enddo
950 :
951 : !DEBUG
952 : !write(std_out,*) ' after multiplication by ftt-1 , so, torque :'
953 : !write(std_out,*) ' intgres(1:nspden,1:natom)=',intgres(1:nspden,1:natom)
954 : !ENDDEBUG
955 :
956 : !Compute the delta of the integrated dens with respect to the target
957 : !Compute the energy correction, to make the energy functional variational
958 : !Also projects the residual in case constraint_kind 2
959 1304 : e_constrained_dft=zero
960 13872 : grcondft=zero
961 1304 : strscondft=zero
962 5216 : ABI_MALLOC(intgden_delta,(nspden,natom))
963 15364 : intgden_delta(:,:)=zero
964 4446 : do iatom=1,natom
965 :
966 : ! The integrated density must be in the total density+magnetization representation
967 3142 : if(nspden==2)then
968 510 : intgd =intgden(1,iatom)+intgden(2,iatom)
969 510 : intgden(2,iatom)=intgden(1,iatom)-intgden(2,iatom)
970 510 : intgden(1,iatom)=intgd
971 2040 : do ii=1,3
972 1530 : gr_intgd(ii) =gr_intgden(ii,1,iatom)+gr_intgden(ii,2,iatom)
973 1530 : gr_intgden(ii,2,iatom)=gr_intgden(ii,1,iatom)-gr_intgden(ii,2,iatom)
974 2040 : gr_intgden(ii,1,iatom)=gr_intgd(ii)
975 : enddo
976 3570 : do ii=1,6
977 3060 : strs_intgd(ii) =strs_intgden(ii,1,iatom)+strs_intgden(ii,2,iatom)
978 3060 : strs_intgden(ii,2,iatom)=strs_intgden(ii,1,iatom)-strs_intgden(ii,2,iatom)
979 3570 : strs_intgden(ii,1,iatom)=strs_intgd(ii)
980 : enddo
981 : endif
982 :
983 : !Comparison with the target value, and computation of the correction in terms of density and magnetization coefficients.
984 3142 : conkind=c_dft%constraint_kind(c_dft%typat(iatom))
985 :
986 3142 : if(conkind >=10)then
987 : !The electronic constraint is such that the ziontypat charge minus (the electronic charge is negative) the atomic electronic density
988 : !intgden gives the target charge chrgat.
989 825 : intgden_delta(1,iatom)=intgden(1,iatom)+c_dft%chrgat(iatom)-c_dft%ziontypat(c_dft%typat(iatom))
990 : ! Uses the usual electronic charge definition, instead of the total nucleus-electronic charge
991 : ! intgden_delta(1,iatom)=intgden(1,iatom)-c_dft%chrgat(iatom)
992 : endif
993 :
994 3142 : if( mod(conkind,10)==1 .and. nspden>1)then
995 : !Fix the different components of the magnetization vector
996 2458 : if(nspden==2)intgden_delta(2,iatom)=intgden(2,iatom)-c_dft%spinat(3,iatom)
997 8908 : if(nspden==4)intgden_delta(2:4,iatom)=intgden(2:4,iatom)-c_dft%spinat(1:3,iatom)
998 684 : else if( ( mod(conkind,10)>=2 .and. mod(conkind,10)<=4) .and. nspden>1)then
999 1372 : norm = sqrt(sum(c_dft%spinat(:,iatom)**2))
1000 343 : if (norm > tol10) then
1001 343 : if( mod(conkind,10)==2 )then
1002 : !Fix the axis of the magnetization vector
1003 149 : if(nspden==4)then
1004 348 : spinat_normed(:) = c_dft%spinat(:,iatom) / norm
1005 : !Calculate the scalar product of the fixed mag. mom. vector and calculated mag. mom. vector
1006 : !This is actually the size of the projection of the calc. mag. mom. vector on the fixed mag. mom. vector
1007 : intgden_proj=spinat_normed(1)*intgden(2,iatom)+ &
1008 : & spinat_normed(2)*intgden(3,iatom)+ &
1009 87 : & spinat_normed(3)*intgden(4,iatom)
1010 348 : intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)-spinat_normed(1:3)*intgden_proj
1011 : !Also projects the residual, so that the usual optimization is done is the largest possible space
1012 : intgres_proj=spinat_normed(1)*intgres(2,iatom)+ &
1013 : & spinat_normed(2)*intgres(3,iatom)+ &
1014 87 : & spinat_normed(3)*intgres(4,iatom)
1015 348 : intgres(2:nspden,iatom)=intgres(2:nspden,iatom)-spinat_normed(1:3)*intgres_proj
1016 62 : else if(nspden==2)then
1017 : !The direction must be correct, collinear, so no change.
1018 62 : intgden_delta(2,iatom)=zero
1019 : endif
1020 194 : else if( mod(conkind,10)==3 )then
1021 : !Fix the amplitude of the magnetization vector
1022 320 : intgden_norm = sqrt(sum(intgden(2:nspden,iatom)**2))
1023 320 : intgden_delta(2:nspden,iatom)=(one-norm/intgden_norm)*intgden(2:nspden,iatom)
1024 : else if( mod(conkind,10)==4 )then
1025 : !Fix the direction of the magnetization vector
1026 86 : if(nspden==4)then
1027 344 : spinat_normed(:) = c_dft%spinat(:,iatom) / norm
1028 344 : intgden_norm = sqrt(sum(intgden(2:nspden,iatom)**2))
1029 344 : intgden_normed(:) = intgden(2:nspden,iatom)/intgden_norm
1030 : !Calculate the difference vector between the actual magnetization vectoro, times the scalar product between the
1031 : !directions of present magnetization and target one, and the target magnetization direction renormalized by the magnetization length.
1032 : !See notes 12 October 2021
1033 : !DEBUG First possibility
1034 : ! intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)-spinat_normed(1:3)*intgden_norm
1035 : !ENDDEBUG
1036 : !DEBUG Second possibility
1037 344 : scprod=sum(spinat_normed(:)*intgden_normed(:))
1038 344 : intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)*scprod-spinat_normed(1:3)*intgden_norm
1039 : !ENDDEBUG
1040 : !Also projects the residual. There might be some misalignement of the intgden_delta with the correct space of allowed variations
1041 : !(not exactly perpendicular to spinat_normed or intgden_normed, or even frankly not at all perpendicular),
1042 : !but when close to fulfilling the constraint, this difference becomes negligible.
1043 : !The present choice, couple with the above definition of intgden_delta aligns both.
1044 : !DEBUG First possibility
1045 : intgres_proj=intgden_normed(1)*intgres(2,iatom)+ &
1046 : & intgden_normed(2)*intgres(3,iatom)+ &
1047 86 : & intgden_normed(3)*intgres(4,iatom)
1048 344 : intgres(2:nspden,iatom)=intgres(2:nspden,iatom)-intgden_normed(1:3)*intgres_proj
1049 : !ENDDEBUG
1050 : !DEBUG Second possibility
1051 : ! intgres_proj=spinat_normed(1)*intgres(2,iatom)+ &
1052 : !& spinat_normed(2)*intgres(3,iatom)+ &
1053 : !& spinat_normed(3)*intgres(4,iatom)
1054 : ! intgres(2:nspden,iatom)=intgres(2:nspden,iatom)-spinat_normed(1:3)*intgres_proj
1055 : !ENDDEBUG
1056 0 : else if(nspden==2)then
1057 : !This case is ill-defined ... What follows is rather arbitrary.
1058 : !When the actual magnetization and the target magnetization have same sign, the intgden_delta is zero.
1059 : ! Otherwise, intgres is set to the difference between the present intgden and the target
1060 0 : intgden_delta(2,iatom)=zero
1061 0 : if(c_dft%spinat(2,iatom)*intgden(2,iatom)<-tol10)intgden_delta(2,iatom)=c_dft%spinat(2,iatom)-intgden(2,iatom)
1062 : endif
1063 : endif
1064 : else
1065 : !In this case (norm of constraint vanishes), we set the atomic magnetization to zero.
1066 0 : intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)
1067 : endif
1068 : end if
1069 : ! Lagrange energy contribution. Note that intgres is the derivative with respect to the chrgat and spinat constraints,
1070 : ! because chrgat and spinat have directly been used in the definition of intgden_delta.
1071 : ! WOOPS : chrgat comes with a POSITIVE sign in intgden_delta ?!?!
1072 14060 : e_constrained_dft=e_constrained_dft-sum(intgden_delta(:,iatom)*intgres(:,iatom))
1073 12568 : do ii=1,3
1074 45322 : grcondft(ii,iatom)=grcondft(ii,iatom)-sum(gr_intgden(ii,:,iatom)*intgres(:,iatom))
1075 : enddo
1076 : ! For the stress, this is the place where the summation over atoms is performed.
1077 23298 : do ii=1,6
1078 87502 : strscondft(ii)=strscondft(ii)-sum(strs_intgden(ii,:,iatom)*intgres(:,iatom))
1079 : enddo
1080 :
1081 : !DEBUG
1082 : ! write(6,*)' calcdenmagsph/constrained_residual, line 1058 : iatom=',iatom
1083 : ! write(6,*)' e_constrained_dft,intgden_delta(:,iatom),intgres(:,iatom)=',e_constrained_dft,intgden_delta(:,iatom),intgres(:,iatom)
1084 : ! write(6,*)' grcondft(1,iatom),gr_intgden(1,:,iatom),intgres(:,iatom)=',grcondft(1,iatom),gr_intgden(1,:,iatom),intgres(:,iatom)
1085 : ! write(6,*)' strscondft(1),strs_intgden(1,:,iatom),intgres(:,iatom)=',strscondft(1),strs_intgden(1,:,iatom),intgres(:,iatom)
1086 : ! call flush(6)
1087 : ! stop
1088 : !ENDDEBUG
1089 :
1090 : enddo
1091 :
1092 1304 : ABI_FREE(gr_intgden)
1093 1304 : ABI_FREE(strs_intgden)
1094 :
1095 3912 : ABI_MALLOC(coeffs_constr_dft,(nspden,natom))
1096 15364 : coeffs_constr_dft=zero
1097 :
1098 : !With the delta of the integrated density and the atomic residual, compute the atomic correction to be applied to the potential
1099 : !See the Eqs.(31), (33) and (34) of notes.
1100 4446 : do iatom=1,natom
1101 :
1102 : !Computation of the correction in terms of density and magnetization coefficients.
1103 3142 : conkind=c_dft%constraint_kind(c_dft%typat(iatom))
1104 3142 : corr_denmag(:)=zero
1105 :
1106 3142 : if(conkind >=10)then
1107 825 : corr_denmag(1)=intgden_delta(1,iatom)*c_dft%magcon_lambda - intgres(1,iatom)
1108 : endif
1109 :
1110 3142 : if( mod(conkind,10)==1 .and. nspden>1)then
1111 :
1112 : !Fix the different components of the magnetization vector
1113 2458 : if(nspden==2)corr_denmag(2)=intgden_delta(2,iatom)*c_dft%magcon_lambda - intgres(2,iatom)
1114 8908 : if(nspden==4)corr_denmag(2:4)=intgden_delta(2:4,iatom)*c_dft%magcon_lambda - intgres(2:4,iatom)
1115 :
1116 684 : else if( ( mod(conkind,10)>=2 .and. mod(conkind,10)<=4) .and. nspden>1)then
1117 :
1118 1372 : norm = sqrt(sum(c_dft%spinat(:,iatom)**2))
1119 343 : if (norm > tol10) then
1120 :
1121 343 : if( mod(conkind,10)==2 .or. mod(conkind,10)==4)then
1122 : !Fix the axis/direction of the magnetization vector
1123 235 : if(nspden==4 .or. mod(conkind,10)==4)then
1124 692 : corr_denmag(2:nspden)=intgden_delta(2:nspden,iatom)*c_dft%magcon_lambda -intgres(2:nspden,iatom)
1125 : else if(nspden==2 .and. mod(conkind,10)==2)then
1126 : !The direction must be correct, collinear, so no change.
1127 : corr_denmag(2)=zero
1128 : endif
1129 :
1130 : else if( mod(conkind,10)==3 )then
1131 :
1132 : !Fix the amplitude of the magnetization vector
1133 : !This is a special case, one does not work (at present) with the intgden_delta, while one should ...
1134 320 : intgden(2:nspden,iatom)=intgden(2:nspden,iatom) - intgres(2:nspden,iatom)/c_dft%magcon_lambda
1135 320 : intgden_norm = sqrt(sum(intgden(2:nspden,iatom)**2))
1136 320 : corr_denmag(2:nspden)=(one-norm/intgden_norm)*intgden(2:nspden,iatom)
1137 320 : corr_denmag(2:nspden)=corr_denmag(2:nspden)*c_dft%magcon_lambda
1138 :
1139 : endif
1140 :
1141 : else
1142 : !In this case, we set the atomic magnetization to zero.
1143 0 : corr_denmag(2:nspden)=intgden_delta(2:nspden,iatom)*c_dft%magcon_lambda - intgres(2,iatom)
1144 : endif
1145 :
1146 : end if
1147 :
1148 : !Convert from density/magnetization constraint residual to actual coefficient that will multiply the spherical function for the potential
1149 4446 : if(nspden==1)then
1150 : !From charge to potential
1151 210 : coeffs_constr_dft(1,iatom)=corr_denmag(1)
1152 2932 : else if(nspden==2 .or. nspden==4)then
1153 : !From charge and magnetization to potential
1154 2932 : coeffs_constr_dft(1,iatom)=corr_denmag(1)+corr_denmag(nspden)
1155 2932 : coeffs_constr_dft(2,iatom)=corr_denmag(1)-corr_denmag(nspden)
1156 2932 : if(nspden==4)then
1157 2422 : coeffs_constr_dft(3,iatom)= corr_denmag(2)
1158 2422 : coeffs_constr_dft(4,iatom)=-corr_denmag(3)
1159 : endif
1160 : endif
1161 :
1162 : enddo
1163 :
1164 : !Now compute the new residual, by adding the spherical functions
1165 1304 : option=1
1166 : call add_atomic_fcts(natom,nspden,c_dft%rprimd,mpi_enreg,nfftf,c_dft%ngfftf,ntypat,option,&
1167 1304 : & c_dft%ratsph,c_dft%ratsm,c_dft%typat,coeffs_constr_dft,vresid,xred) ! Ben change: add ratsm
1168 :
1169 1304 : ABI_FREE(coeffs_constr_dft)
1170 1304 : ABI_FREE(intgden)
1171 1304 : ABI_FREE(intgden_delta)
1172 1304 : ABI_FREE(intgr)
1173 :
1174 1304 : end subroutine constrained_residual
1175 : !!***
1176 :
1177 : !!****f* m_dens/mag_penalty
1178 : !! NAME
1179 : !! mag_penalty
1180 : !!
1181 : !! FUNCTION
1182 : !! This routine is called to compute the potential corresponding to constrained magnetic moments using the penalty function algorithm.
1183 : !!
1184 : !! INPUTS
1185 : !! c_dft <type(constrained_dft_t)>=datastructure for the information related to constrained DFT
1186 : !! ! magconon=constraining option (on/off); 1=fix only the direction, 2=fix the direction and size
1187 : !! ! magcon_lambda=strength of the atomic spherical constraint
1188 : !! ! natom=number of atoms
1189 : !! ! nfftf=number of points in fine fft grid
1190 : !! ! ngfftf=FFT grid dimensions
1191 : !! ! nspden = number of spin densities (1 2 or 4)
1192 : !! ! ntypat=number of types of atoms
1193 : !! ! ratsm=smearing width for ratsph
1194 : !! ! ratsph(ntypat)=radii for muffin tin spheres of each atom
1195 : !! ! rprimd=lattice vectors (dimensioned)
1196 : !! ! spinat(3,natom)=magnetic moments vectors, possible targets according to the value of constraint_kind
1197 : !! ! typat(natom)=types of atoms
1198 : !! mpi_enreg=mpi structure with communicator info
1199 : !! rhor=density in real space
1200 : !! xred=reduced atomic positions
1201 : !!
1202 : !! OUTPUT
1203 : !! nv_constr_dft_r=the constrained potential
1204 : !!
1205 : !! NOTES
1206 : !! based on html notes for the VASP implementation at
1207 : !! http://cms.mpi.univie.ac.at/vasp/vasp/Constraining_direction_magnetic_moments.html
1208 : !!
1209 : !! SOURCE
1210 :
1211 109 : subroutine mag_penalty(c_dft,mpi_enreg,rhor,nv_constr_dft_r,xred,qgbt,use_gbt)
1212 :
1213 : !Arguments ------------------------------------
1214 : !scalars
1215 : class(constrained_dft_t),intent(in) :: c_dft
1216 : integer,intent(in) :: use_gbt
1217 : real(dp),intent(out) :: nv_constr_dft_r(c_dft%nfftf,c_dft%nspden)
1218 : type(MPI_type),intent(in) :: mpi_enreg
1219 : !arrays
1220 : real(dp),intent(in) :: rhor(c_dft%nfftf,c_dft%nspden)
1221 : real(dp),intent(in) :: xred(3,c_dft%natom),qgbt(3)
1222 :
1223 : !Local variables-------------------------------
1224 : !scalars
1225 : integer :: iatom,magconon,natom,nfftf,nspden,ntypat,option
1226 : integer,parameter :: cplex1=1
1227 : real(dp):: cmm_x,cmm_y,cmm_z,intgden_proj,norm
1228 : !arrays
1229 109 : real(dp), allocatable :: coeffs_constr_dft(:,:) ! nspden,natom
1230 109 : real(dp), allocatable :: intgden(:,:) ! nspden,natom
1231 218 : real(dp) :: rhomag(2,c_dft%nspden),spinat_normed(3)
1232 : ! ***********************************************************************************************
1233 :
1234 109 : magconon=c_dft%magconon
1235 109 : natom=c_dft%natom
1236 109 : nfftf=c_dft%nfftf
1237 109 : nspden=c_dft%nspden
1238 109 : ntypat=c_dft%ntypat
1239 :
1240 436 : ABI_MALLOC(coeffs_constr_dft,(nspden,natom))
1241 327 : ABI_MALLOC(intgden,(nspden,natom))
1242 :
1243 : !We need the integrated magnetic moments and the smoothing function
1244 : call calcdenmagsph(mpi_enreg,natom,nfftf,c_dft%ngfftf,nspden,ntypat,&
1245 109 : c_dft%ratsm,c_dft%ratsph,rhor,c_dft%rprimd,c_dft%typat,xred,1,cplex1,qgbt,use_gbt,intgden=intgden,rhomag=rhomag)
1246 :
1247 218 : call prtdenmagsph(cplex1,intgden,natom,nspden,ntypat,[std_out],1,qgbt,c_dft%ratsm,c_dft%ratsph,rhomag,c_dft%typat,c_dft%znucl,c_dft%spinaxis)
1248 :
1249 : !Loop over atoms
1250 : !-------------------------------------------
1251 218 : do iatom=1,natom
1252 :
1253 436 : norm = sqrt(sum(c_dft%spinat(:,iatom)**2))
1254 109 : spinat_normed(:) = zero
1255 109 : if (norm > tol10) then
1256 436 : spinat_normed(:) = c_dft%spinat(:,iatom) / norm
1257 0 : else if (magconon == 1) then
1258 : ! if spinat = 0 and we are imposing the direction only, skip this atom
1259 : cycle
1260 : end if
1261 :
1262 : ! Calculate the x- and y-components of the square bracket term
1263 109 : cmm_x = zero
1264 109 : cmm_y = zero
1265 109 : cmm_z = zero
1266 109 : intgden_proj = zero
1267 109 : if (nspden == 4) then
1268 65 : if (magconon==1) then
1269 : ! Calculate the scalar product of the fixed mag. mom. vector and calculated mag. mom. vector
1270 : ! This is actually the size of the projection of the calc. mag. mom. vector on the fixed mag. mom. vector
1271 : intgden_proj=spinat_normed(1)*intgden(2,iatom)+ &
1272 : & spinat_normed(2)*intgden(3,iatom)+ &
1273 54 : & spinat_normed(3)*intgden(4,iatom)
1274 :
1275 54 : cmm_x=intgden(2,iatom)
1276 54 : cmm_x=cmm_x-spinat_normed(1)*intgden_proj
1277 :
1278 54 : cmm_y=intgden(3,iatom)
1279 54 : cmm_y=cmm_y-spinat_normed(2)*intgden_proj
1280 :
1281 11 : else if (magconon==2 .and. nspden == 4) then
1282 11 : cmm_x=intgden(2,iatom)-c_dft%spinat(1,iatom)
1283 11 : cmm_y=intgden(3,iatom)-c_dft%spinat(2,iatom)
1284 : end if
1285 :
1286 : ! Calculate the constraining potential for x- and y- components of the mag. mom. vector
1287 : ! Eric Bousquet has derived the relationship between spin components and potential spin matrix elements:
1288 : ! 1 = up up = +z
1289 : ! 2 = down down = -z
1290 : ! 3 = up down = +x
1291 : ! 4 = down up = -y
1292 65 : coeffs_constr_dft(3,iatom)= 2*c_dft%magcon_lambda*cmm_x
1293 65 : coeffs_constr_dft(4,iatom)=-2*c_dft%magcon_lambda*cmm_y
1294 : end if ! nspden 4
1295 :
1296 : ! Calculate the z-component of the square bracket term
1297 109 : if (magconon==1) then
1298 79 : if (nspden == 4) then
1299 : ! This apparently enforces the axis of magnetization, not its direction.
1300 : ! m_z - spinat_z * <m | spinat>
1301 54 : cmm_z = intgden(4,iatom) - spinat_normed(3)*intgden_proj
1302 25 : else if (nspden == 2) then
1303 : ! This apparently enforces the direction of the magnetization. So, the behaviour differs in nspden=4 and 2 cases .
1304 : ! this will be just a sign +/- : are we in the same direction as spinat_z?
1305 : ! need something more continuous??? To make sure the gradient pushes the state towards FM/AFM?
1306 25 : cmm_z = -sign(one, (intgden(1,iatom)-intgden(2,iatom))*spinat_normed(3))
1307 : end if
1308 30 : else if (magconon==2) then
1309 30 : if (nspden == 4) then
1310 11 : cmm_z=intgden(4,iatom)-c_dft%spinat(3,iatom)
1311 19 : else if (nspden == 2) then
1312 : ! this is up spins - down spins - requested moment ~ 0
1313 : ! EB: note that intgden comes from calcdenmagsph, which, in nspden=2 case, returns
1314 : ! intgden(1)=rho_up=n+m
1315 : ! intgden(2)=rho_dn=n-m
1316 : ! Then, is the following line be
1317 : ! cmm_z=half*(intgden(1,iatom)-intgden(2,iatom)) - spinat(3,iatom)
1318 : ! ??
1319 19 : cmm_z=intgden(1,iatom)-intgden(2,iatom) - c_dft%spinat(3,iatom)
1320 : end if
1321 : endif
1322 :
1323 : ! Calculate the constraining potential for z-component of the mag. mom. vector
1324 109 : coeffs_constr_dft(1,iatom)= 2*c_dft%magcon_lambda*cmm_z
1325 218 : coeffs_constr_dft(2,iatom)=-2*c_dft%magcon_lambda*cmm_z
1326 :
1327 : enddo ! iatom
1328 :
1329 : !Now compute the potential in real space
1330 109 : option=0
1331 : call add_atomic_fcts(natom,nspden,c_dft%rprimd,mpi_enreg,nfftf,c_dft%ngfftf,ntypat,option,c_dft%ratsph, &
1332 109 : c_dft%ratsm,c_dft%typat,coeffs_constr_dft,nv_constr_dft_r,xred) ! Ben change: add ratsm
1333 :
1334 109 : ABI_FREE(coeffs_constr_dft)
1335 109 : ABI_FREE(intgden)
1336 :
1337 109 : end subroutine mag_penalty
1338 : !!***
1339 :
1340 : !!****f* m_dens/mag_penalty_e
1341 : !! NAME
1342 : !! mag_penalty_e
1343 : !!
1344 : !! FUNCTION
1345 : !! Compute the energy corresponding to constrained magnetic moments.
1346 : !!
1347 : !! INPUTS
1348 : !! magconon=constraining option (on/off); 1=fix only the direction, 2=fix the direction and size
1349 : !! spinat=fixed magnetic moments vectors
1350 : !! magcon_lambda=the size of the penalty terms
1351 : !!
1352 : !! OUTPUT
1353 : !! Epen=penalty contribution to the total energy corresponding to the constrained potential
1354 : !! Econstr=???
1355 : !! Eexp=???
1356 : !!
1357 : !! SOURCE
1358 :
1359 5 : subroutine mag_penalty_e(magconon,magcon_lambda,mpi_enreg,natom,nfft,ngfft,nspden,ntypat,ratsm,ratsph,rhor,rprimd,spinat,typat,xred,znucl,qgbt,use_gbt,spinaxis)
1360 :
1361 : !Arguments ------------------------------------
1362 : !scalars
1363 : integer,intent(in) :: natom,magconon,nspden,nfft,ntypat,use_gbt
1364 : real(dp),intent(in) :: magcon_lambda,ratsm,qgbt(3)
1365 : !arrays
1366 : integer, intent(in) :: ngfft(18),typat(natom)
1367 : real(dp),intent(in) :: spinat(3,natom), rprimd(3,3),znucl(ntypat),spinaxis(3)
1368 : real(dp),intent(in) :: ratsph(ntypat),rhor(nfft,nspden),xred(3,natom)
1369 : type(MPI_type),intent(in) :: mpi_enreg
1370 :
1371 : !Local variables-------------------------------
1372 : !scalars
1373 : integer :: iatom,ii
1374 : integer,parameter :: cplex1=1 ! dummy argument for calcdenmagsph
1375 : real(dp) :: intgden_proj, Epen,Econstr,lVp, norm
1376 : !arrays
1377 : real(dp) :: intmm(3), mag_1atom(3)
1378 5 : real(dp), allocatable :: intgden(:,:)
1379 : real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3),ucvol
1380 10 : real(dp) :: rhomag(2,nspden),spinat_normed(3)
1381 : character(len=500) :: msg
1382 : ! *********************************************************************
1383 :
1384 : !We need the metric because it is needed in calcdenmagsph.F90
1385 5 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
1386 :
1387 20 : ABI_MALLOC(intgden, (nspden,natom))
1388 :
1389 : !We need the integrated magnetic moments
1390 : call calcdenmagsph(mpi_enreg,natom,nfft,ngfft,nspden,ntypat,ratsm,ratsph,rhor,rprimd,typat,xred,&
1391 5 : 1,cplex1,qgbt,use_gbt,intgden=intgden,rhomag=rhomag)
1392 :
1393 10 : call prtdenmagsph(cplex1,intgden,natom,nspden,ntypat,[std_out],1,qgbt,ratsm,ratsph,rhomag,typat,znucl,spinaxis)
1394 :
1395 5 : Epen=0
1396 5 : Econstr=0
1397 5 : lVp=0
1398 :
1399 : !Loop over atoms
1400 : !-------------------------------------------
1401 10 : do iatom=1,natom
1402 :
1403 20 : norm = sqrt(sum(spinat(:,iatom)**2))
1404 5 : spinat_normed(:) = zero
1405 5 : if (norm > tol10) then
1406 20 : spinat_normed(:) = spinat(:,iatom) / norm
1407 0 : else if (magconon == 1) then
1408 : ! if spinat = 0 and we are imposing the direction only, skip this atom
1409 : cycle
1410 : end if
1411 : ! Calculate the scalar product of the fixed mag. mom. vector and calculated mag. mom. vector
1412 : ! This is actually the size of the projection of the calc. mag. mom. vector on the fixed mag. mom. vector
1413 :
1414 : ! for the collinear spin case, set up a fictitious 3D vector along z
1415 5 : if (nspden == 4) then
1416 12 : mag_1atom(1:3) = intgden(2:4,iatom)
1417 2 : else if (nspden == 2) then
1418 2 : mag_1atom = zero
1419 2 : mag_1atom(3) = intgden(1,iatom)-intgden(2,iatom)
1420 : end if
1421 :
1422 5 : intgden_proj = zero
1423 5 : intmm = zero
1424 : ! Calculate the square bracket term
1425 5 : if (magconon==1) then
1426 : intgden_proj=spinat_normed(1)*mag_1atom(1)+ &
1427 : & spinat_normed(2)*mag_1atom(2)+ &
1428 3 : & spinat_normed(3)*mag_1atom(3)
1429 :
1430 12 : do ii=1,3
1431 12 : intmm(ii)=mag_1atom(ii)-spinat_normed(ii)*intgden_proj
1432 : end do
1433 :
1434 : ! Calculate the energy Epen corresponding to the constraining potential
1435 : ! Econstr and lVp do not have a clear meaning (yet)
1436 3 : Epen=Epen+magcon_lambda*(intmm(1)*intmm(1)+intmm(2)*intmm(2)+intmm(3)*intmm(3))
1437 3 : Econstr=Econstr-magcon_lambda*(intmm(1)*mag_1atom(1)+intmm(2)*mag_1atom(2)+intmm(3)*mag_1atom(3))
1438 3 : lVp=lVp+2*magcon_lambda*(intmm(1)*mag_1atom(1)+intmm(2)*mag_1atom(2)+intmm(3)*mag_1atom(3))
1439 :
1440 2 : else if (magconon==2) then
1441 8 : do ii=1,3
1442 8 : intmm(ii)=mag_1atom(ii)-spinat(ii,iatom)
1443 : end do
1444 :
1445 : ! Calculate the energy Epen corresponding to the constraining potential
1446 : ! Epen = -Econstr - lVp
1447 : ! Econstr = -M**2 + spinat**2
1448 : ! lVp = +2 M \cdot spinat
1449 2 : Epen=Epen+magcon_lambda*(intmm(1)*intmm(1)+intmm(2)*intmm(2)+intmm(3)*intmm(3))
1450 : Econstr=Econstr-magcon_lambda*(mag_1atom(1)*mag_1atom(1)+&
1451 : & mag_1atom(2)*mag_1atom(2)+&
1452 : & mag_1atom(3)*mag_1atom(3)) &
1453 : & +magcon_lambda*(spinat(1,iatom)*spinat(1,iatom)+&
1454 : & spinat(2,iatom)*spinat(2,iatom)+&
1455 2 : & spinat(3,iatom)*spinat(3,iatom))
1456 2 : lVp=lVp+2*magcon_lambda*(intmm(1)*mag_1atom(1)+intmm(2)*mag_1atom(2)+intmm(3)*mag_1atom(3))
1457 : end if
1458 :
1459 5 : write(msg, *) 'atom constraining magnetic field'
1460 5 : call wrtout(std_out,msg)
1461 : write(msg, '(I3,A2,E12.5,A2,E12.5,A2,E12.5)') &
1462 5 : iatom,' ',magcon_lambda*intmm(1),' ',magcon_lambda*intmm(2),' ',magcon_lambda*intmm(3)
1463 10 : call wrtout(std_out,msg)
1464 :
1465 : ! End loop over atoms
1466 : ! -------------------------------------------
1467 : end do
1468 :
1469 : !Printing
1470 5 : write(msg, '(A17,E10.3)' ) ' magcon_lambda = ',magcon_lambda
1471 5 : call wrtout(std_out,msg)
1472 5 : write(msg, '(A17,E12.5)' ) ' Lagrange penalty = ',Epen
1473 5 : call wrtout(std_out,msg)
1474 5 : write(msg, '(A17,E12.5)' ) ' E_constraint = ',Econstr
1475 5 : call wrtout(std_out,msg)
1476 5 : write(msg, '(A17,E12.5)' ) ' lVp = ',lVp
1477 5 : call wrtout(std_out,msg)
1478 :
1479 5 : ABI_FREE(intgden)
1480 :
1481 5 : end subroutine mag_penalty_e
1482 : !!***
1483 :
1484 : !!****f* m_dens/calcdenmagsph
1485 : !! NAME
1486 : !! calcdenmagsph
1487 : !!
1488 : !! FUNCTION
1489 : !! Compute and print integral of total density inside spheres around atoms,
1490 : !! or optionally of integral of potential residual.
1491 : !! Also can compute the contributions to forces and stresses due to density-magnetization type constraints.
1492 : !!
1493 : !! INPUTS
1494 : !! mpi_enreg=information about MPI parallelization
1495 : !! natom=number of atoms in cell.
1496 : !! nfft=(effective) number of FFT grid points (for this processor)
1497 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
1498 : !! nspden=number of spin-density components
1499 : !! ntypat=number of atom types
1500 : !! ratopt= if 1 the atomic spheres are defined in real space
1501 : !! if 2 the atomic spheres are dfined in reciprocal space and then Fourier transformed
1502 : !! option = if not larger than 10, then a density is input , if larger than 10 then a potential residual is input.
1503 : !! ratsm=smearing width for ratsph
1504 : !! ratsph(ntypat)=radius of spheres around atoms
1505 : !! rhor(nfft,nspden)=array for electron density in electrons/bohr**3.
1506 : !! (total in first half and spin-up in second half if nspden=2)
1507 : !! (total in first comp. and magnetization in comp. 2 to 4 if nspden=4)
1508 : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
1509 : !! typat(natom)=type of each atom
1510 : !! xred(3,natom)=reduced dimensionless atomic coordinates
1511 : !! [qphon(3)]= perturbation wave vector.
1512 : !!
1513 : !! OUTPUT
1514 : !! dentot(nspden)=integrated density (magnetization...) over full u.c. vol. Optional argument
1515 : !! gr_intgden(3,nspden,natom)=grad wrt atomic positions, of integrated density (magnetization...) for each atom in a sphere. Optional arg
1516 : !! intgden(nspden, natom)=integrated density (magnetization...) for each atom in a sphere of radius ratsph. Optional arg
1517 : !! Note that when intgden is present, the definition of the spherical integration function changes, as it is smoothed.
1518 : !! intgf2(natom,natom)=overlaps of the spherical integration functions for each atom in a sphere of radius ratsph. Optional arg
1519 : !! rhomag(2,nspden)=integrated complex density (magnetization...) over full u.c. vol. Optional argument
1520 : !! In collinear case component 1 is total density and 2 is _magnetization_ up-down
1521 : !! In non collinear case component 1 is total density, and 2:4 are the magnetization vector
1522 : !! strs_intgden(6,nspden,natom)=stress contribution due to constrained integrated density (magnetization...), due to each atom. Optional arg
1523 : !! fatsph(nfft,natom)= functions defining the atomic spheres of integration in real space
1524 : !! taumr(nfft,natom,3)= array describing r-xred(iatom) at any point of the FFT grid
1525 : !! Rest is printing
1526 : !!
1527 : !! SOURCE
1528 :
1529 56610 : subroutine calcdenmagsph(mpi_enreg,natom,nfft,ngfft,nspden,ntypat,ratsm,ratsph,rhor,rprimd,typat,xred,&
1530 21602 : & option,cplex,qgbt,use_gbt,dentot,gr_intgden,intgden,intgf2,rhomag,strs_intgden,fatsph,qphon,taumr)
1531 :
1532 : !Arguments ---------------------------------------------
1533 : !scalars
1534 : integer,intent(in) :: natom,nfft,nspden,ntypat
1535 : real(dp),intent(in) :: ratsm
1536 : type(MPI_type),intent(in) :: mpi_enreg
1537 : integer,intent(in) :: option
1538 : integer,intent(in) :: cplex
1539 : integer,intent(in) :: use_gbt
1540 : !arrays
1541 : integer,intent(in) :: ngfft(18),typat(natom)
1542 : real(dp),intent(in) :: ratsph(ntypat),rhor(cplex*nfft,nspden),rprimd(3,3)
1543 : real(dp),intent(in) :: xred(3,natom)
1544 : real(dp),intent(in) :: qgbt(3)
1545 : real(dp),intent(out),optional :: dentot(nspden)
1546 : real(dp),intent(out),optional :: gr_intgden(3,nspden,natom)
1547 : real(dp),intent(out),optional :: intgden(cplex,nspden,natom)
1548 : real(dp),intent(out),optional :: intgf2(natom,natom)
1549 : real(dp),intent(out),optional :: rhomag(2,nspden)
1550 : real(dp),intent(out),optional :: strs_intgden(6,nspden,natom)
1551 : real(dp),intent(out),optional,target :: fatsph(nfft,natom)
1552 : real(dp),intent(in),optional :: qphon(3)
1553 : real(dp),intent(out),optional,target :: taumr(nfft,natom,3)
1554 : !Local variables ------------------------------
1555 :
1556 : !scalars
1557 : integer,parameter :: ndir=3,ishift=5
1558 : integer :: i1,i2,i3,iatom,ierr,ifft_local,ii,isp,ispden,ix,iy,iz,izloc,jatom,n1,n1a,n1b,n2,ifft,ifft_local_cplex
1559 : integer :: neighbor_overlap,n2a,n2b,n3,n3a,n3b,nfftot,n4,n5,n6
1560 : ! integer :: n1c, n2c, n3c
1561 : integer :: jfft
1562 : real(dp) :: arg,phr1d_im,phr1d_re
1563 : real(dp),parameter :: delta=0.99_dp
1564 37740 : real(dp) :: difx,dify,difz,r2,r2atsph,rr1,rr2,rr3,rx,ry,rz,qr,mx,my,mz,rhor_local(nspden)
1565 : real(dp) :: dfsm,fact,fsm,ratsm2,ucvol
1566 : logical :: grid_found
1567 : !arrays
1568 18870 : integer, contiguous, pointer :: fftn3_distrib(:),ffti3_local(:)
1569 37740 : integer :: overlap_ij(natom,natom)
1570 : real(dp) :: gmet(3,3),gprimd(3,3),gr_intg(3,4)
1571 37740 : real(dp) :: intg(cplex,4),qphon_(3),rhomag_(2,nspden)
1572 : ! real(dp) :: intg_im(4),intg_re(4)
1573 : real(dp) :: strs(3,3),strs_cartred(3,3),strs_intg(6,4),tsec(2)
1574 56610 : real(dp) :: dist_ij(natom,natom),intgden_(cplex,nspden,natom)!,intgden_im_(nspden,natom)
1575 37740 : real(dp) :: my_xred(3, natom), rmet(3,3),xshift(3, natom), taumr_local(3)
1576 18870 : real(dp), allocatable :: fsm_atom(:,:)
1577 18870 : real(dp), ABI_CONTIGUOUS pointer :: fatsph_(:,:),taumr_(:,:,:)
1578 : !real(dp) :: rprimd_mod(3,3),strain
1579 : ! *************************************************************************
1580 :
1581 : !MG NOTE: the computation of intg is clearly wrong when cplex = 2 (DFPT)
1582 :
1583 18870 : n1=ngfft(1);n2=ngfft(2);n3=ngfft(3)
1584 18870 : n4=ngfft(4);n5=ngfft(5);n6=ngfft(6)
1585 18870 : nfftot=n1*n2*n3
1586 :
1587 : !Manage optinal arguments
1588 258634 : if(present(intgden)) intgden=zero
1589 65684 : if(present(gr_intgden)) gr_intgden=zero
1590 98438 : if(present(strs_intgden)) strs_intgden=zero
1591 18870 : qphon_=zero
1592 18870 : if(present(qphon))then
1593 74 : qphon_=qphon
1594 : endif
1595 :
1596 18870 : if(present(fatsph)) then
1597 62 : fatsph_ => fatsph
1598 952754 : fatsph_=zero
1599 : end if
1600 18870 : if(present(taumr)) then
1601 62 : taumr_ => taumr
1602 2858324 : taumr_=zero
1603 : end if
1604 :
1605 18870 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
1606 :
1607 : ! This routine is not able to handle xred positions that are "far" from the
1608 : ! first unit cell so wrap xred into [0, 1[ interval here.
1609 203078 : call wrap2_zero_one(xred, my_xred, xshift)
1610 :
1611 : !If intgf2 present, check that the spheres do not overlap. If they overlap, one needs to treat explicitly the neighbors.
1612 18870 : if(present(intgf2))then
1613 180 : neighbor_overlap=0
1614 498 : dist_ij(:,:)=zero
1615 498 : intgf2(:,:)=zero
1616 498 : overlap_ij(:,:)=0
1617 54 : dist_ij(1,1)=dist2(xred(:,1),xred(:,1),rprimd,-1)
1618 180 : do iatom=1,natom
1619 126 : dist_ij(iatom,iatom)=dist_ij(1,1)
1620 126 : overlap_ij(iatom,iatom)=1
1621 402 : do jatom=iatom,natom
1622 222 : if(iatom/=jatom)dist_ij(iatom,jatom)=dist2(xred(:,iatom),xred(:,jatom),rprimd,1)
1623 348 : if(dist_ij(iatom,jatom)-ratsph(typat(iatom))-ratsph(typat(jatom))<tol10)then
1624 49 : overlap_ij(iatom,jatom)=1
1625 49 : neighbor_overlap=1
1626 : endif
1627 : enddo
1628 : enddo
1629 54 : if(neighbor_overlap==1)then
1630 76 : ABI_MALLOC(fsm_atom,(nfft,natom))
1631 626181 : fsm_atom(:,:)=zero
1632 : endif
1633 : endif
1634 :
1635 : !Get the distrib associated with this fft_grid
1636 18870 : grid_found=.false.
1637 :
1638 18870 : if(n2 == mpi_enreg%distribfft%n2_coarse ) then
1639 13597 : if(n3== size(mpi_enreg%distribfft%tab_fftdp3_distrib)) then
1640 13543 : fftn3_distrib => mpi_enreg%distribfft%tab_fftdp3_distrib
1641 13543 : ffti3_local => mpi_enreg%distribfft%tab_fftdp3_local
1642 13543 : grid_found=.true.
1643 : end if
1644 : end if
1645 :
1646 18870 : if(n2 == mpi_enreg%distribfft%n2_fine ) then
1647 5535 : if(n3 == size(mpi_enreg%distribfft%tab_fftdp3dg_distrib)) then
1648 5535 : fftn3_distrib => mpi_enreg%distribfft%tab_fftdp3dg_distrib
1649 5535 : ffti3_local => mpi_enreg%distribfft%tab_fftdp3dg_local
1650 : grid_found = .true.
1651 : end if
1652 : end if
1653 :
1654 13335 : ABI_CHECK(grid_found, "Unable to find an allocated distrib for this fft grid")
1655 :
1656 : !Loop over atoms
1657 : !-------------------------------------------
1658 64922 : do iatom=1,natom
1659 :
1660 : ! Define a "box" around the atom that extends outside of the unit cell
1661 46052 : r2atsph=1.0000001_dp*ratsph(typat(iatom))**2
1662 46052 : rr1=sqrt(r2atsph*gmet(1,1))
1663 46052 : rr2=sqrt(r2atsph*gmet(2,2))
1664 46052 : rr3=sqrt(r2atsph*gmet(3,3))
1665 :
1666 46052 : n1a=int((my_xred(1,iatom)-rr1+ishift)*n1+delta)-ishift*n1
1667 46052 : n1b=int((my_xred(1,iatom)+rr1+ishift)*n1 )-ishift*n1
1668 46052 : n2a=int((my_xred(2,iatom)-rr2+ishift)*n2+delta)-ishift*n2
1669 46052 : n2b=int((my_xred(2,iatom)+rr2+ishift)*n2 )-ishift*n2
1670 46052 : n3a=int((my_xred(3,iatom)-rr3+ishift)*n3+delta)-ishift*n3
1671 46052 : n3b=int((my_xred(3,iatom)+rr3+ishift)*n3 )-ishift*n3
1672 :
1673 : !This is the "width" of the zone of smearing, in term of the square of radius
1674 46052 : ratsm2 = (2*ratsph(typat(iatom))-ratsm)*ratsm
1675 :
1676 417416 : intg(:,:)=zero
1677 46052 : gr_intg(:,:)=zero
1678 46052 : strs_intg(:,:)=zero
1679 :
1680 629449 : do i3=n3a,n3b
1681 583397 : iz=mod(i3+ishift*n3,n3)
1682 :
1683 629449 : if(fftn3_distrib(iz+1)==mpi_enreg%me_fft) then
1684 :
1685 572411 : izloc = ffti3_local(iz+1) - 1
1686 572411 : difz=dble(i3)/dble(n3)-my_xred(3,iatom)
1687 9884125 : do i2=n2a,n2b
1688 9311714 : iy=mod(i2+ishift*n2,n2)
1689 9311714 : dify=dble(i2)/dble(n2)-my_xred(2,iatom)
1690 208950021 : do i1=n1a,n1b
1691 199065896 : ix=mod(i1+ishift*n1,n1)
1692 199065896 : difx=dble(i1)/dble(n1)-my_xred(1,iatom)
1693 : !DEBUG
1694 : ! if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then
1695 : ! difx=dble(i1)/dble(n1)-(my_xred(1,iatom)+0.00005)
1696 : ! endif
1697 : !ENDDEBUG
1698 199065896 : rx=difx*rprimd(1,1)+dify*rprimd(1,2)+difz*rprimd(1,3)
1699 :
1700 : !DEBUG
1701 : ! if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then
1702 : ! strain=-0.001
1703 : ! rx=difx*rprimd(1,1)*(one+strain)+dify*rprimd(1,2)+difz*rprimd(1,3)
1704 : ! endif
1705 : !ENDDEBUG
1706 :
1707 199065896 : ry=difx*rprimd(2,1)+dify*rprimd(2,2)+difz*rprimd(2,3)
1708 199065896 : rz=difx*rprimd(3,1)+dify*rprimd(3,2)+difz*rprimd(3,3)
1709 199065896 : r2=rx**2+ry**2+rz**2
1710 :
1711 : ! Identify the fft indexes of the rectangular grid around the atom
1712 199065896 : if(r2 > r2atsph) then
1713 : cycle
1714 : end if
1715 :
1716 88854453 : call radsmear(dfsm,fsm,r2,r2atsph,ratsm2)
1717 :
1718 88854453 : ifft_local=1+ix+n1*(iy+n2*izloc)
1719 :
1720 88854453 : if(present(fatsph)) then
1721 60636 : fatsph_(ifft_local,iatom)=fsm
1722 : end if
1723 88854453 : if(present(taumr)) then
1724 60636 : taumr_(ifft_local,iatom,1)=difx
1725 60636 : taumr_(ifft_local,iatom,2)=dify
1726 60636 : taumr_(ifft_local,iatom,3)=difz
1727 : end if
1728 :
1729 : ! Compute the finite-q real-space phase
1730 88854453 : taumr_local(1)=difx
1731 88854453 : taumr_local(2)=dify
1732 88854453 : taumr_local(3)=difz
1733 355417812 : arg=two_pi*dot_product(qphon_,taumr_local)
1734 88854453 : phr1d_re=dcos(arg)
1735 88854453 : phr1d_im=dsin(arg)
1736 88854453 : ifft_local_cplex=1+cplex*(ifft_local-1)
1737 :
1738 88854453 : if(present(intgf2))then
1739 : ! intgden_(1,iatom)= integral of the square of the spherical integrating function
1740 109724 : if(neighbor_overlap==0)intgf2(iatom,iatom)=intgf2(iatom,iatom)+fsm*fsm
1741 13136 : if(neighbor_overlap==1)fsm_atom(ifft_local,iatom)=fsm_atom(ifft_local,iatom)+fsm
1742 : endif
1743 :
1744 88854453 : if (nspden==4 .and. use_gbt /= 0) then
1745 : ! If GBT is on, we have to include the e^{iq.r} phase
1746 206397 : qr = two_pi * (qgbt(1)*dble(i1)/dble(n1) + qgbt(2)*dble(i2)/dble(n2) + qgbt(3)*dble(i3)/dble(n3))
1747 206397 : rhor_local(1) = rhor(ifft_local,1)
1748 206397 : mx = rhor(ifft_local,2)
1749 206397 : my = rhor(ifft_local,3)
1750 206397 : mz = rhor(ifft_local,4)
1751 : ! e^-iqr :cos(qr)-isin(qr)
1752 206397 : rhor_local(2) = cos(qr)*mx - sin(qr)*my ! mx
1753 206397 : rhor_local(3) = sin(qr)*mx + cos(qr)*my ! my
1754 206397 : rhor_local(4) = mz
1755 : else
1756 259685971 : rhor_local(1:nspden) = rhor(ifft_local,1:nspden)
1757 : end if
1758 : ! Integral of density or potential residual
1759 88854453 : if (cplex==1) then
1760 258756197 : intg(1,1:nspden)=intg(1,1:nspden)+fsm*rhor(ifft_local,1:nspden)
1761 457533 : else if (cplex==2) then
1762 1830132 : if (sum(qphon_(:)**2)<tol8) then
1763 1823959 : intg(1,1:nspden)=intg(1,1:nspden)+fsm*rhor(2*ifft_local-1,1:nspden)
1764 1823959 : intg(2,1:nspden)=intg(2,1:nspden)+fsm*rhor(2*ifft_local ,1:nspden)
1765 : else
1766 137800 : intg(1,1:nspden)=intg(1,1:nspden)+phr1d_re*fsm*rhor(2*ifft_local-1,1:nspden)-phr1d_im*fsm*rhor(2*ifft_local ,1:nspden)
1767 137800 : intg(2,1:nspden)=intg(2,1:nspden)+phr1d_re*fsm*rhor(2*ifft_local ,1:nspden)+phr1d_im*fsm*rhor(2*ifft_local-1,1:nspden)
1768 : end if
1769 : end if
1770 187020620 : if((present(gr_intgden).or.present(strs_intgden)).and. option<10 .and. ratsm2>tol12)then
1771 11337976 : do ispden=1,nspden
1772 7873026 : fact=dfsm*rhor(ifft_local_cplex,ispden)
1773 7873026 : if(present(gr_intgden))then
1774 7873026 : gr_intg(1,ispden)=gr_intg(1,ispden)+difx*fact
1775 7873026 : gr_intg(2,ispden)=gr_intg(2,ispden)+dify*fact
1776 7873026 : gr_intg(3,ispden)=gr_intg(3,ispden)+difz*fact
1777 : endif
1778 11337976 : if(present(strs_intgden))then
1779 7873026 : strs_intg(1,ispden)=strs_intg(1,ispden)+difx*difx*fact
1780 7873026 : strs_intg(2,ispden)=strs_intg(2,ispden)+dify*dify*fact
1781 7873026 : strs_intg(3,ispden)=strs_intg(3,ispden)+difz*difz*fact
1782 7873026 : strs_intg(4,ispden)=strs_intg(4,ispden)+dify*difz*fact
1783 7873026 : strs_intg(5,ispden)=strs_intg(5,ispden)+difx*difz*fact
1784 7873026 : strs_intg(6,ispden)=strs_intg(6,ispden)+difx*dify*fact
1785 : endif
1786 : enddo
1787 : endif
1788 : end do
1789 : end do
1790 : end if
1791 : end do
1792 :
1793 :
1794 : !DEBUG
1795 : ! n1c=(n1b+n1a)/2
1796 : ! n2c=(n2b+n2a)/2
1797 : ! do i3= n3a-5,n3b+5
1798 : ! n1c=mod(n1c+ishift*n1,n1)
1799 : ! n2c=mod(n2c+ishift*n2,n2)
1800 : ! iz=mod(i3+ishift*n3,n3)
1801 : ! end do
1802 : !ENDDEBUG
1803 :
1804 :
1805 46052 : if(present(intgf2) .and. neighbor_overlap==0)then
1806 76 : intgf2(iatom,iatom)=intgf2(iatom,iatom)*ucvol/dble(nfftot)
1807 : endif
1808 :
1809 417416 : intg(:,:)=intg(:,:)*ucvol/dble(nfftot)
1810 :
1811 46052 : if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then
1812 : ! Convert to gradient in reduced coordinates
1813 166526 : gr_intg=matmul(rmet,gr_intg)
1814 53414 : gr_intg(:,:)=-gr_intg(:,:)*two*ucvol/dble(nfftot)
1815 : !DEBUG
1816 : ! write(6,*)' calcdenmagsph : intg(1)=',intg(1)
1817 : ! write(6,*)' calcdenmagsph : iatom,gr_intg(1,1)=',iatom,gr_intg(1,1)
1818 : ! call flush(6)
1819 : ! stop
1820 : !ENDDEBUG
1821 : endif
1822 :
1823 46052 : if(present(strs_intgden).and. option<10 .and. ratsm2>tol12)then
1824 : ! Convert to stress in cartesian coordinates, for each spin constraint
1825 15710 : do isp=1,4
1826 : ! First change the representation
1827 12568 : strs(1,1)=strs_intg(1,isp) ; strs(2,2)=strs_intg(2,isp) ; strs(3,3)=strs_intg(3,isp)
1828 12568 : strs(2,3)=strs_intg(4,isp) ; strs(3,2)=strs_intg(4,isp)
1829 12568 : strs(1,3)=strs_intg(5,isp) ; strs(3,1)=strs_intg(5,isp)
1830 12568 : strs(1,2)=strs_intg(6,isp) ; strs(2,1)=strs_intg(6,isp)
1831 :
1832 : ! Then perform representation change, following Eq.(25) in Hamann2005
1833 50272 : do ii=1,3
1834 615832 : strs_cartred(:,ii)=matmul(rprimd,strs(:,ii))
1835 : enddo
1836 50272 : do ii=1,3
1837 615832 : strs(ii,:)=matmul(rprimd,strs_cartred(ii,:))
1838 : enddo
1839 :
1840 : !DEBUG
1841 : ! rprimd_mod=rprimd
1842 : ! rprimd_mod(1,1)=rprimd(1,1)*(one+strain)
1843 : ! do ii=1,3
1844 : ! strs_cartred(:,ii)=matmul(rprimd_mod,strs(:,ii))
1845 : ! enddo
1846 : ! do ii=1,3
1847 : ! strs(ii,:)=matmul(rprimd_mod,strs_cartred(ii,:))
1848 : ! enddo
1849 : !ENDDEBUG
1850 :
1851 12568 : strs_intg(1,isp)=two*strs(1,1) ; strs_intg(2,isp)=two*strs(2,2) ; strs_intg(3,isp)=two*strs(3,3)
1852 12568 : strs_intg(4,isp)=strs(2,3)+strs(3,2)
1853 12568 : strs_intg(5,isp)=strs(1,3)+strs(3,1)
1854 15710 : strs_intg(6,isp)=strs(1,2)+strs(2,1)
1855 : enddo
1856 91118 : strs_intg(:,:)=strs_intg(:,:)/dble(nfftot)
1857 : !DEBUG
1858 : ! strs_intg(:,:)=zero
1859 : ! write(6,*)' calcdenmagsph : iatom,-strs_intg(1,1)*ucvol=',iatom,strs_intg(1,1)*ucvol
1860 : ! call flush(6)
1861 : ! stop
1862 : !ENDDEBUG
1863 : endif
1864 :
1865 64922 : if(nspden==2 .and. option/=11)then
1866 : ! Specific treatment of collinear density, due to the storage mode.
1867 : ! intgden_(1,iatom)= integral of up density
1868 : ! intgden_(2,iatom)= integral of dn density
1869 29771 : intgden_(1:cplex,1,iatom)=intg(1:cplex,2)
1870 29771 : intgden_(1:cplex,2,iatom)=intg(1:cplex,1)-intg(1:cplex,2)
1871 : !if (cplex==2) then
1872 : ! intgden_im_(1,iatom)=intg(2,2)
1873 : ! intgden_im_(2,iatom)=intg(2,1)-intg(2,2)
1874 : !endif
1875 14825 : if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then
1876 2040 : gr_intgden(:,1,iatom)=gr_intg(:,2)
1877 2040 : gr_intgden(:,2,iatom)=gr_intg(:,1)-gr_intg(:,2)
1878 : endif
1879 14825 : if(present(strs_intgden).and. option<10 .and. ratsm2>tol12)then
1880 3570 : strs_intgden(:,1,iatom)=strs_intg(:,2)
1881 3570 : strs_intgden(:,2,iatom)=strs_intg(:,1)-strs_intg(:,2)
1882 : endif
1883 : else
1884 166429 : intgden_(1:cplex,1:nspden,iatom)=intg(1:cplex,1:nspden)
1885 31227 : if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then
1886 42224 : gr_intgden(:,1:nspden,iatom)=gr_intg(:,1:nspden)
1887 : endif
1888 31227 : if(present(strs_intgden).and. option<10 .and. ratsm2>tol12)then
1889 71918 : strs_intgden(:,1:nspden,iatom)=strs_intg(:,1:nspden)
1890 : endif
1891 : endif
1892 :
1893 : end do ! iatom
1894 :
1895 : !-------------------------------------------
1896 : !
1897 : ! In case intgf2 must be computed, while the atoms overlap, a double loop over atoms is needed
1898 18870 : if(present(intgf2) .and. neighbor_overlap==1)then
1899 69 : do iatom=1,natom
1900 149 : do jatom=iatom,natom
1901 149 : if(overlap_ij(iatom,jatom)/=0)then
1902 1935 : do i3=1,n3
1903 1836 : iz=mod(i3,n3)
1904 1935 : if(fftn3_distrib(iz+1)==mpi_enreg%me_fft) then
1905 1836 : izloc = ffti3_local(iz+1) - 1
1906 42300 : do i2=1,n2
1907 40464 : iy=mod(i2,n2)
1908 1128348 : do i1=1,n1
1909 1086048 : ix=mod(i1,n1)
1910 1086048 : ifft_local=1+ix+n1*(iy+n2*izloc)
1911 1126512 : intgf2(iatom,jatom)=intgf2(iatom,jatom)+fsm_atom(ifft_local,iatom)*fsm_atom(ifft_local,jatom)
1912 : enddo
1913 : enddo
1914 : endif
1915 : enddo ! i3
1916 99 : intgf2(iatom,jatom)=intgf2(iatom,jatom)*ucvol/dble(nfftot)
1917 : endif
1918 : enddo
1919 69 : if(iatom/=1)then
1920 80 : do jatom=1,iatom-1
1921 80 : intgf2(iatom,jatom)=intgf2(jatom,iatom)
1922 : enddo
1923 : endif
1924 : enddo
1925 19 : ABI_FREE(fsm_atom)
1926 : endif
1927 :
1928 : !MPI parallelization
1929 18870 : if(present(intgf2)) then
1930 54 : if(mpi_enreg%nproc_fft>1)then
1931 0 : call timab(48,1,tsec)
1932 0 : call xmpi_sum(intgf2,mpi_enreg%comm_fft,ierr)
1933 0 : call timab(48,2,tsec)
1934 : end if
1935 : end if
1936 :
1937 : !-------------------------------------------
1938 :
1939 : !MPI parallelization
1940 18870 : if(present(intgden) .or. option/=0) then
1941 18816 : if(mpi_enreg%nproc_fft>1)then
1942 544 : call timab(48,1,tsec)
1943 544 : call xmpi_sum(intgden_,mpi_enreg%comm_fft,ierr)
1944 544 : call timab(48,2,tsec)
1945 : end if
1946 258634 : if(present(intgden))intgden = intgden_
1947 : end if
1948 :
1949 18870 : if(present(gr_intgden) .and. option<10 .and. ratsm2>tol12) then
1950 1304 : if(mpi_enreg%nproc_fft>1)then
1951 0 : call timab(48,1,tsec)
1952 0 : call xmpi_sum(gr_intgden,mpi_enreg%comm_fft,ierr)
1953 0 : call timab(48,2,tsec)
1954 : end if
1955 : end if
1956 :
1957 18870 : if(present(strs_intgden) .and. option<10 .and. ratsm2>tol12) then
1958 1304 : if(mpi_enreg%nproc_fft>1)then
1959 0 : call timab(48,1,tsec)
1960 0 : call xmpi_sum(strs_intgden,mpi_enreg%comm_fft,ierr)
1961 0 : call timab(48,2,tsec)
1962 : end if
1963 : end if
1964 :
1965 : !EB - Compute magnetization of the whole cell
1966 18870 : if(present(dentot) .or. present(rhomag))then
1967 74090 : rhomag_(:,:)=zero
1968 11282 : if(nspden==2) then
1969 50425001 : do ifft=1,nfft
1970 50422382 : jfft=1+cplex*(ifft-1)
1971 101245604 : rhomag_(1:cplex,1)=rhomag_(1:cplex,1)+rhor(jfft:jfft+cplex-1,1) ! real & imag part of density
1972 101248223 : rhomag_(1:cplex,2)=rhomag_(1:cplex,2)+2*rhor(jfft:jfft+cplex-1,2)-rhor(jfft:jfft+cplex-1,1) ! real & imag part of magnetization
1973 : end do
1974 8663 : else if(nspden==4) then
1975 27223670 : do ifft=1,nfft
1976 27221325 : jfft=1+cplex*(ifft-1)
1977 247890142 : rhomag_(1:cplex,1:nspden)=rhomag_(1:cplex,1:nspden)+rhor(jfft:jfft+cplex-1,1:nspden)
1978 : end do
1979 : end if
1980 :
1981 53872 : rhomag_(1:cplex,1:nspden)=rhomag_(1:cplex,1:nspden)*ucvol/dble(nfftot)
1982 :
1983 : !MPI parallelization
1984 11282 : if(mpi_enreg%nproc_fft>1)then
1985 440 : call timab(48,1,tsec)
1986 440 : call xmpi_sum(rhomag_,mpi_enreg%comm_fft,ierr)
1987 440 : call timab(48,2,tsec)
1988 : end if
1989 :
1990 14812 : if(present(dentot)) dentot(:)=rhomag_(1,:)
1991 74090 : if(present(rhomag)) rhomag(:,:)=rhomag_(:,:)
1992 : endif
1993 :
1994 : !DEBUG BUT KEEP
1995 : !if(.false.) call printmagvtk(mpi_enreg,cplex,nspden,nfft,ngfft,rhor,rprimd,'DEN.vtk')
1996 :
1997 59342 : end subroutine calcdenmagsph
1998 : !!***
1999 :
2000 : !!****f* m_dens/prtdenmagsph
2001 : !! NAME
2002 : !! prtdenmagsph
2003 : !!
2004 : !! FUNCTION
2005 : !! Print integral of total density inside spheres around atoms,
2006 : !! and optionally integral of potential residual (also gradient of the constraint energy wrt constraint).
2007 : !!
2008 : !! INPUTS
2009 : !! intgden(nspden, natom)=integrated rhor or potential residual, for each atom in a sphere of radius ratsph.
2010 : !! if option <10, intgden is a density (+magnetization)
2011 : !! Representation differs according to nspden :
2012 : !! if nspden=1, total density
2013 : !! if nspden=2, spin up, then spin down
2014 : !! if nspden=4, total density, then mag_x, mag_y, mag_z
2015 : !! if 20>option>=10, intgden is a potential residual (+spin magnetic field residual).
2016 : !! Representation is: first, mean potential; then (if nspden>=2) B_z for nspden=2, B_x, B_y and B_z for nspden=4.
2017 : !! if option>=20, intgden is a a gradient wrt target (=torque), also potential residual (+spin magnetic field residual) multiplied by f-1.
2018 : !! natom=number of atoms in cell.
2019 : !! nspden=number of spin-density components
2020 : !! ntypat=number of atom types
2021 : !! units=unit numbers for printing
2022 : !! option = if not larger than 10, then a density is input , if between 10 and 19 then a potential residual is input, if beyond, a torque is input..
2023 : !! When 1, 11, 21, the default printing is on (to unit nunit), if -1, 2, 3, 4, special printing options, if 0 no printing.
2024 : !! ratsm=smearing width for ratsph
2025 : !! ratsph(ntypat)=radius of spheres around atoms
2026 : !! rhomag(2,nspden)=integral of charge or magnetization over the whole cell (also taking into account a possible imaginary part for DFPT).
2027 : !! typat(natom)=type of each atom
2028 : !! ziontypat(ntypat)= --optional-- ionic charge of each atomic type
2029 : !!
2030 : !! OUTPUT
2031 : !! Printing
2032 : !!
2033 : !! SOURCE
2034 :
2035 9802 : subroutine prtdenmagsph(cplex, intgden, natom, nspden, ntypat, units, option, qgbt, ratsm, ratsph, rhomag, typat, znucl, spinaxis, ziontypat)
2036 :
2037 : !Arguments ---------------------------------------------
2038 : !scalars
2039 : integer,intent(in) :: natom,nspden,ntypat
2040 : integer,intent(in) :: units(:)
2041 : real(dp),intent(in) :: ratsm
2042 : integer ,intent(in) :: option
2043 : integer, intent(in) :: cplex
2044 : !arrays
2045 : integer,intent(in) :: typat(natom)
2046 : real(dp),intent(in) :: intgden(cplex,nspden,natom),qgbt(3),znucl(ntypat),spinaxis(3)
2047 : real(dp),intent(in) :: ratsph(ntypat),rhomag(2,nspden)
2048 : real(dp),intent(in),optional :: ziontypat(ntypat)
2049 :
2050 : !Local variables ------------------------------
2051 : !scalars
2052 : integer :: iatom,icplex
2053 : real(dp) :: mag_coll , mag_x, mag_y, mag_z ! EB
2054 : real(dp) :: mag_coll_im, mag_x_im, mag_y_im, mag_z_im ! SPr
2055 : real(dp) :: rho_tot, rho_tot_im
2056 : real(dp) :: sum_mag, sum_mag_x,sum_mag_y,sum_mag_z,sum_rho_up,sum_rho_dn,sum_rho_tot ! EB
2057 : real(dp) :: sum_mag_im, sum_mag_x_im,sum_mag_y_im,sum_mag_z_im,sum_rho_up_im,sum_rho_dn_im,sum_rho_tot_im ! SR
2058 : real(dp) :: mag_r, mag_theta, mag_phi, vec(3)
2059 : real(dp) :: sum_mag_r, sum_mag_theta, sum_mag_phi
2060 : real(dp) :: exact_mag_r, exact_mag_theta, exact_mag_phi
2061 : real(dp) :: exact_mag_r_im, exact_mag_theta_im, exact_mag_phi_im
2062 : real(dp) :: alpha, beta, Rspin(3,3), Rspin_t(3,3), mag_cart(3), mag_spin(3), mag_tot_cart(3), mag_tot_cart_im(3)
2063 : character(len=500) :: msg,msg1
2064 : character(len=500) :: msg_cplex
2065 : type(atomdata_t) :: atom
2066 :
2067 : ! *************************************************************************
2068 : !write(ab_out,*)' prtdenmagsph : enter, rhomag(1,2)=',rhomag(1,2)
2069 :
2070 9802 : if(nspden==2)then
2071 1323 : rho_tot=rhomag(1,1) ; mag_coll=rhomag(1,2)
2072 1323 : if(cplex==2)then
2073 12 : rho_tot_im=rhomag(2,1) ; mag_coll_im=rhomag(2,2)
2074 : endif
2075 8479 : else if(nspden==4)then
2076 2156 : rho_tot=rhomag(1,1) ; mag_x=rhomag(1,2) ; mag_y=rhomag(1,3) ; mag_z=rhomag(1,4)
2077 2156 : if(cplex==2)then
2078 11 : rho_tot_im=rhomag(2,1) ; mag_x_im=rhomag(2,2) ; mag_y_im=rhomag(2,3) ; mag_z_im=rhomag(2,4)
2079 : endif
2080 : endif
2081 :
2082 9802 : if(option/=0)then
2083 :
2084 : !Printing
2085 9802 : sum_mag=zero
2086 9802 : sum_mag_x=zero
2087 9802 : sum_mag_y=zero
2088 9802 : sum_mag_z=zero
2089 9802 : sum_mag_x_im=zero
2090 9802 : sum_mag_y_im=zero
2091 9802 : sum_mag_z_im=zero
2092 9802 : sum_rho_up=zero
2093 9802 : sum_rho_dn=zero
2094 9802 : sum_rho_tot=zero
2095 :
2096 9802 : sum_mag_im=zero
2097 9802 : sum_mag_x_im=zero
2098 9802 : sum_mag_y_im=zero
2099 9802 : sum_mag_z_im=zero
2100 9802 : sum_rho_up_im=zero
2101 9802 : sum_rho_dn_im=zero
2102 9802 : sum_rho_tot_im=zero
2103 :
2104 : !Rotation matrices identity by default
2105 9802 : Rspin(:,:)=zero ; Rspin_t(:,:)=zero
2106 9802 : Rspin(1,1)=one ; Rspin(2,2)=one ; Rspin(3,3)=one
2107 9802 : Rspin_t(:,:)=Rspin(:,:)
2108 :
2109 : !Print spinaxis info only if axis not aligned with z
2110 9802 : if (abs(spinaxis(1))>tol8 .or. abs(spinaxis(2))>tol8) then
2111 1 : call geteuler(spinaxis, alpha, beta)
2112 1 : msg=' Spinaxis rotation information:'
2113 1 : write(msg, '(3a)' ) trim(msg),ch10,' ------------------------------'; call wrtout(units,msg)
2114 1 : write(msg, '(a,f12.6)') ' Alpha rotation angle around z-axis (degrees):', alpha * 180.0_dp / pi; call wrtout(units,msg)
2115 1 : write(msg, '(a,f12.6)') ' Beta rotation angle around y-axis (degrees): ', beta * 180.0_dp / pi; call wrtout(units,msg)
2116 1 : write(msg, '(a)') ' ---------------------------------------------------------'; call wrtout(units,msg)
2117 1 : call cart2spinaxis(alpha, beta, Rspin)
2118 1 : write(msg, '(a)') ' Rotation matrix from cartesian coordinate to spinaxis coordinate'; call wrtout(units,msg)
2119 1 : write(msg, '(3f14.8)') Rspin(1,1), Rspin(1,2), Rspin(1,3); call wrtout(units,msg)
2120 1 : write(msg, '(3f14.8)') Rspin(2,1), Rspin(2,2), Rspin(2,3); call wrtout(units,msg)
2121 1 : write(msg, '(3f14.8)') Rspin(3,1), Rspin(3,2), Rspin(3,3); call wrtout(units,msg)
2122 :
2123 13 : Rspin_t = transpose(Rspin)
2124 1 : write(msg, '(a)') ' Rotation matrix from spinaxis coordinate to cartesian coordinate'; call wrtout(units,msg)
2125 1 : write(msg, '(3f14.8)') Rspin_t(1,1), Rspin_t(1,2), Rspin_t(1,3); call wrtout(units,msg)
2126 1 : write(msg, '(3f14.8)') Rspin_t(2,1), Rspin_t(2,2), Rspin_t(2,3); call wrtout(units,msg)
2127 1 : write(msg, '(3f14.8)') Rspin_t(3,1), Rspin_t(3,2), Rspin_t(3,3); call wrtout(units,msg)
2128 1 : write(msg, '(a)') ' ----------------------------------------------------------------'
2129 1 : call wrtout(units,msg)
2130 : end if
2131 :
2132 9802 : mag_tot_cart=zero
2133 9802 : mag_tot_cart_im=zero
2134 9802 : if (nspden==4) then
2135 8624 : mag_spin = [mag_x,mag_y,mag_z]
2136 28028 : mag_tot_cart = matmul(Rspin_t,mag_spin)
2137 2156 : if (cplex==2) then
2138 44 : mag_spin = [mag_x_im,mag_y_im,mag_z_im]
2139 143 : mag_tot_cart_im = matmul(Rspin_t,mag_spin)
2140 : end if
2141 : end if
2142 :
2143 9802 : if(option==1 .or. option==11 .or. option==21) then
2144 :
2145 9802 : if(nspden==1) then
2146 6323 : if(option== 1)msg1=' Integrated electronic density in atomic spheres:'
2147 6323 : if(option==11)msg1=ch10//' Integrated potential residual in atomic spheres:'
2148 6323 : if(option==21)msg1=ch10//' Gradient with respect to target (=torque) :'
2149 6323 : write(msg, '(3a)' ) trim(msg1),ch10,' ------------------------------------------------'
2150 6323 : call wrtout(units,msg)
2151 6323 : if(ratsm>tol8)then
2152 221 : write(msg, '(a,f8.4,a)' ) ' Radius=ratsph(iatom), smearing ratsm=',ratsm,'.'
2153 221 : call wrtout(units,msg)
2154 : endif
2155 6323 : if(option== 1)then
2156 6213 : msg=' Atom Sphere_radius Integrated_density'
2157 6213 : if(present(ziontypat)) write(msg,'(a,a)')trim(msg),' Atomic charge'
2158 : endif
2159 6323 : if(option==11)msg=' Atom Sphere_radius Integrated_potresid'
2160 6323 : if(option==21)msg=' Atom Sphere_radius Torque'
2161 6323 : call wrtout(units,msg)
2162 25496 : do iatom=1,natom
2163 19173 : call atomdata_from_znucl(atom, znucl(typat(iatom)))
2164 19173 : write(msg, '(i5,f15.5,f20.8)' ) iatom,ratsph(typat(iatom)),intgden(1,1,iatom)
2165 : !write(msg, '(i5,a3,f15.5,f20.8)' ) iatom,atom%symbol,ratsph(typat(iatom)),intgden(1,1,iatom)
2166 19173 : if(option==21)then
2167 : ! There is a change of sign to get the gradient wrt chrgat.
2168 10 : write(msg, '(i5,f15.5,f20.8)' ) iatom,ratsph(typat(iatom)),-intgden(1,1,iatom)
2169 : !write(msg, '(i5,a3,f15.5,f20.8)' ) iatom,atom%symbol,ratsph(typat(iatom)),-intgden(1,1,iatom)
2170 : endif
2171 : !If option=1, print atomic charge
2172 19173 : if(option==1 .and. present(ziontypat))then
2173 10 : write(msg, '(a,f20.8)' ) trim(msg),ziontypat(typat(iatom))-intgden(1,1,iatom)
2174 : endif
2175 44669 : call wrtout(units,msg)
2176 : end do
2177 : endif
2178 :
2179 9802 : if(nspden==2 .or. nspden==4) then
2180 :
2181 3479 : if(option== 1)msg1=' Integrated electronic and magnetization densities in atomic spheres:'
2182 3479 : if(option==11)msg1=ch10//' Integrated potential residual in atomic spheres (scalar + magnetic field):'
2183 3479 : if(option==21)msg1=ch10//' Gradient with respect to target (=torque) (scalar + magnetic field):'
2184 3479 : write(msg, '(3a)' ) trim(msg1),ch10,' ------------------------------------------------------------------------------------------------------------'
2185 3479 : call wrtout(units,msg)
2186 :
2187 3479 : if(option== 1 .and. nspden==2) msg1='. Diff(up-dn)=approximate z local magnetic moment.'
2188 3479 : if(option== 1 .and. nspden==4) msg1='. mag(i)=approximate local magnetic moment.'
2189 3479 : if(option==11 .or. option==21) msg1='.'
2190 3479 : write(msg, '(a,f8.4,a)' ) ' Radius=ratsph(iatom), smearing ratsm=',ratsm,trim(msg1)
2191 3479 : call wrtout(units,msg)
2192 :
2193 3479 : if(option==1)then
2194 2231 : if(nspden==2) msg=' Atom Radius up_density dn_density Total(up+dn) Diff(up-dn)'
2195 2231 : if(nspden==4) msg=' Atom Radius Total density |mag| mag(x) mag(y) mag(z) mag(theta) mag(phi) '
2196 2231 : if(present(ziontypat))msg=trim(msg)//' Atomic charge'
2197 1248 : else if(option==11)then
2198 1199 : if(nspden==2) msg=' Atom Radius Potential B(z) up pot down pot'
2199 1199 : if(nspden==4) msg=' Atom Radius Potential |B| B(x) B(y) B(z) B(theta) B(phi) '
2200 49 : else if(option==21)then
2201 49 : if(nspden==2) msg=' Atom Radius grchrg T(z) up torque down torque'
2202 49 : if(nspden==4) msg=' Atom Radius Torque |T| T(x) T(y) T(z) T(theta) T(phi) '
2203 : endif
2204 3479 : if (cplex==2) then
2205 23 : msg_cplex=msg
2206 : else
2207 3456 : call wrtout(units,msg)
2208 : endif
2209 :
2210 : endif
2211 :
2212 9802 : if(nspden==2)then
2213 2658 : do icplex=1,cplex
2214 1335 : sum_mag=zero
2215 1335 : sum_rho_up=zero
2216 1335 : sum_rho_dn=zero
2217 1335 : sum_rho_tot=zero
2218 1335 : if (cplex==2) then
2219 24 : if (icplex==1) then
2220 12 : write(msg, '(a)') ' Real part of magnetization:'
2221 12 : call wrtout(units,msg)
2222 12 : call wrtout(units,msg_cplex)
2223 12 : elseif (icplex==2) then
2224 12 : write(msg, '(a)') '----------------------------'
2225 12 : call wrtout(units,msg)
2226 12 : write(msg, '(a)') ' Imaginary part of magnetization:'
2227 12 : call wrtout(units,msg)
2228 12 : call wrtout(units,msg_cplex)
2229 : endif
2230 : endif
2231 3839 : do iatom=1,natom
2232 2504 : call atomdata_from_znucl(atom, znucl(typat(iatom)))
2233 2504 : if(option/=21)then
2234 2480 : write(msg,'(i5,a3,f10.5,2f13.6,a,f12.6,a,f12.6)' ) iatom,atom%symbol,ratsph(typat(iatom)),intgden(icplex,1,iatom),intgden(icplex,2,iatom)
2235 : else
2236 24 : write(msg,'(i5,a3,f10.5,2f13.6,a,f12.6,a,f12.6)' ) iatom,atom%symbol,ratsph(typat(iatom)),-intgden(icplex,1,iatom),intgden(icplex,2,iatom)
2237 : endif
2238 2504 : write(msg,'(a,a,f12.6,a,f12.6)')trim(msg),' ',(intgden(icplex,1,iatom)+intgden(icplex,2,iatom)),' ',(intgden(icplex,1,iatom)-intgden(icplex,2,iatom))
2239 2504 : if(option==1 .and. present(ziontypat)) then
2240 24 : write(msg, '(a,f14.6)') trim(msg),ziontypat(typat(iatom))-(intgden(icplex,1,iatom)+intgden(icplex,2,iatom))
2241 : end if
2242 2504 : call wrtout(units,msg)
2243 : ! Compute the sum of the magnetization
2244 2504 : sum_mag=sum_mag+intgden(icplex,1,iatom)-intgden(icplex,2,iatom)
2245 2504 : sum_rho_up=sum_rho_up+intgden(icplex,1,iatom)
2246 2504 : sum_rho_dn=sum_rho_dn+intgden(icplex,2,iatom)
2247 6343 : sum_rho_tot=sum_rho_tot+intgden(icplex,1,iatom)+intgden(icplex,2,iatom)
2248 : end do
2249 1335 : write(msg, '(a)') ' ------------------------------------------------------------------------------------------------------------'
2250 1335 : call wrtout(units,msg)
2251 1335 : write(msg, '(a,2f13.6,a,f12.6,a,f12.6)') ' Sum: ', sum_rho_up,sum_rho_dn,' ',sum_rho_tot,' ',sum_mag
2252 1335 : call wrtout(units,msg)
2253 :
2254 1335 : if(option==1)then
2255 1068 : write(msg, '(a,f14.6)') ' Total magnetization (from the atomic spheres): ', sum_mag
2256 1068 : call wrtout(units,msg)
2257 1068 : if (icplex==1) then
2258 1056 : write(msg, '(a,f14.6)') ' Total magnetization (exact up - dn): ', mag_coll
2259 12 : elseif (icplex==2) then
2260 12 : write(msg, '(a,f14.6)') ' Total magnetization (exact up - dn): ', mag_coll_im
2261 : endif
2262 1068 : call wrtout(units,msg)
2263 : endif
2264 1335 : write(msg, '(a)') ' '
2265 2658 : call wrtout(units,msg)
2266 : enddo
2267 :
2268 8479 : elseif(nspden==4) then
2269 :
2270 4323 : do icplex=1,cplex
2271 2167 : sum_mag_x=zero
2272 2167 : sum_mag_y=zero
2273 2167 : sum_mag_z=zero
2274 2167 : if (cplex==2) then
2275 22 : if (icplex==1) then
2276 11 : write(msg, '(a)') ' Real part of magnetization:'
2277 11 : call wrtout(units,msg)
2278 11 : call wrtout(units,msg_cplex)
2279 11 : elseif (icplex==2) then
2280 11 : write(msg, '(a)') '----------------------------'
2281 11 : call wrtout(units,msg)
2282 11 : write(msg, '(a)') ' Imaginary part of magnetization:'
2283 11 : call wrtout(units,msg)
2284 11 : call wrtout(units,msg_cplex)
2285 : endif
2286 : endif
2287 7661 : do iatom=1,natom
2288 71422 : mag_cart(:)=matmul(Rspin_t,intgden(icplex,2:4,iatom))
2289 5494 : call vcart2ylm(mag_cart, mag_r, mag_theta, mag_phi)
2290 5494 : call atomdata_from_znucl(atom, znucl(typat(iatom)))
2291 5494 : if(option/=21)then
2292 5402 : write(msg, '(i5,a3,f10.5,f16.6,a,6f12.6)' ) iatom,atom%symbol,ratsph(typat(iatom)),intgden(icplex,1,iatom),' ',mag_r,mag_cart(1),mag_cart(2),mag_cart(3),mag_theta,mag_phi
2293 : else
2294 92 : write(msg, '(i5,a3,f10.5,f16.6,a,6f12.6)' ) iatom,atom%symbol,ratsph(typat(iatom)),-intgden(icplex,1,iatom),' ',mag_r,mag_cart(1),mag_cart(2),mag_cart(3),mag_theta,mag_phi
2295 : endif
2296 5494 : if(option==1 .and. present(ziontypat))&
2297 92 : & write(msg, '(a,f14.6)') trim(msg),ziontypat(typat(iatom))-intgden(icplex,1,iatom)
2298 5494 : call wrtout(units,msg)
2299 : ! Compute the sum of the magnetization in x, y and z directions
2300 5494 : sum_mag_x=sum_mag_x+mag_cart(1)
2301 5494 : sum_mag_y=sum_mag_y+mag_cart(2)
2302 13155 : sum_mag_z=sum_mag_z+mag_cart(3)
2303 : enddo
2304 8668 : vec = (/sum_mag_x,sum_mag_y,sum_mag_z /)
2305 2167 : call vcart2ylm(vec, sum_mag_r, sum_mag_theta, sum_mag_phi)
2306 2167 : write(msg, '(a)') ' ------------------------------------------------------------------------------------------------------------'
2307 2167 : call wrtout(units,msg)
2308 :
2309 6490 : if(option==1)then
2310 4724 : if (any(qgbt /= zero)) then
2311 8 : write(msg, '(a,f12.6,f12.6,f12.6)') ' Cell sum of sphere magnetization'
2312 8 : call wrtout(units,msg)
2313 : else
2314 1178 : write(msg, '(a)') ' Total magnetization (spheres) '
2315 1178 : call wrtout(units,msg)
2316 : endif
2317 1186 : write(msg, '(a,3f12.6)') ' (cart.coord.) ', sum_mag_x,sum_mag_y,sum_mag_z
2318 1186 : call wrtout(units,msg)
2319 1186 : write(msg, '(a,f12.6,a,2f12.6)') ' (sph.coord.) ', sum_mag_r," ",sum_mag_theta,sum_mag_phi
2320 1186 : call wrtout(units,msg)
2321 :
2322 4724 : if (any(qgbt /= zero)) then
2323 8 : write(msg, '(a,f10.6,f12.6,f12.6)') ' Integral of periodic magnetization'
2324 8 : call wrtout(units,msg)
2325 : else
2326 1178 : write(msg, '(a,f12.6,f12.6,4f12.6)') ' Total magnetization (exact) '
2327 1178 : call wrtout(units,msg)
2328 : endif
2329 1186 : if (icplex==1) then
2330 1175 : vec = mag_tot_cart
2331 1175 : call vcart2ylm(vec, exact_mag_r, exact_mag_theta, exact_mag_phi)
2332 1175 : write(msg, '(a,3f12.6)') ' (cart.coord.) ', mag_tot_cart(1),mag_tot_cart(2),mag_tot_cart(3)
2333 1175 : call wrtout(units,msg)
2334 1175 : write(msg, '(a,f12.6,a,2f12.6)') ' (sph.coord.) ', exact_mag_r," ",exact_mag_theta,exact_mag_phi
2335 1175 : call wrtout(units,msg)
2336 11 : elseif (icplex==2) then
2337 11 : vec = mag_tot_cart_im
2338 11 : call vcart2ylm(vec, exact_mag_r_im, exact_mag_theta_im, exact_mag_phi_im)
2339 11 : write(msg, '(a,3f12.6)') ' (cart.coord.) ', mag_tot_cart_im(1),mag_tot_cart_im(2),mag_tot_cart_im(3)
2340 11 : call wrtout(units,msg)
2341 11 : write(msg,'(a,f12.6,a,2f12.6)')' (sph.coord.) ', exact_mag_r_im," ", exact_mag_theta_im,exact_mag_phi_im
2342 11 : call wrtout(units,msg)
2343 : endif
2344 : endif
2345 : enddo
2346 : end if
2347 :
2348 : elseif(option==-1) then
2349 :
2350 0 : write(msg, '(2a)') ch10,' ---------------------------------------------------------------------------------------------------------------'
2351 0 : call wrtout(units,msg)
2352 :
2353 0 : if(nspden==1) then
2354 : write(msg, '(4a)' ) &
2355 0 : & ' Fermi level charge density n_f:',ch10,&
2356 0 : & ' ------------------------------------------------------------------------',ch10
2357 : else
2358 : write(msg, '(4a)' ) &
2359 0 : & ' Fermi level charge density n_f and magnetization m_f:',ch10,&
2360 0 : & ' ------------------------------------------------------------------------',ch10
2361 : end if
2362 0 : call wrtout(units,msg)
2363 :
2364 0 : if(cplex==1) then
2365 0 : write(msg, '(a,f13.8)') ' n_f = ',rho_tot
2366 : else
2367 0 : write(msg, '(a,f13.8,a,f13.8)') ' Re[n_f]= ', rho_tot," Im[n_f]= ",rho_tot_im
2368 : end if
2369 0 : call wrtout(units,msg)
2370 0 : if(nspden==2) then
2371 0 : if(cplex==1) then
2372 0 : write(msg, '(a,f13.8)') ' m_f = ', mag_coll
2373 : else
2374 0 : write(msg, '(a,f13.8,a,f13.8)') ' Re[m_f]= ', mag_coll," Im[m_f]= ",mag_coll_im
2375 : end if
2376 0 : call wrtout(units,msg)
2377 0 : elseif (nspden==4) then
2378 0 : write(msg, '(a,f13.8)') ' mx_f = ',mag_tot_cart(1)
2379 0 : call wrtout(units,msg)
2380 0 : write(msg, '(a,f13.8)') ' my_f = ',mag_tot_cart(2)
2381 0 : call wrtout(units,msg)
2382 0 : write(msg, '(a,f13.8)') ' mz_f = ',mag_tot_cart(3)
2383 0 : call wrtout(units,msg)
2384 : end if
2385 :
2386 0 : write(msg, '(3a)') ch10,' ------------------------------------------------------------------------',ch10
2387 0 : call wrtout(units,msg)
2388 :
2389 :
2390 : else if (option==2 .or. option==3 .or. option==4) then
2391 : ! Used in the DFPT case, option=idir+1
2392 :
2393 0 : if(abs(rho_tot)<1.0d-10) then
2394 0 : rho_tot=0
2395 : end if
2396 :
2397 0 : write(msg, '(2a)') ch10,' ---------------------------------------------------------------------------'
2398 0 : call wrtout(units,msg)
2399 :
2400 : ! if(nspden==1) then
2401 : ! write(msg, '(4a)' ) &
2402 : !& ' Integral of the first order density n^(1):',ch10,&
2403 : !& ' ------------------------------------------------------------------------',ch10
2404 : ! else
2405 : ! write(msg, '(4a)' ) &
2406 : !& ' Integrals of the first order density n^(1) and magnetization m^(1):',ch10,&
2407 : !& ' ------------------------------------------------------------------------',ch10
2408 : ! end if
2409 : ! call wrtout(units,msg)
2410 : !
2411 : ! if(cplex==1) then
2412 : ! write(msg, '(a,e16.8)') ' n^(1) = ', rho_tot
2413 : ! else
2414 : ! write(msg, '(a,e16.8,a,e16.8)') ' Re[n^(1)] = ', rho_tot," Im[n^(1)] = ",rho_tot_im
2415 : ! end if
2416 : ! call wrtout(units,msg)
2417 : !
2418 : ! if(nspden==2) then
2419 : !
2420 : ! if(cplex==1) then
2421 : ! write(msg, '(a,e16.8)') ' m^(1) = ', mag_coll
2422 : ! else
2423 : ! write(msg, '(a,e16.8,a,e16.8)') ' Re[m^(1)] = ', mag_coll," Im[m^(1)] = ",mag_coll_im
2424 : ! end if
2425 : ! call wrtout(units,msg)
2426 : !
2427 : ! elseif (nspden==4) then
2428 : ! if(cplex==1) then
2429 : ! write(msg, '(a,e16.8)') ' mx^(1) = ', mag_x
2430 : ! call wrtout(units,msg)
2431 : ! write(msg, '(a,e16.8)') ' my^(1) = ', mag_y
2432 : ! call wrtout(units,msg)
2433 : ! write(msg, '(a,e16.8)') ' mz^(1) = ', mag_z
2434 : ! call wrtout(units,msg)
2435 : ! else
2436 : ! write(msg, '(a,e16.8,a,e16.8)') ' Re[mx^(1)]= ', mag_x, " Im[mx^(1)]= ", mag_x_im
2437 : ! call wrtout(units,msg)
2438 : ! write(msg, '(a,e16.8,a,e16.8)') ' Re[my^(1)]= ', mag_y, " Im[my^(1)]= ", mag_y_im
2439 : ! call wrtout(units,msg)
2440 : ! write(msg, '(a,e16.8,a,e16.8)') ' Re[mz^(1)]= ', mag_z, " Im[mz^(1)]= ", mag_z_im
2441 : ! call wrtout(units,msg)
2442 : ! end if
2443 : ! end if
2444 : !
2445 : ! write(msg, '(3a)') ch10,' ------------------------------------------------------------------------',ch10
2446 : ! call wrtout(units,msg)
2447 :
2448 : end if
2449 :
2450 : end if ! option/=0
2451 :
2452 9802 : end subroutine prtdenmagsph
2453 : !!***
2454 :
2455 : !!****f* m_dens/radsmear
2456 : !! NAME
2457 : !! radsmear
2458 : !!
2459 : !! FUNCTION
2460 : !! As a function of the argument xarg (a positive number), return a function fsm that is zero
2461 : !! beyond some cut-off value xcut, one for xarg smaller than xcut-xsmear,
2462 : !! and interpolates smoothly between one and zero in the region from xcut-xsmear to xcut.
2463 : !! Also returns the derivative of this function, called dfsm.
2464 : !! The function fsm is twice differentiable at xcut (the first derivative is continuous, not the second),
2465 : !! and three times differentiable at xcut-xsmear (the second derivative is continuous, not the third).
2466 : !!
2467 : !!
2468 : !! INPUTS
2469 : !! xarg=argument of the function (should be positive)
2470 : !! xcut=largest value for which the function is non-zero
2471 : !! xsmear=defined the smearing region, between xcut-xsmear and xcut
2472 : !!
2473 : !! OUTPUT
2474 : !! fsm=value of the function
2475 : !! dfsm=derivative of the function with respect to xarg (zero, except in the smearing region).
2476 : !!
2477 : !! SOURCE
2478 :
2479 92223976 : subroutine radsmear(dfsm,fsm,xarg,xcut,xsmear)
2480 :
2481 : !Arguments ------------------------------------
2482 : !scalars
2483 : real(dp), intent(out) :: dfsm,fsm
2484 : real(dp), intent(in) :: xarg, xcut, xsmear
2485 :
2486 : !Local variables ------------------------------
2487 : !scalars
2488 : real(dp) :: xsmearinv,xx
2489 : !******************************************************************
2490 :
2491 92223976 : fsm = zero
2492 92223976 : dfsm=zero
2493 92223976 : if (xarg < xcut - xsmear - tol12) then
2494 90987178 : fsm = one
2495 1236798 : else if (xarg < xcut - tol12) then
2496 1236798 : xsmearinv=one/xsmear
2497 1236798 : xx = (xcut - xarg) * xsmearinv
2498 1236798 : fsm = xx**2*(3+xx*(1+xx*(-6+3*xx)))
2499 1236798 : dfsm = -(xx*(6+xx*(3+xx*(-24+15*xx))))*xsmearinv
2500 : end if
2501 :
2502 92223976 : end subroutine radsmear
2503 : !!***
2504 :
2505 : !!****f* ABINIT/printmagvtk
2506 : !! NAME
2507 : !! printmagvtk
2508 : !!
2509 : !! FUNCTION
2510 : !! Auxiliary routine for printing out magnetization density in VTK format.
2511 : !! Output file name is DEN.vtk
2512 : !!
2513 : !! INPUTS
2514 : !! mpi_enreg = information about adopted parallelization strategy
2515 : !! nspden = number of components of density matrix (possible values re 1,2, or 4)
2516 : !! nspden: 1 -> rho
2517 : !! nspden: 2 -> rho_up,rho_dwn
2518 : !! nspden: 4 -> rho,mx,my,mz
2519 : !! nfft = number of fft points per FFT processor
2520 : !! ngfft = full information about FFT mesh
2521 : !! rhor = density array stored in the memory of current FFT processor
2522 : !! rprimd = array of lattice vectors
2523 : !!
2524 : !! OUTPUT
2525 : !!
2526 : !! NOTES
2527 : !! At the moment this routine is mainly used for development and debugging
2528 : !! of gs and dfpt calculations with non-collinear spins. If needed, can be used
2529 : !! to print final density in vtk format.
2530 : !! IMPORTANT: implementation is thoroughly checked only for npspinor = 1,
2531 : !! for other case might need to change the part gathering
2532 : !! the FFT mesh info
2533 : !!
2534 : !! SOURCE
2535 :
2536 : subroutine printmagvtk(mpi_enreg,cplex,nspden,nfft,ngfft,rhor,rprimd,fname)
2537 :
2538 : !Arguments ------------------------------------
2539 : !scalars
2540 : type(MPI_type),intent(in) :: mpi_enreg
2541 : integer,intent(in) :: nfft,nspden,cplex
2542 : !arrays
2543 : integer,intent(in) :: ngfft(18)
2544 : real(dp),intent(in) :: rhor(cplex*nfft,nspden),rprimd(3,3)
2545 : character(len=*),intent(in) :: fname
2546 :
2547 : !Local variables-------------------------------
2548 : !scalars
2549 : integer :: denvtk,denxyz,denxyz_im,nfields
2550 : integer :: nx,ny,nz,nfft_tot
2551 : integer :: ii,jj,kk,ind,ispden
2552 : integer :: mpi_comm,mpi_head,mpi_rank,ierr
2553 : real(dp) :: rx,ry,rz
2554 : integer :: nproc_fft,ir
2555 : character(len=500) :: msg
2556 : character(len=10) :: outformat
2557 : character(len=fnlen) :: fname_vtk, fname_xyz, fname_xyz_re, fname_xyz_im
2558 : !arrays
2559 : real(dp),allocatable :: rhorfull(:,:)
2560 : ! *************************************************************************
2561 :
2562 : fname_vtk=adjustl(adjustr(fname)//".vtk")
2563 : fname_xyz=adjustl(adjustr(fname)//".xyz")
2564 : fname_xyz_re=adjustl(adjustr(fname)//"_re.xyz")
2565 : fname_xyz_im=adjustl(adjustr(fname)//"_im.xyz")
2566 : !write(std_out,*) ' Writing out .vtk file: ',fname_vtk
2567 : !write(std_out,*) ' Writing out .xyz file: ',fname_xyz
2568 :
2569 : !if 1 or two component density then write out either 1 or 2 scalar density fields
2570 : !if 4, then write one scalar field (density) and one vector field (magnetization density)
2571 : if(nspden/=4)then
2572 : nfields=nspden
2573 : else
2574 : nfields=2
2575 : end if
2576 :
2577 : nfields=nfields*cplex
2578 :
2579 : ! FFT mesh specifications: full grid
2580 : nx=ngfft(1) ! number of points along 1st lattice vector
2581 : ny=ngfft(2) ! number of points along 2nd lattice vector
2582 : nz=ngfft(3) ! number of points along 3rd lattice vector
2583 : nfft_tot=nx*ny*nz ! total number of fft mesh points (can be different from nfft in case of distributed memory of nproc_fft processors)
2584 :
2585 :
2586 : ! Gather information about memory distribution
2587 : mpi_head=0
2588 : mpi_comm = mpi_enreg%comm_fft
2589 : mpi_rank = xmpi_comm_rank(mpi_comm)
2590 : nproc_fft=ngfft(10)
2591 :
2592 : ! Create array to host full FFT mesh
2593 : if(mpi_rank==mpi_head)then
2594 : ABI_MALLOC(rhorfull,(cplex*nfft_tot,nspden))
2595 : end if
2596 :
2597 : ! Fill in the full mesh
2598 : if(nproc_fft==1)then
2599 : rhorfull=rhor
2600 : else
2601 : do ir=1,nspden
2602 : call xmpi_gather(rhor(:,ir),cplex*nfft,rhorfull(:,ir),cplex*nfft,mpi_head,mpi_comm,ierr)
2603 : end do
2604 : end if
2605 :
2606 : if(mpi_rank==mpi_head)then
2607 :
2608 : ! Open the output vtk file
2609 : if (open_file(fname_vtk,msg,newunit=denvtk,status='replace',form='formatted') /=0) then
2610 : ABI_WARNING(msg)
2611 : RETURN
2612 : end if
2613 :
2614 : if(cplex==1) then
2615 : if (open_file(fname_xyz,msg,newunit=denxyz,status='replace',form='formatted') /=0) then
2616 : ABI_WARNING(msg)
2617 : RETURN
2618 : end if
2619 : else if (cplex==2) then
2620 : if (open_file(fname_xyz_re,msg,newunit=denxyz,status='replace',form='formatted') /=0) then
2621 : ABI_WARNING(msg)
2622 : RETURN
2623 : end if
2624 : if (open_file(fname_xyz_im,msg,newunit=denxyz_im,status='replace',form='formatted') /=0) then
2625 : ABI_WARNING(msg)
2626 : RETURN
2627 : end if
2628 : end if
2629 :
2630 : ! Write the header of the output vtk file
2631 : write(denvtk,"(a)") '# vtk DataFile Version 2.0'
2632 : write(denvtk,"(a)") 'Electron density components'
2633 : write(denvtk,"(a)") 'ASCII'
2634 : write(denvtk,"(a)") 'DATASET STRUCTURED_GRID'
2635 : write(denvtk,"(a,3i6)") 'DIMENSIONS ', nx,ny,nz
2636 : write(denvtk,"(a,i18,a)") 'POINTS ',nfft_tot,' double'
2637 :
2638 : if (nspden==1) then
2639 : outformat="(4e16.8)"
2640 : else if (nspden==2) then
2641 : outformat="(5e16.8)"
2642 : else
2643 : outformat="(7e16.8)"
2644 : end if
2645 :
2646 : ! Write out information about grid points
2647 : do kk=0,nz-1
2648 : do jj=0,ny-1
2649 : do ii=0,nx-1
2650 :
2651 : rx=(dble(ii)/nx)*rprimd(1,1)+(dble(jj)/ny)*rprimd(1,2)+(dble(kk)/nz)*rprimd(1,3)
2652 : ry=(dble(ii)/nx)*rprimd(2,1)+(dble(jj)/ny)*rprimd(2,2)+(dble(kk)/nz)*rprimd(2,3)
2653 : rz=(dble(ii)/nx)*rprimd(3,1)+(dble(jj)/ny)*rprimd(3,2)+(dble(kk)/nz)*rprimd(3,3)
2654 : write(denvtk,'(3f16.8)') rx,ry,rz !coordinates of the grid point
2655 : ind=1+ii+nx*(jj+ny*kk)
2656 : if (cplex==1) then
2657 : write(denxyz,outformat) rx,ry,rz,(rhorfull(ind,ispden),ispden=1,nspden)
2658 : else
2659 : write(denxyz,outformat) rx,ry,rz,(rhorfull(2*ind-1,ispden),ispden=1,nspden)
2660 : write(denxyz_im,outformat) rx,ry,rz,(rhorfull(2*ind ,ispden),ispden=1,nspden)
2661 : end if
2662 : end do
2663 : end do
2664 : end do
2665 :
2666 : if(cplex==1) then
2667 : close(denxyz)
2668 : else
2669 : close(denxyz)
2670 : close(denxyz_im)
2671 : end if
2672 :
2673 : ! Write out information about field defined on the FFT mesh
2674 : write(denvtk,"(a,i18)") 'POINT_DATA ',nfft_tot
2675 : write(denvtk,"(a,i6)") 'FIELD Densities ',nfields
2676 :
2677 :
2678 : ! Write out different fields depending on the number of density matrix components
2679 : if(nspden==1)then
2680 :
2681 : !single component, so just write out the density
2682 : if(cplex==1) then
2683 : write(denvtk,"(a,i18,a)") 'rho 1 ',nfft_tot,' double'
2684 : do kk=0,nz-1
2685 : do jj=0,ny-1
2686 : do ii=0,nx-1
2687 : ind=1+ii+nx*(jj+ny*kk)
2688 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2689 : end do
2690 : end do
2691 : end do
2692 : else
2693 : write(denvtk,"(a,i18,a)") 'Re_rho 1 ',nfft_tot,' double'
2694 : do kk=0,nz-1
2695 : do jj=0,ny-1
2696 : do ii=0,nx-1
2697 : ind=2*(1+ii+nx*(jj+ny*kk))-1
2698 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2699 : end do
2700 : end do
2701 : end do
2702 : write(denvtk,"(a,i18,a)") 'Im_rho 1 ',nfft_tot,' double'
2703 : do kk=0,nz-1
2704 : do jj=0,ny-1
2705 : do ii=0,nx-1
2706 : ind=2*(1+ii+nx*(jj+ny*kk))
2707 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2708 : end do
2709 : end do
2710 : end do
2711 : end if
2712 :
2713 : else if(nspden==2)then
2714 :
2715 : !two component, write the density for spin_up and spin_down channels
2716 : if(cplex==1) then
2717 :
2718 : write(denvtk,"(a,i18,a)") 'rho 1 ',nfft_tot,' double'
2719 : do kk=0,nz-1
2720 : do jj=0,ny-1
2721 : do ii=0,nx-1
2722 : ind=1+ii+nx*(jj+ny*kk)
2723 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2724 : end do
2725 : end do
2726 : end do
2727 : write(denvtk,"(a,i18,a)") 'mag 1 ',nfft_tot,' double'
2728 : do kk=0,nz-1
2729 : do jj=0,ny-1
2730 : do ii=0,nx-1
2731 : ind=1+ii+nx*(jj+ny*kk)
2732 : write(denvtk,'(f16.8)') 2*rhorfull(ind,2)-rhorfull(ind,1)
2733 : end do
2734 : end do
2735 : end do
2736 :
2737 : else
2738 :
2739 : write(denvtk,"(a,i18,a)") 'Re_rho 1 ',nfft_tot,' double'
2740 : do kk=0,nz-1
2741 : do jj=0,ny-1
2742 : do ii=0,nx-1
2743 : ind=2*(1+ii+nx*(jj+ny*kk))-1
2744 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2745 : end do
2746 : end do
2747 : end do
2748 : write(denvtk,"(a,i18,a)") 'Im_rho 1 ',nfft_tot,' double'
2749 : do kk=0,nz-1
2750 : do jj=0,ny-1
2751 : do ii=0,nx-1
2752 : ind=2*(1+ii+nx*(jj+ny*kk))
2753 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2754 : end do
2755 : end do
2756 : end do
2757 : write(denvtk,"(a,i18,a)") 'Re_mag 1 ',nfft_tot,' double'
2758 : do kk=0,nz-1
2759 : do jj=0,ny-1
2760 : do ii=0,nx-1
2761 : ind=2*(1+ii+nx*(jj+ny*kk))-1
2762 : write(denvtk,'(f16.8)') 2*rhorfull(ind,2)-rhorfull(ind,1)
2763 : end do
2764 : end do
2765 : end do
2766 : write(denvtk,"(a,i18,a)") 'Im_mag 1 ',nfft_tot,' double'
2767 : do kk=0,nz-1
2768 : do jj=0,ny-1
2769 : do ii=0,nx-1
2770 : ind=2*(1+ii+nx*(jj+ny*kk))
2771 : write(denvtk,'(f16.8)') 2*rhorfull(ind,2)-rhorfull(ind,1)
2772 : end do
2773 : end do
2774 : end do
2775 :
2776 : end if
2777 :
2778 : else !here is the last option: nspden==4
2779 :
2780 : if(cplex==1) then
2781 :
2782 : !four component, write the density (scalar field) and magnetization density (vector field)
2783 : write(denvtk,"(a,i18,a)") 'rho 1 ',nfft_tot,' double'
2784 : do kk=0,nz-1
2785 : do jj=0,ny-1
2786 : do ii=0,nx-1
2787 : ind=1+ii+nx*(jj+ny*kk)
2788 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2789 : end do
2790 : end do
2791 : end do
2792 : write(denvtk,"(a,i18,a)") 'mag 3 ',nfft_tot,' double'
2793 : do kk=0,nz-1
2794 : do jj=0,ny-1
2795 : do ii=0,nx-1
2796 : ind=1+ii+nx*(jj+ny*kk)
2797 : write(denvtk,'(3f16.8)') rhorfull(ind,2),rhorfull(ind,3),rhorfull(ind,4)
2798 : end do
2799 : end do
2800 : end do
2801 :
2802 : else
2803 :
2804 : write(denvtk,"(a,i18,a)") 'Re_rho 1 ',nfft_tot,' double'
2805 : do kk=0,nz-1
2806 : do jj=0,ny-1
2807 : do ii=0,nx-1
2808 : ind=2*(1+ii+nx*(jj+ny*kk))-1
2809 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2810 : end do
2811 : end do
2812 : end do
2813 : write(denvtk,"(a,i18,a)") 'Im_rho 1 ',nfft_tot,' double'
2814 : do kk=0,nz-1
2815 : do jj=0,ny-1
2816 : do ii=0,nx-1
2817 : ind=2*(1+ii+nx*(jj+ny*kk))
2818 : write(denvtk,'(f16.8)') rhorfull(ind,1)
2819 : end do
2820 : end do
2821 : end do
2822 : write(denvtk,"(a,i18,a)") 'Re_mag 3 ',nfft_tot,' double'
2823 : do kk=0,nz-1
2824 : do jj=0,ny-1
2825 : do ii=0,nx-1
2826 : ind=2*(1+ii+nx*(jj+ny*kk))-1
2827 : write(denvtk,'(3f16.8)') rhorfull(ind,2),rhorfull(ind,3),rhorfull(ind,4)
2828 : end do
2829 : end do
2830 : end do
2831 : write(denvtk,"(a,i18,a)") 'Im_mag 3 ',nfft_tot,' double'
2832 : do kk=0,nz-1
2833 : do jj=0,ny-1
2834 : do ii=0,nx-1
2835 : ind=2*(1+ii+nx*(jj+ny*kk))
2836 : write(denvtk,'(3f16.8)') rhorfull(ind,2),rhorfull(ind,3),rhorfull(ind,4)
2837 : end do
2838 : end do
2839 : end do
2840 :
2841 : end if
2842 :
2843 : end if ! nspden options condition
2844 :
2845 : close (denvtk)
2846 :
2847 : !clean up the gathered FFT mesh
2848 : ABI_FREE(rhorfull)
2849 :
2850 : end if
2851 :
2852 : end subroutine printmagvtk
2853 : !!***
2854 :
2855 : !!****f* ABINIT/calmaxdifmag
2856 : !! NAME
2857 : !! calmaxdifmag
2858 : !!
2859 : !! FUNCTION
2860 : !! Compute the maximum absolute value of the magnetization among all atoms,
2861 : !! and the maximum absolute change in magnetization between the current and previous SCF cycles.
2862 : !!
2863 : !! INPUTS
2864 : !! intgden(cplex,nspden,natom) = Integrated magnetic moments at the present SCF cycle.
2865 : !! intgden0(cplex,nspden,natom) = Integrated magnetic moments at the previous SCF cycle.
2866 : !! natom = Number of atoms.
2867 : !! nspden = Number of spin-density components (typically 1, 2, or 4).
2868 : !!
2869 : !! OUTPUT
2870 : !! maxmag = Maximum absolute value of magnetization among all atoms.
2871 : !! difmag = Maximum absolute change in magnetization between present and previous SCF cycle.
2872 : !!
2873 : !! SIDE EFFECTS
2874 : !! None
2875 : !!
2876 : !! NOTES
2877 : !! This routine can handle both real and complex spin densities.
2878 : !!
2879 : !! SOURCE
2880 :
2881 9102 : subroutine calmaxdifmag(cplex,intgden,intgden0,natom,nspden,maxmag,difmag)
2882 :
2883 : !Arguments ---------------------------------------------
2884 : integer,intent(in) :: natom,nspden,cplex
2885 : real(dp),intent(in) :: intgden(cplex,nspden,natom),intgden0(cplex,nspden,natom)
2886 : real(dp),intent(out)::maxmag,difmag
2887 : !Local variables ------------------------------
2888 : integer :: iatom
2889 : real(dp)::mag,mag0
2890 9102 : maxmag=zero;difmag=zero
2891 9102 : if (nspden==2 ) then
2892 19458 : do iatom=1,natom
2893 12992 : mag=intgden(1,1,iatom)-intgden(1,2,iatom)
2894 12992 : mag0=intgden0(1,1,iatom)-intgden0(1,2,iatom)
2895 12992 : maxmag=max(maxmag,abs(mag))
2896 12992 : difmag=max(difmag,abs(mag-mag0))
2897 19458 : if (cplex==2) then
2898 121 : mag=intgden(2,1,iatom)-intgden(2,2,iatom)
2899 121 : mag0=intgden(2,1,iatom)-intgden0(2,2,iatom)
2900 121 : maxmag=max(maxmag,abs(mag))
2901 121 : difmag=max(difmag,abs(mag-mag0))
2902 : endif
2903 : end do
2904 2636 : else if (nspden==4 ) then
2905 8392 : do iatom=1,natom
2906 23024 : mag =sqrt(sum(intgden(1,2:4,iatom)**2))
2907 23024 : mag0=sqrt(sum(intgden0(1,2:4,iatom)**2))
2908 5756 : maxmag=max(maxmag,abs(mag))
2909 5756 : difmag=max(difmag,abs(mag-mag0))
2910 8392 : if (cplex==2) then
2911 1240 : mag =sqrt(sum(intgden(2,2:4,iatom)**2))
2912 1240 : mag0=sqrt(sum(intgden0(2,2:4,iatom)**2))
2913 310 : maxmag=max(maxmag,abs(mag))
2914 310 : difmag=max(difmag,abs(mag-mag0))
2915 : endif
2916 : end do
2917 : endif
2918 9102 : if (maxmag < tol8) then
2919 2017 : maxmag=0
2920 2017 : if (difmag < tol8) difmag=0
2921 : endif
2922 9102 : end subroutine calmaxdifmag
2923 : !!***
2924 :
2925 : !!****f* m_dens/fatsph_recip
2926 : !! NAME
2927 : !! fatsph_recip
2928 : !!
2929 : !! FUNCTION
2930 : !! Compute the atomic spheres functions in reciprocal space as a product of
2931 : !! a Bessel function times a Gaussian smearing for the boundary. The functions
2932 : !! are subsequently Fourier transformed to real space.
2933 : !!
2934 : !! INPUTS
2935 : !! mpi_enreg=information about MPI parallelization
2936 : !! natom=number of atoms in cell.
2937 : !! nfft=(effective) number of FFT grid points (for this processor)
2938 : !! ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft
2939 : !! ntypat=number of atom types
2940 : !! ratsm=smearing width for ratsph
2941 : !! ratsph(ntypat)=radius of spheres around atoms
2942 : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
2943 : !! typat(natom)=type of each atom
2944 : !! xred(3,natom)=reduced dimensionless atomic coordinates
2945 : !!
2946 : !! OUTPUT
2947 : !! fatsph(nfft,natom)= functions defining the atomic spheres of integration in real space
2948 : !! fatsphi3(n1,n2,n3,natom)= Same functions with triple indexing
2949 : !!
2950 : !! SOURCE
2951 :
2952 0 : subroutine fatsph_recip(fatsph,fatsph3i,gmet,mpi_enreg,natom,nfft,ngfft,ntypat,&
2953 0 : & ratsm,ratsph,typat,ucvol,xred)
2954 :
2955 : !Arguments ------------------------------------
2956 : !scalars
2957 : integer,intent(in) :: natom,nfft,ntypat
2958 : real(dp),intent(in) :: ratsm,ucvol
2959 : type(MPI_type),intent(in) :: mpi_enreg
2960 : !arrays
2961 : integer,intent(in) :: ngfft(18),typat(natom)
2962 : real(dp),intent(in) :: gmet(3,3),ratsph(ntypat)
2963 : real(dp),intent(in) :: xred(3,natom)
2964 : real(dp),intent(out):: fatsph(nfft,natom)
2965 : real(dp),intent(out):: fatsph3i(ngfft(1),ngfft(2),ngfft(3),natom)
2966 :
2967 : !Local variables ------------------------------
2968 : !scalars
2969 : integer :: iatom
2970 : integer :: i1,i2,i3,id1,id2,id3,ig1,ig2,ig3,ii,ii1,n1,n2,n3,n4,n5,n6
2971 : real(dp) :: arg1,arg2,fac1,fac2,fac3,gq1,gq2,gq3,gcube
2972 : real(dp) :: gsquar,gmag,gmagrad,rad,sfr,sfi,widthsq
2973 : !arrays
2974 0 : integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:)
2975 0 : integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:)
2976 : real(dp) :: gq(3)
2977 0 : real(dp) :: work1(2,nfft),work2(nfft,1),work3(ngfft(1),ngfft(2),ngfft(3),1)
2978 :
2979 : !******************************************************************
2980 :
2981 : !Geometric parameters
2982 0 : n1=ngfft(1);n2=ngfft(2);n3=ngfft(3)
2983 0 : n4=ngfft(4);n5=ngfft(5);n6=ngfft(6)
2984 0 : id1=n1/2+2
2985 0 : id2=n2/2+2
2986 0 : id3=n3/2+2
2987 0 : widthsq=ratsm**2
2988 :
2989 : !Get the distrib associated with this fft_grid
2990 0 : call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
2991 :
2992 0 : do iatom=1, natom
2993 :
2994 0 : ii=0
2995 0 : work1(:,:)=zero
2996 : !G=0 term
2997 0 : rad=ratsph(typat(iatom))
2998 0 : work1(1,1)=four_pi*rad**3/(three*ucvol)
2999 0 : do i3=1,n3
3000 0 : ig3=i3-(i3/id3)*n3-1
3001 0 : gq3=dble(ig3)
3002 0 : gq(3)=gq3
3003 0 : do i2=1,n2
3004 0 : if (fftn2_distrib(i2)==mpi_enreg%me_fft) then
3005 0 : ig2=i2-(i2/id2)*n2-1
3006 0 : gq2=dble(ig2)
3007 0 : gq(2)=gq2
3008 :
3009 : ! Note the lower limit of the next loop
3010 0 : ii1=1
3011 0 : if(i3==1 .and. i2==1 .and. ig2==0 .and. ig3==0)then
3012 0 : ii1=2
3013 0 : ii=ii+1
3014 : end if
3015 0 : do i1=ii1,n1
3016 0 : ig1=i1-(i1/id1)*n1-1
3017 0 : gq1=dble(ig1)
3018 0 : gq(1)=gq1
3019 0 : ii=ii+1
3020 :
3021 0 : gsquar=gsq_vl3(gq1,gq2,gq3)
3022 0 : gmag=sqrt(gsquar)
3023 0 : gcube=gmag*gsquar
3024 0 : gmagrad=two_pi*gmag*rad
3025 0 : arg1=-gsquar*pi**2*widthsq
3026 0 : arg2=two_pi*dot_product(xred(:,iatom),gq)
3027 :
3028 0 : fac1=two/(two_pi**2*gcube*ucvol)
3029 0 : fac2=sin(gmagrad)-gmagrad*cos(gmagrad)
3030 0 : fac3=exp(arg1)
3031 0 : sfr=cos(arg2)
3032 0 : sfi=-sin(arg2)
3033 :
3034 0 : work1(1,ii)=fac1*fac2*fac3*sfr
3035 0 : work1(2,ii)=fac1*fac2*fac3*sfi
3036 :
3037 : end do
3038 : end if
3039 : end do
3040 : end do
3041 :
3042 : ! Transform to real space
3043 0 : call fourdp(1,work1,work2,1,mpi_enreg,nfft,1,ngfft,0)
3044 0 : fatsph(:,iatom)=work2(:,1)
3045 :
3046 0 : call fftpac(1,mpi_enreg,1,n1,n2,n3,n1,n2,n3,ngfft,work2,work3,2)
3047 0 : fatsph3i(:,:,:,iatom)=work3(:,:,:,1)
3048 :
3049 : end do !iatom
3050 :
3051 : contains
3052 :
3053 0 : function gsq_vl3(g1,g2,g3)
3054 :
3055 : real(dp) :: gsq_vl3
3056 : real(dp),intent(in) :: g1,g2,g3 ! Note that they are real, unlike in other similar function definitions
3057 : !Define G^2 based on G space metric gmet.
3058 : gsq_vl3=g1*g1*gmet(1,1)+g2*g2*gmet(2,2)+&
3059 : & g3*g3*gmet(3,3)+2.0_dp*g1*g2*gmet(1,2)+&
3060 0 : & 2.0_dp*g2*g3*gmet(2,3)+2.0_dp*g3*g1*gmet(3,1)
3061 0 : end function gsq_vl3
3062 :
3063 : end subroutine fatsph_recip
3064 : !!***
3065 :
3066 : !!****f* m_dens/magmom_to_d2
3067 : !! NAME
3068 : !! magmom_to_d2
3069 : !!
3070 : !! FUNCTION
3071 : !! Incorporates the magnetic moments in the ddb files as second
3072 : !! order energy derivatives with respect to (ipert,idir) and a
3073 : !! Zeeman field. Both total, i.e., response to a uniform Zeeman
3074 : !! field (ipert=natom+5) and local (ipert=natom+11+1:2*natom+11)
3075 : !! magnetic moments are considered. The Zeeman field directions
3076 : !! are passed in Cartesian format.
3077 : !! It also incorporates the second-order energy derivatives involving
3078 : !! a scalar-potential perturbation from the charge-induced by
3079 : !! another (ipert,idir). TODO: Check the consistency of signs in this case.
3080 : !!
3081 : !! INPUTS
3082 : !! blkflg(3,mpert,3,mpert)=flags for each element of the 2DTE (=1 if computed)
3083 : !! idir=direction of the perturbation
3084 : !! intgden(cplex,nspden, natom)=integrated rhor or potential residual, for each atom in a sphere of radius ratsph.
3085 : !! Representation differs according to nspden :
3086 : !! if nspden=1, total density
3087 : !! if nspden=2, spin up, then spin down
3088 : !! if nspden=4, total density, then mag_x, mag_y, mag_z
3089 : !! ipert=type of perturbation
3090 : !! mpert=maximum number of perturbations
3091 : !! natom=number of atoms in cell.
3092 : !! nspden=number of spin-density components
3093 : !! rhomag(2,nspden)=integral of charge or magnetization over the whole cell (also taking into account a possible imaginary part for DFPT).
3094 : !!
3095 : !! OUTPUT
3096 : !! d2lo(2,3,mpert,3,mpert)= Local contributions to the second-order energy functional.
3097 : !!
3098 : !! SOURCE
3099 :
3100 12 : subroutine magmom_to_d2(blkflg,cplex,d2lo,idir,intgden,ipert,mpert,natom,nspden,rhomag)
3101 :
3102 : !Arguments ---------------------------------------------
3103 : !scalars
3104 : integer,intent(in) :: cplex,idir,ipert,mpert,natom,nspden
3105 : !arrays
3106 : integer,intent(inout) :: blkflg(3,mpert,3,mpert)
3107 : real(dp),intent(in) :: intgden(cplex,nspden,natom)
3108 : real(dp),intent(in) :: rhomag(2,nspden)
3109 : real(dp),intent(inout) :: d2lo(2,3,mpert,3,mpert)
3110 : !Local variables ------------------------------
3111 : !scalars
3112 : integer :: iatom
3113 :
3114 : ! *************************************************************************
3115 :
3116 : ! We store in DDB the second-order energy derivatives, hence the negative
3117 : ! sign applied to the induced magnetic moments.
3118 :
3119 : ! Incorporate total charge and magnetic moments
3120 12 : if (nspden==2) then
3121 0 : blkflg(1,natom+6,idir,ipert)= 1
3122 0 : d2lo(1,1,natom+6,idir,ipert)= -rhomag(1,1)
3123 0 : if (cplex==2) d2lo(2,1,natom+6,idir,ipert)= rhomag(2,1)
3124 0 : blkflg(3,natom+5,idir,ipert)= 1
3125 0 : d2lo(1,3,natom+5,idir,ipert)= -half*rhomag(1,2)
3126 0 : if (cplex==2) d2lo(2,3,natom+5,idir,ipert)= -half*rhomag(2,2)
3127 12 : else if (nspden==4) then
3128 12 : blkflg(1,natom+6,idir,ipert)=1
3129 12 : d2lo(1,1,natom+6,idir,ipert)= -rhomag(1,1)
3130 12 : if (cplex==2) d2lo(2,1,natom+6,idir,ipert)= rhomag(2,1)
3131 48 : blkflg(1:3,natom+5,idir,ipert)=1
3132 48 : d2lo(1,1:3,natom+5,idir,ipert)= -half*rhomag(1,2:4)
3133 36 : if (cplex==2) d2lo(2,1:3,natom+5,idir,ipert)= -half*rhomag(2,2:4)
3134 : end if
3135 :
3136 : ! Incorporate local magnetic moments
3137 12 : if (nspden==2) then
3138 0 : do iatom= 1, natom
3139 0 : blkflg(3,natom+11+iatom,idir,ipert)= 1
3140 0 : d2lo(1,3,natom+11+iatom,idir,ipert)= -half*intgden(1,2,iatom)
3141 0 : if (cplex==2) d2lo(2,3,natom+11+iatom,idir,ipert)= -half*intgden(2,2,iatom)
3142 : end do
3143 12 : else if (nspden==4) then
3144 84 : do iatom= 1, natom
3145 288 : blkflg(1:3,natom+11+iatom,idir,ipert)= 1
3146 288 : d2lo(1,1:3,natom+11+iatom,idir,ipert)= -half*intgden(1,2:4,iatom)
3147 228 : if (cplex==2) d2lo(2,1:3,natom+11+iatom,idir,ipert)= -half*intgden(2,2:4,iatom)
3148 : end do
3149 : end if
3150 :
3151 12 : end subroutine magmom_to_d2
3152 : !!***
3153 :
3154 0 : end module m_dens
3155 : !!***
|