TABLE OF CONTENTS
- ABINIT/m_dens
- ABINIT/printmagvtk
- m_dens/add_atomic_fcts
- m_dens/calcdenmagsph
- m_dens/constrained_dft_free
- m_dens/constrained_dft_ini
- m_dens/constrained_dft_t
- m_dens/constrained_residual
- m_dens/dens_hirsh
- m_dens/mag_penalty
- m_dens/mag_penalty_e
- m_dens/prtdenmagsph
- m_dens/radsmear
ABINIT/m_dens [ Modules ]
NAME
m_dens
FUNCTION
Module containing the definition of the constrained_dft_t data type and methods used to handle it, and also includes the computation of integrated atomic charge and magnetization, as well as Hirshfeld charges.
COPYRIGHT
Copyright (C) 1998-2024 ABINIT group (MT,ILuk,MVer,EB,SPr) This file is distributed under the terms of the GNU General Public License, see ~abinit/COPYING or http://www.gnu.org/copyleft/gpl.txt .
SOURCE
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 33 use m_time, only : timab 34 use m_numeric_tools, only : wrap2_zero_one 35 use m_io_tools, only : open_file 36 use m_geometry, only : dist2, xcart2xred, metric 37 use m_mpinfo, only : ptabs_fourdp 38 39 implicit none 40 41 private 42 43 public :: dens_hirsh ! Compute the Hirshfeld charges 44 public :: add_atomic_fcts ! Add atomic functions to real space function 45 public :: constrained_dft_ini ! Initialize the constrained_dft datastructure 46 public :: constrained_dft_free ! Free the constrained_dft datastructure 47 public :: constrained_residual ! Recompute the potential residual, to account for constraints 48 public :: mag_penalty ! Compute the potential corresponding to constrained magnetic moments (using add_atomic_fcts) with the penalty function. 49 public :: mag_penalty_e ! Compute the energy corresponding to constrained magnetic moments. 50 public :: calcdenmagsph ! Compute integral of total density and magnetization inside spheres around atoms. 51 public :: prtdenmagsph ! Print integral of total density and magnetization inside spheres around atoms.
ABINIT/printmagvtk [ Functions ]
NAME
printmagvtk
FUNCTION
Auxiliary routine for printing out magnetization density in VTK format. Output file name is DEN.vtk
INPUTS
mpi_enreg = information about adopted parallelization strategy nspden = number of components of density matrix (possible values re 1,2, or 4) nspden: 1 -> rho nspden: 2 -> rho_up,rho_dwn nspden: 4 -> rho,mx,my,mz nfft = number of fft points per FFT processor ngfft = full information about FFT mesh rhor = density array stored in the memory of current FFT processor rprimd = array of lattice vectors
OUTPUT
SIDE EFFECTS
NOTES
At the moment this routine is mainly used for development and debugging of gs and dfpt calculations with non-collinear spins. If needed, can be used to print final density in vtk format. IMPORTANT: implementation is thoroughly checked only for npspinor = 1, for other case might need to change the part gathering the FFT mesh info
SOURCE
2317 subroutine printmagvtk(mpi_enreg,cplex,nspden,nfft,ngfft,rhor,rprimd,fname) 2318 2319 !Arguments ------------------------------------ 2320 !scalars 2321 type(MPI_type),intent(in) :: mpi_enreg 2322 integer,intent(in) :: nfft,nspden,cplex 2323 !arrays 2324 integer,intent(in) :: ngfft(18) 2325 real(dp),intent(in) :: rhor(cplex*nfft,nspden),rprimd(3,3) 2326 character(len=*),intent(in) :: fname 2327 2328 !Local variables------------------------------- 2329 !scalars 2330 integer :: denvtk,denxyz,denxyz_im,nfields 2331 integer :: nx,ny,nz,nfft_tot 2332 integer :: ii,jj,kk,ind,ispden 2333 integer :: mpi_comm,mpi_head,mpi_rank,ierr 2334 real(dp) :: rx,ry,rz 2335 integer :: nproc_fft,ir 2336 character(len=500) :: msg 2337 character(len=10) :: outformat 2338 character(len=50) :: fname_vtk 2339 character(len=50) :: fname_xyz 2340 character(len=50) :: fname_xyz_re 2341 character(len=50) :: fname_xyz_im 2342 !arrays 2343 real(dp),allocatable :: rhorfull(:,:) 2344 2345 2346 ! ************************************************************************* 2347 2348 DBG_ENTER("COLL") 2349 2350 ! if (option/=1 .and. option/=2 ) then 2351 ! write(msg,'(3a,i0)')& 2352 !& 'The argument option should be 1 or 2,',ch10,& 2353 !& 'however, option=',option 2354 ! ABI_BUG(msg) 2355 ! end if 2356 ! 2357 ! if (sizein<1) then 2358 ! write(msg,'(3a,i0)')& 2359 !& 'The argument sizein should be a positive number,',ch10,& 2360 !& 'however, sizein=',sizein 2361 ! ABI_ERROR(msg) 2362 ! end if 2363 2364 DBG_EXIT("COLL") 2365 2366 fname_vtk=adjustl(adjustr(fname)//".vtk") 2367 fname_xyz=adjustl(adjustr(fname)//".xyz") 2368 fname_xyz_re=adjustl(adjustr(fname)//"_re.xyz") 2369 fname_xyz_im=adjustl(adjustr(fname)//"_im.xyz") 2370 !write(std_out,*) ' Writing out .vtk file: ',fname_vtk 2371 !write(std_out,*) ' Writing out .xyz file: ',fname_xyz 2372 2373 !if 1 or two component density then write out either 1 or 2 scalar density fields 2374 !if 4, then write one scalar field (density) and one vector field (magnetization density) 2375 if(nspden/=4)then 2376 nfields=nspden 2377 else 2378 nfields=2 2379 end if 2380 2381 nfields=nfields*cplex 2382 2383 ! FFT mesh specifications: full grid 2384 nx=ngfft(1) ! number of points along 1st lattice vector 2385 ny=ngfft(2) ! number of points along 2nd lattice vector 2386 nz=ngfft(3) ! number of points along 3rd lattice vector 2387 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) 2388 2389 2390 ! Gather information about memory distribution 2391 mpi_head=0 2392 mpi_comm = mpi_enreg%comm_fft 2393 mpi_rank = xmpi_comm_rank(mpi_comm) 2394 nproc_fft=ngfft(10) 2395 2396 ! Create array to host full FFT mesh 2397 if(mpi_rank==mpi_head)then 2398 ABI_MALLOC(rhorfull,(cplex*nfft_tot,nspden)) 2399 end if 2400 2401 ! Fill in the full mesh 2402 if(nproc_fft==1)then 2403 rhorfull=rhor 2404 else 2405 do ir=1,nspden 2406 call xmpi_gather(rhor(:,ir),cplex*nfft,rhorfull(:,ir),cplex*nfft,mpi_head,mpi_comm,ierr) 2407 end do 2408 end if 2409 2410 if(mpi_rank==mpi_head)then 2411 2412 ! Open the output vtk file 2413 if (open_file(fname_vtk,msg,newunit=denvtk,status='replace',form='formatted') /=0) then 2414 ABI_WARNING(msg) 2415 RETURN 2416 end if 2417 2418 if(cplex==1) then 2419 if (open_file(fname_xyz,msg,newunit=denxyz,status='replace',form='formatted') /=0) then 2420 ABI_WARNING(msg) 2421 RETURN 2422 end if 2423 else if (cplex==2) then 2424 if (open_file(fname_xyz_re,msg,newunit=denxyz,status='replace',form='formatted') /=0) then 2425 ABI_WARNING(msg) 2426 RETURN 2427 end if 2428 if (open_file(fname_xyz_im,msg,newunit=denxyz_im,status='replace',form='formatted') /=0) then 2429 ABI_WARNING(msg) 2430 RETURN 2431 end if 2432 end if 2433 2434 ! Write the header of the output vtk file 2435 write(denvtk,"(a)") '# vtk DataFile Version 2.0' 2436 write(denvtk,"(a)") 'Electron density components' 2437 write(denvtk,"(a)") 'ASCII' 2438 write(denvtk,"(a)") 'DATASET STRUCTURED_GRID' 2439 write(denvtk,"(a,3i6)") 'DIMENSIONS ', nx,ny,nz 2440 write(denvtk,"(a,i18,a)") 'POINTS ',nfft_tot,' double' 2441 2442 if (nspden==1) then 2443 outformat="(4e16.8)" 2444 else if (nspden==2) then 2445 outformat="(5e16.8)" 2446 else 2447 outformat="(7e16.8)" 2448 end if 2449 2450 ! Write out information about grid points 2451 do kk=0,nz-1 2452 do jj=0,ny-1 2453 do ii=0,nx-1 2454 2455 rx=(dble(ii)/nx)*rprimd(1,1)+(dble(jj)/ny)*rprimd(1,2)+(dble(kk)/nz)*rprimd(1,3) 2456 ry=(dble(ii)/nx)*rprimd(2,1)+(dble(jj)/ny)*rprimd(2,2)+(dble(kk)/nz)*rprimd(2,3) 2457 rz=(dble(ii)/nx)*rprimd(3,1)+(dble(jj)/ny)*rprimd(3,2)+(dble(kk)/nz)*rprimd(3,3) 2458 write(denvtk,'(3f16.8)') rx,ry,rz !coordinates of the grid point 2459 ind=1+ii+nx*(jj+ny*kk) 2460 if (cplex==1) then 2461 write(denxyz,outformat) rx,ry,rz,(rhorfull(ind,ispden),ispden=1,nspden) 2462 else 2463 write(denxyz,outformat) rx,ry,rz,(rhorfull(2*ind-1,ispden),ispden=1,nspden) 2464 write(denxyz_im,outformat) rx,ry,rz,(rhorfull(2*ind ,ispden),ispden=1,nspden) 2465 end if 2466 end do 2467 end do 2468 end do 2469 2470 if(cplex==1) then 2471 close(denxyz) 2472 else 2473 close(denxyz) 2474 close(denxyz_im) 2475 end if 2476 2477 ! Write out information about field defined on the FFT mesh 2478 write(denvtk,"(a,i18)") 'POINT_DATA ',nfft_tot 2479 write(denvtk,"(a,i6)") 'FIELD Densities ',nfields 2480 2481 2482 ! Write out different fields depending on the number of density matrix components 2483 if(nspden==1)then 2484 2485 !single component, so just write out the density 2486 if(cplex==1) then 2487 write(denvtk,"(a,i18,a)") 'rho 1 ',nfft_tot,' double' 2488 do kk=0,nz-1 2489 do jj=0,ny-1 2490 do ii=0,nx-1 2491 ind=1+ii+nx*(jj+ny*kk) 2492 write(denvtk,'(f16.8)') rhorfull(ind,1) 2493 end do 2494 end do 2495 end do 2496 else 2497 write(denvtk,"(a,i18,a)") 'Re_rho 1 ',nfft_tot,' double' 2498 do kk=0,nz-1 2499 do jj=0,ny-1 2500 do ii=0,nx-1 2501 ind=2*(1+ii+nx*(jj+ny*kk))-1 2502 write(denvtk,'(f16.8)') rhorfull(ind,1) 2503 end do 2504 end do 2505 end do 2506 write(denvtk,"(a,i18,a)") 'Im_rho 1 ',nfft_tot,' double' 2507 do kk=0,nz-1 2508 do jj=0,ny-1 2509 do ii=0,nx-1 2510 ind=2*(1+ii+nx*(jj+ny*kk)) 2511 write(denvtk,'(f16.8)') rhorfull(ind,1) 2512 end do 2513 end do 2514 end do 2515 end if 2516 2517 else if(nspden==2)then 2518 2519 !two component, write the density for spin_up and spin_down channels 2520 if(cplex==1) then 2521 2522 write(denvtk,"(a,i18,a)") 'rho 1 ',nfft_tot,' double' 2523 do kk=0,nz-1 2524 do jj=0,ny-1 2525 do ii=0,nx-1 2526 ind=1+ii+nx*(jj+ny*kk) 2527 write(denvtk,'(f16.8)') rhorfull(ind,1) 2528 end do 2529 end do 2530 end do 2531 write(denvtk,"(a,i18,a)") 'mag 1 ',nfft_tot,' double' 2532 do kk=0,nz-1 2533 do jj=0,ny-1 2534 do ii=0,nx-1 2535 ind=1+ii+nx*(jj+ny*kk) 2536 write(denvtk,'(f16.8)') 2*rhorfull(ind,2)-rhorfull(ind,1) 2537 end do 2538 end do 2539 end do 2540 2541 else 2542 2543 write(denvtk,"(a,i18,a)") 'Re_rho 1 ',nfft_tot,' double' 2544 do kk=0,nz-1 2545 do jj=0,ny-1 2546 do ii=0,nx-1 2547 ind=2*(1+ii+nx*(jj+ny*kk))-1 2548 write(denvtk,'(f16.8)') rhorfull(ind,1) 2549 end do 2550 end do 2551 end do 2552 write(denvtk,"(a,i18,a)") 'Im_rho 1 ',nfft_tot,' double' 2553 do kk=0,nz-1 2554 do jj=0,ny-1 2555 do ii=0,nx-1 2556 ind=2*(1+ii+nx*(jj+ny*kk)) 2557 write(denvtk,'(f16.8)') rhorfull(ind,1) 2558 end do 2559 end do 2560 end do 2561 write(denvtk,"(a,i18,a)") 'Re_mag 1 ',nfft_tot,' double' 2562 do kk=0,nz-1 2563 do jj=0,ny-1 2564 do ii=0,nx-1 2565 ind=2*(1+ii+nx*(jj+ny*kk))-1 2566 write(denvtk,'(f16.8)') 2*rhorfull(ind,2)-rhorfull(ind,1) 2567 end do 2568 end do 2569 end do 2570 write(denvtk,"(a,i18,a)") 'Im_mag 1 ',nfft_tot,' double' 2571 do kk=0,nz-1 2572 do jj=0,ny-1 2573 do ii=0,nx-1 2574 ind=2*(1+ii+nx*(jj+ny*kk)) 2575 write(denvtk,'(f16.8)') 2*rhorfull(ind,2)-rhorfull(ind,1) 2576 end do 2577 end do 2578 end do 2579 2580 end if 2581 2582 else !here is the last option: nspden==4 2583 2584 if(cplex==1) then 2585 2586 !four component, write the density (scalar field) and magnetization density (vector field) 2587 write(denvtk,"(a,i18,a)") 'rho 1 ',nfft_tot,' double' 2588 do kk=0,nz-1 2589 do jj=0,ny-1 2590 do ii=0,nx-1 2591 ind=1+ii+nx*(jj+ny*kk) 2592 write(denvtk,'(f16.8)') rhorfull(ind,1) 2593 end do 2594 end do 2595 end do 2596 write(denvtk,"(a,i18,a)") 'mag 3 ',nfft_tot,' double' 2597 do kk=0,nz-1 2598 do jj=0,ny-1 2599 do ii=0,nx-1 2600 ind=1+ii+nx*(jj+ny*kk) 2601 write(denvtk,'(3f16.8)') rhorfull(ind,2),rhorfull(ind,3),rhorfull(ind,4) 2602 end do 2603 end do 2604 end do 2605 2606 else 2607 2608 write(denvtk,"(a,i18,a)") 'Re_rho 1 ',nfft_tot,' double' 2609 do kk=0,nz-1 2610 do jj=0,ny-1 2611 do ii=0,nx-1 2612 ind=2*(1+ii+nx*(jj+ny*kk))-1 2613 write(denvtk,'(f16.8)') rhorfull(ind,1) 2614 end do 2615 end do 2616 end do 2617 write(denvtk,"(a,i18,a)") 'Im_rho 1 ',nfft_tot,' double' 2618 do kk=0,nz-1 2619 do jj=0,ny-1 2620 do ii=0,nx-1 2621 ind=2*(1+ii+nx*(jj+ny*kk)) 2622 write(denvtk,'(f16.8)') rhorfull(ind,1) 2623 end do 2624 end do 2625 end do 2626 write(denvtk,"(a,i18,a)") 'Re_mag 3 ',nfft_tot,' double' 2627 do kk=0,nz-1 2628 do jj=0,ny-1 2629 do ii=0,nx-1 2630 ind=2*(1+ii+nx*(jj+ny*kk))-1 2631 write(denvtk,'(3f16.8)') rhorfull(ind,2),rhorfull(ind,3),rhorfull(ind,4) 2632 end do 2633 end do 2634 end do 2635 write(denvtk,"(a,i18,a)") 'Im_mag 3 ',nfft_tot,' double' 2636 do kk=0,nz-1 2637 do jj=0,ny-1 2638 do ii=0,nx-1 2639 ind=2*(1+ii+nx*(jj+ny*kk)) 2640 write(denvtk,'(3f16.8)') rhorfull(ind,2),rhorfull(ind,3),rhorfull(ind,4) 2641 end do 2642 end do 2643 end do 2644 2645 end if 2646 2647 end if ! nspden options condition 2648 2649 close (denvtk) 2650 2651 !clean up the gathered FFT mesh 2652 ABI_FREE(rhorfull) 2653 2654 end if 2655 2656 end subroutine printmagvtk
m_dens/add_atomic_fcts [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
add_atomic_fcts
FUNCTION
This routine is called to assemble the atomic spherical functions, and, if option/=0, to add it to some input function (usually an input potential residual). The contributions from each atomic sphere are governed by parameters coeff_constr_dft, input to the present routine.
INPUTS
natom=number of atoms nspden = number of spin densities (1 2 or 4) 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 rprimd=lattice vectors (dimensionful) mpi_enreg=mpi structure with communicator info nfft=number of points in standard fft grid ngfft=FFT grid dimensions ntypat=number of types of atoms ratsph(ntypat)=radii for muffin tin spheres of each atom typat(natom)=types of atoms xred(3,natom)=reduced atomic positions
SIDE EFFECTS
nv_constr_dft_r=the constrained potential or density in real space
SOURCE
454 subroutine add_atomic_fcts(natom,nspden,rprimd,mpi_enreg,nfft,ngfft,ntypat,option,ratsph, & 455 ratsm, typat,coeffs_constr_dft,nv_constr_dft_r,xred) 456 457 !Arguments ------------------------------------ 458 !scalars 459 integer,intent(in) :: natom,nfft,nspden,ntypat,option 460 type(MPI_type),intent(in) :: mpi_enreg 461 !arrays 462 integer,intent(in) :: typat(natom) 463 integer,intent(in) :: ngfft(18) 464 real(dp),intent(in) :: coeffs_constr_dft(nspden,natom) 465 real(dp),intent(inout) :: nv_constr_dft_r(nfft,nspden) 466 real(dp),intent(in) :: ratsph(ntypat) 467 real(dp),intent(in) :: ratsm ! Ben change 468 real(dp),intent(in) :: rprimd(3,3) 469 real(dp),intent(in) :: xred(3,natom) 470 471 !Local variables------------------------------- 472 !scalars 473 integer,parameter :: ishift=5 474 integer :: iatom, ierr 475 integer :: n1a, n1b, n3a, n3b, n2a, n2b 476 integer :: n1, n2, n3 477 integer :: ifft_local 478 integer :: i1,i2,i3,ix,iy,iz,izloc 479 real(dp) :: dfsm,dify,difz,fsm,r2atsph,rr1,rr2,rr3,ratsm2,rx23,ry23,rz23 !Ben change: remove ratsm 480 real(dp) :: r2,r2_11,r2_123,r2_23 481 real(dp) :: ucvol 482 real(dp),parameter :: delta=0.99_dp 483 !arrays 484 real(dp), allocatable :: difx(:) 485 real(dp) :: gprimd(3,3),rmet(3,3),gmet(3,3) 486 real(dp) :: tsec(2) 487 integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:) 488 integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:) 489 490 ! *********************************************************************************************** 491 492 !We need the metric because it is needed to compute the "box" around each atom 493 call metric(gmet,gprimd,-1,rmet,rprimd,ucvol) 494 495 n1 = ngfft(1) 496 n2 = ngfft(2) 497 n3 = ngfft(3) 498 499 !Ben change: comment out ratsm line 500 !ratsm = 0.05_dp ! default value for the smearing region radius - may become input variable later 501 502 if(option==0)then 503 nv_constr_dft_r = zero 504 endif 505 506 !Get the distrib associated with this fft_grid 507 call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local) 508 509 !Loop over atoms 510 !------------------------------------------- 511 do iatom=1,natom 512 513 if(sum(coeffs_constr_dft(1:nspden,iatom)**2)<tol12)then 514 cycle 515 endif 516 517 ! Define a "box" around the atom 518 r2atsph=1.0000001_dp*ratsph(typat(iatom))**2 519 rr1=sqrt(r2atsph*gmet(1,1)) 520 rr2=sqrt(r2atsph*gmet(2,2)) 521 rr3=sqrt(r2atsph*gmet(3,3)) 522 523 n1a=int((xred(1,iatom)-rr1+ishift)*n1+delta)-ishift*n1 524 n1b=int((xred(1,iatom)+rr1+ishift)*n1 )-ishift*n1 525 n2a=int((xred(2,iatom)-rr2+ishift)*n2+delta)-ishift*n2 526 n2b=int((xred(2,iatom)+rr2+ishift)*n2 )-ishift*n2 527 n3a=int((xred(3,iatom)-rr3+ishift)*n3+delta)-ishift*n3 528 n3b=int((xred(3,iatom)+rr3+ishift)*n3 )-ishift*n3 529 530 ratsm2 = -(ratsm**2 - 2*ratsph(typat(iatom))*ratsm) 531 532 ABI_MALLOC(difx,(n1a:n1b)) 533 do i1=n1a,n1b 534 difx(i1)=dble(i1)/dble(n1)-xred(1,iatom) 535 enddo ! i1 536 537 do i3=n3a,n3b 538 iz=mod(i3+ishift*n3,n3) 539 if(fftn3_distrib(iz+1)==mpi_enreg%me_fft) then 540 izloc = ffti3_local(iz+1) - 1 541 difz=dble(i3)/dble(n3)-xred(3,iatom) 542 do i2=n2a,n2b 543 iy=mod(i2+ishift*n2,n2) 544 dify=dble(i2)/dble(n2)-xred(2,iatom) 545 rx23=dify*rprimd(1,2)+difz*rprimd(1,3) 546 ry23=dify*rprimd(2,2)+difz*rprimd(2,3) 547 rz23=dify*rprimd(3,2)+difz*rprimd(3,3) 548 r2_23=rx23**2+ry23**2+rz23**2 549 r2_11=rprimd(1,1)**2+rprimd(2,1)**2+rprimd(3,1)**2 550 r2_123=2*(rprimd(1,1)*rx23+rprimd(2,1)*ry23+rprimd(3,1)*rz23) 551 do i1=n1a,n1b 552 r2=(difx(i1)*r2_11+r2_123)*difx(i1)+r2_23 553 if (r2 > r2atsph) cycle 554 call radsmear(dfsm,fsm,r2,r2atsph,ratsm2) 555 ix=mod(i1+ishift*n1,n1) 556 ! Identify the fft indexes of the rectangular grid around the atom 557 ifft_local=1+ix+n1*(iy+n2*izloc) 558 nv_constr_dft_r(ifft_local,1:nspden)=nv_constr_dft_r(ifft_local,1:nspden) + fsm*coeffs_constr_dft(1:nspden,iatom) 559 560 end do ! i1 561 end do ! i2 562 end if ! if this is my fft slice 563 end do ! i3 564 ABI_FREE(difx) 565 566 ! end loop over atoms 567 end do 568 569 !MPI parallelization 570 !TODO: test if xmpi_sum does the correct stuff for a slice of nv_constr_dft_r 571 if(mpi_enreg%nproc_fft>1)then 572 call timab(48,1,tsec) 573 call xmpi_sum(nv_constr_dft_r,mpi_enreg%comm_fft,ierr) 574 call timab(48,2,tsec) 575 end if 576 577 ! write (201,*) '# potential 1' 578 ! write (201,*) nv_constr_dft_r(:,1) 579 580 ! write (202,*) '# potential 2' 581 ! write (202,*) nv_constr_dft_r(:,2) 582 583 ! if (nspden > 2) then 584 ! write (203,*) '# potential 3' 585 ! write (203,*) nv_constr_dft_r(:,3) 586 587 ! write (204,*) '# potential 4' 588 ! write (204,*) nv_constr_dft_r(:,4) 589 ! end if 590 591 end subroutine add_atomic_fcts
m_dens/calcdenmagsph [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
calcdenmagsph
FUNCTION
Compute and print integral of total density inside spheres around atoms, or optionally of integral of potential residual. Also can compute the contributions to forces and stresses due to density-magnetization type constraints.
INPUTS
mpi_enreg=information about MPI parallelization natom=number of atoms in cell. nfft=(effective) number of FFT grid points (for this processor) ngfft(18)=contain all needed information about 3D FFT, see ~abinit/doc/variables/vargs.htm#ngfft nspden=number of spin-density components ntypat=number of atom types option = if not larger than 10, then a density is input , if larger than 10 then a potential residual is input. ratsm=smearing width for ratsph ratsph(ntypat)=radius of spheres around atoms rhor(nfft,nspden)=array for electron density in electrons/bohr**3. (total in first half and spin-up in second half if nspden=2) (total in first comp. and magnetization in comp. 2 to 4 if nspden=4) rprimd(3,3)=dimensional primitive translations in real space (bohr) typat(natom)=type of each atom xred(3,natom)=reduced dimensionless atomic coordinates
OUTPUT
dentot(nspden)=integrated density (magnetization...) over full u.c. vol. Optional argument gr_intgden(3,nspden,natom)=grad wrt atomic positions, of integrated density (magnetization...) for each atom in a sphere. Optional arg intgden(nspden, natom)=integrated density (magnetization...) for each atom in a sphere of radius ratsph. Optional arg Note that when intgden is present, the definition of the spherical integration function changes, as it is smoothed. intgf2(natom,natom)=overlaps of the spherical integration functions for each atom in a sphere of radius ratsph. Optional arg rhomag(2,nspden)=integrated complex density (magnetization...) over full u.c. vol. Optional argument In collinear case component 1 is total density and 2 is _magnetization_ up-down In non collinear case component 1 is total density, and 2:4 are the magnetization vector strs_intgden(6,nspden,natom)=stress contribution due to constrained integrated density (magnetization...), due to each atom. Optional arg Rest is printing
SOURCE
1517 subroutine calcdenmagsph(mpi_enreg,natom,nfft,ngfft,nspden,ntypat,ratsm,ratsph,rhor,rprimd,typat,xred,& 1518 & option,cplex,dentot,gr_intgden,intgden,intgf2,rhomag,strs_intgden) 1519 1520 !Arguments --------------------------------------------- 1521 !scalars 1522 integer,intent(in) :: natom,nfft,nspden,ntypat 1523 real(dp),intent(in) :: ratsm 1524 type(MPI_type),intent(in) :: mpi_enreg 1525 integer ,intent(in) :: option 1526 integer, intent(in) :: cplex 1527 !arrays 1528 integer,intent(in) :: ngfft(18),typat(natom) 1529 real(dp),intent(in) :: ratsph(ntypat),rhor(cplex*nfft,nspden),rprimd(3,3) 1530 real(dp),intent(in) :: xred(3,natom) 1531 real(dp),intent(out),optional :: dentot(nspden) 1532 real(dp),intent(out),optional :: gr_intgden(3,nspden,natom) 1533 real(dp),intent(out),optional :: intgden(nspden,natom) 1534 real(dp),intent(out),optional :: intgf2(natom,natom) 1535 real(dp),intent(out),optional :: rhomag(2,nspden) 1536 real(dp),intent(out),optional :: strs_intgden(6,nspden,natom) 1537 !Local variables ------------------------------ 1538 !scalars 1539 integer,parameter :: ndir=3,ishift=5 1540 integer :: i1,i2,i3,iatom,ierr,ifft_local,ii,isp,ispden,ix,iy,iz,izloc,jatom,n1,n1a,n1b,n2,ifft 1541 integer :: neighbor_overlap,n2a,n2b,n3,n3a,n3b,nfftot 1542 integer :: jfft 1543 real(dp),parameter :: delta=0.99_dp 1544 real(dp) :: difx,dify,difz,r2,r2atsph,rr1,rr2,rr3,rx,ry,rz 1545 real(dp) :: dfsm,fact,fsm,ratsm2,ucvol 1546 logical :: grid_found 1547 !arrays 1548 integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:) 1549 integer :: overlap_ij(natom,natom) 1550 real(dp) :: gmet(3,3),gprimd(3,3),gr_intg(3,4) 1551 real(dp) :: intg(4),rhomag_(2,nspden) 1552 real(dp) :: strs(3,3),strs_cartred(3,3),strs_intg(6,4),tsec(2) 1553 real(dp) :: dist_ij(natom,natom),intgden_(nspden,natom) 1554 real(dp) :: my_xred(3, natom), rmet(3,3),xshift(3, natom) 1555 real(dp), allocatable :: fsm_atom(:,:) 1556 1557 !real(dp) :: rprimd_mod(3,3),strain 1558 1559 ! ************************************************************************* 1560 1561 n1=ngfft(1);n2=ngfft(2);n3=ngfft(3) 1562 nfftot=n1*n2*n3 1563 intgden_=zero 1564 if(present(intgden))then 1565 intgden=zero 1566 endif 1567 if(present(gr_intgden))then 1568 gr_intgden=zero 1569 endif 1570 if(present(strs_intgden))then 1571 strs_intgden=zero 1572 endif 1573 1574 call metric(gmet,gprimd,-1,rmet,rprimd,ucvol) 1575 1576 ! This routine is not able to handle xred positions that are "far" from the 1577 ! first unit cell so wrap xred into [0, 1[ interval here. 1578 call wrap2_zero_one(xred, my_xred, xshift) 1579 1580 !If intgf2 present, check that the spheres do not overlap. If they overlap, one needs to treat explicitly the neighbors. 1581 if(present(intgf2))then 1582 neighbor_overlap=0 1583 dist_ij(:,:)=zero 1584 intgf2(:,:)=zero 1585 overlap_ij(:,:)=0 1586 dist_ij(1,1)=dist2(xred(:,1),xred(:,1),rprimd,-1) 1587 do iatom=1,natom 1588 dist_ij(iatom,iatom)=dist_ij(1,1) 1589 overlap_ij(iatom,iatom)=1 1590 do jatom=iatom,natom 1591 if(iatom/=jatom)dist_ij(iatom,jatom)=dist2(xred(:,iatom),xred(:,jatom),rprimd,1) 1592 if(dist_ij(iatom,jatom)-ratsph(typat(iatom))-ratsph(typat(jatom))<tol10)then 1593 overlap_ij(iatom,jatom)=1 1594 neighbor_overlap=1 1595 endif 1596 enddo 1597 enddo 1598 if(neighbor_overlap==1)then 1599 ABI_MALLOC(fsm_atom,(nfft,natom)) 1600 fsm_atom(:,:)=zero 1601 endif 1602 endif 1603 1604 !Get the distrib associated with this fft_grid 1605 grid_found=.false. 1606 1607 if(n2 == mpi_enreg%distribfft%n2_coarse ) then 1608 if(n3== size(mpi_enreg%distribfft%tab_fftdp3_distrib)) then 1609 fftn3_distrib => mpi_enreg%distribfft%tab_fftdp3_distrib 1610 ffti3_local => mpi_enreg%distribfft%tab_fftdp3_local 1611 grid_found=.true. 1612 end if 1613 end if 1614 1615 if(n2 == mpi_enreg%distribfft%n2_fine ) then 1616 if(n3 == size(mpi_enreg%distribfft%tab_fftdp3dg_distrib)) then 1617 fftn3_distrib => mpi_enreg%distribfft%tab_fftdp3dg_distrib 1618 ffti3_local => mpi_enreg%distribfft%tab_fftdp3dg_local 1619 grid_found = .true. 1620 end if 1621 end if 1622 1623 if(.not.(grid_found)) then 1624 ABI_BUG("Unable to find an allocated distrib for this fft grid") 1625 end if 1626 1627 !Loop over atoms 1628 !------------------------------------------- 1629 do iatom=1,natom 1630 1631 ! Define a "box" around the atom 1632 r2atsph=1.0000001_dp*ratsph(typat(iatom))**2 1633 rr1=sqrt(r2atsph*gmet(1,1)) 1634 rr2=sqrt(r2atsph*gmet(2,2)) 1635 rr3=sqrt(r2atsph*gmet(3,3)) 1636 1637 n1a=int((my_xred(1,iatom)-rr1+ishift)*n1+delta)-ishift*n1 1638 n1b=int((my_xred(1,iatom)+rr1+ishift)*n1 )-ishift*n1 1639 n2a=int((my_xred(2,iatom)-rr2+ishift)*n2+delta)-ishift*n2 1640 n2b=int((my_xred(2,iatom)+rr2+ishift)*n2 )-ishift*n2 1641 n3a=int((my_xred(3,iatom)-rr3+ishift)*n3+delta)-ishift*n3 1642 n3b=int((my_xred(3,iatom)+rr3+ishift)*n3 )-ishift*n3 1643 1644 !This is the "width" of the zone of smearing, in term of the square of radius 1645 ratsm2 = (2*ratsph(typat(iatom))-ratsm)*ratsm 1646 1647 intg(:)=zero 1648 gr_intg(:,:)=zero 1649 strs_intg(:,:)=zero 1650 1651 do i3=n3a,n3b 1652 iz=mod(i3+ishift*n3,n3) 1653 1654 if(fftn3_distrib(iz+1)==mpi_enreg%me_fft) then 1655 1656 izloc = ffti3_local(iz+1) - 1 1657 difz=dble(i3)/dble(n3)-my_xred(3,iatom) 1658 do i2=n2a,n2b 1659 iy=mod(i2+ishift*n2,n2) 1660 dify=dble(i2)/dble(n2)-my_xred(2,iatom) 1661 do i1=n1a,n1b 1662 ix=mod(i1+ishift*n1,n1) 1663 1664 difx=dble(i1)/dble(n1)-my_xred(1,iatom) 1665 !DEBUG 1666 ! if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then 1667 ! difx=dble(i1)/dble(n1)-(my_xred(1,iatom)+0.00005) 1668 ! endif 1669 !ENDDEBUG 1670 rx=difx*rprimd(1,1)+dify*rprimd(1,2)+difz*rprimd(1,3) 1671 1672 !DEBUG 1673 ! if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then 1674 ! strain=-0.001 1675 ! rx=difx*rprimd(1,1)*(one+strain)+dify*rprimd(1,2)+difz*rprimd(1,3) 1676 ! endif 1677 !ENDDEBUG 1678 1679 ry=difx*rprimd(2,1)+dify*rprimd(2,2)+difz*rprimd(2,3) 1680 rz=difx*rprimd(3,1)+dify*rprimd(3,2)+difz*rprimd(3,3) 1681 r2=rx**2+ry**2+rz**2 1682 1683 1684 ! Identify the fft indexes of the rectangular grid around the atom 1685 if(r2 > r2atsph) then 1686 cycle 1687 end if 1688 1689 call radsmear(dfsm,fsm,r2,r2atsph,ratsm2) 1690 1691 ifft_local=1+ix+n1*(iy+n2*izloc) 1692 1693 if(present(intgf2))then 1694 ! intgden_(1,iatom)= integral of the square of the spherical integrating function 1695 if(neighbor_overlap==0)intgf2(iatom,iatom)=intgf2(iatom,iatom)+fsm*fsm 1696 if(neighbor_overlap==1)fsm_atom(ifft_local,iatom)=fsm_atom(ifft_local,iatom)+fsm 1697 endif 1698 ! Integral of density or potential residual 1699 intg(1:nspden)=intg(1:nspden)+fsm*rhor(ifft_local,1:nspden) 1700 if((present(gr_intgden).or.present(strs_intgden)).and. option<10 .and. ratsm2>tol12)then 1701 do ispden=1,nspden 1702 fact=dfsm*rhor(ifft_local,ispden) 1703 if(present(gr_intgden))then 1704 gr_intg(1,ispden)=gr_intg(1,ispden)+difx*fact 1705 gr_intg(2,ispden)=gr_intg(2,ispden)+dify*fact 1706 gr_intg(3,ispden)=gr_intg(3,ispden)+difz*fact 1707 endif 1708 if(present(strs_intgden))then 1709 strs_intg(1,ispden)=strs_intg(1,ispden)+difx*difx*fact 1710 strs_intg(2,ispden)=strs_intg(2,ispden)+dify*dify*fact 1711 strs_intg(3,ispden)=strs_intg(3,ispden)+difz*difz*fact 1712 strs_intg(4,ispden)=strs_intg(4,ispden)+dify*difz*fact 1713 strs_intg(5,ispden)=strs_intg(5,ispden)+difx*difz*fact 1714 strs_intg(6,ispden)=strs_intg(6,ispden)+difx*dify*fact 1715 endif 1716 enddo 1717 endif 1718 end do 1719 end do 1720 end if 1721 end do 1722 1723 if(present(intgf2) .and. neighbor_overlap==0)then 1724 intgf2(iatom,iatom)=intgf2(iatom,iatom)*ucvol/dble(nfftot) 1725 endif 1726 1727 intg(:)=intg(:)*ucvol/dble(nfftot) 1728 1729 if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then 1730 ! Convert to gradient in reduced coordinates 1731 gr_intg=matmul(rmet,gr_intg) 1732 gr_intg(:,:)=-gr_intg(:,:)*two*ucvol/dble(nfftot) 1733 !DEBUG 1734 ! write(6,*)' calcdenmagsph : intg(1)=',intg(1) 1735 ! write(6,*)' calcdenmagsph : iatom,gr_intg(1,1)=',iatom,gr_intg(1,1) 1736 ! call flush(6) 1737 ! stop 1738 !ENDDEBUG 1739 endif 1740 1741 if(present(strs_intgden).and. option<10 .and. ratsm2>tol12)then 1742 ! Convert to stress in cartesian coordinates, for each spin constraint 1743 do isp=1,4 1744 ! First change the representation 1745 strs(1,1)=strs_intg(1,isp) ; strs(2,2)=strs_intg(2,isp) ; strs(3,3)=strs_intg(3,isp) 1746 strs(2,3)=strs_intg(4,isp) ; strs(3,2)=strs_intg(4,isp) 1747 strs(1,3)=strs_intg(5,isp) ; strs(3,1)=strs_intg(5,isp) 1748 strs(1,2)=strs_intg(6,isp) ; strs(2,1)=strs_intg(6,isp) 1749 1750 ! Then perform representation change, following Eq.(25) in Hamann2005 1751 do ii=1,3 1752 strs_cartred(:,ii)=matmul(rprimd,strs(:,ii)) 1753 enddo 1754 do ii=1,3 1755 strs(ii,:)=matmul(rprimd,strs_cartred(ii,:)) 1756 enddo 1757 1758 !DEBUG 1759 ! rprimd_mod=rprimd 1760 ! rprimd_mod(1,1)=rprimd(1,1)*(one+strain) 1761 ! do ii=1,3 1762 ! strs_cartred(:,ii)=matmul(rprimd_mod,strs(:,ii)) 1763 ! enddo 1764 ! do ii=1,3 1765 ! strs(ii,:)=matmul(rprimd_mod,strs_cartred(ii,:)) 1766 ! enddo 1767 !ENDDEBUG 1768 1769 strs_intg(1,isp)=two*strs(1,1) ; strs_intg(2,isp)=two*strs(2,2) ; strs_intg(3,isp)=two*strs(3,3) 1770 strs_intg(4,isp)=strs(2,3)+strs(3,2) 1771 strs_intg(5,isp)=strs(1,3)+strs(3,1) 1772 strs_intg(6,isp)=strs(1,2)+strs(2,1) 1773 enddo 1774 strs_intg(:,:)=strs_intg(:,:)/dble(nfftot) 1775 !DEBUG 1776 ! strs_intg(:,:)=zero 1777 ! write(6,*)' calcdenmagsph : iatom,-strs_intg(1,1)*ucvol=',iatom,strs_intg(1,1)*ucvol 1778 ! call flush(6) 1779 ! stop 1780 !ENDDEBUG 1781 endif 1782 1783 if(nspden==2 .and. option/=11)then 1784 ! Specific treatment of collinear density, due to the storage mode. 1785 ! intgden_(1,iatom)= integral of up density 1786 ! intgden_(2,iatom)= integral of dn density 1787 intgden_(1,iatom)=intg(2) 1788 intgden_(2,iatom)=intg(1)-intg(2) 1789 if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then 1790 gr_intgden(:,1,iatom)=gr_intg(:,2) 1791 gr_intgden(:,2,iatom)=gr_intg(:,1)-gr_intg(:,2) 1792 endif 1793 if(present(strs_intgden).and. option<10 .and. ratsm2>tol12)then 1794 strs_intgden(:,1,iatom)=strs_intg(:,2) 1795 strs_intgden(:,2,iatom)=strs_intg(:,1)-strs_intg(:,2) 1796 endif 1797 else 1798 intgden_(1:nspden,iatom)=intg(1:nspden) 1799 if(present(gr_intgden).and. option<10 .and. ratsm2>tol12)then 1800 gr_intgden(:,1:nspden,iatom)=gr_intg(:,1:nspden) 1801 endif 1802 if(present(strs_intgden).and. option<10 .and. ratsm2>tol12)then 1803 strs_intgden(:,1:nspden,iatom)=strs_intg(:,1:nspden) 1804 endif 1805 endif 1806 1807 end do ! iatom 1808 !------------------------------------------- 1809 ! 1810 ! In case intgf2 must be computed, while the atoms overlap, a double loop over atoms is needed 1811 if(present(intgf2) .and. neighbor_overlap==1)then 1812 do iatom=1,natom 1813 do jatom=iatom,natom 1814 if(overlap_ij(iatom,jatom)/=0)then 1815 do i3=1,n3 1816 iz=mod(i3,n3) 1817 if(fftn3_distrib(iz+1)==mpi_enreg%me_fft) then 1818 izloc = ffti3_local(iz+1) - 1 1819 do i2=1,n2 1820 iy=mod(i2,n2) 1821 do i1=1,n1 1822 ix=mod(i1,n1) 1823 ifft_local=1+ix+n1*(iy+n2*izloc) 1824 intgf2(iatom,jatom)=intgf2(iatom,jatom)+fsm_atom(ifft_local,iatom)*fsm_atom(ifft_local,jatom) 1825 enddo 1826 enddo 1827 endif 1828 enddo ! i3 1829 intgf2(iatom,jatom)=intgf2(iatom,jatom)*ucvol/dble(nfftot) 1830 endif 1831 enddo 1832 if(iatom/=1)then 1833 do jatom=1,iatom-1 1834 intgf2(iatom,jatom)=intgf2(jatom,iatom) 1835 enddo 1836 endif 1837 enddo 1838 ABI_FREE(fsm_atom) 1839 endif 1840 1841 !MPI parallelization 1842 if(present(intgf2)) then 1843 if(mpi_enreg%nproc_fft>1)then 1844 call timab(48,1,tsec) 1845 call xmpi_sum(intgf2,mpi_enreg%comm_fft,ierr) 1846 call timab(48,2,tsec) 1847 end if 1848 end if 1849 1850 !------------------------------------------- 1851 1852 !MPI parallelization 1853 if(present(intgden) .or. option/=0) then 1854 if(mpi_enreg%nproc_fft>1)then 1855 call timab(48,1,tsec) 1856 call xmpi_sum(intgden_,mpi_enreg%comm_fft,ierr) 1857 call timab(48,2,tsec) 1858 end if 1859 if(present(intgden))intgden = intgden_ 1860 end if 1861 1862 if(present(gr_intgden) .and. option<10 .and. ratsm2>tol12) then 1863 if(mpi_enreg%nproc_fft>1)then 1864 call timab(48,1,tsec) 1865 call xmpi_sum(gr_intgden,mpi_enreg%comm_fft,ierr) 1866 call timab(48,2,tsec) 1867 end if 1868 end if 1869 1870 if(present(strs_intgden) .and. option<10 .and. ratsm2>tol12) then 1871 if(mpi_enreg%nproc_fft>1)then 1872 call timab(48,1,tsec) 1873 call xmpi_sum(strs_intgden,mpi_enreg%comm_fft,ierr) 1874 call timab(48,2,tsec) 1875 end if 1876 end if 1877 1878 !EB - Compute magnetization of the whole cell 1879 if(present(dentot) .or. present(rhomag))then 1880 rhomag_(:,:)=zero 1881 if(nspden==2) then 1882 do ifft=1,nfft 1883 jfft=1+cplex*(ifft-1) 1884 rhomag_(1:cplex,1)=rhomag_(1:cplex,1)+rhor(jfft:jfft+cplex-1,1) ! real & imag part of density 1885 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 1886 end do 1887 else if(nspden==4) then 1888 do ifft=1,nfft 1889 jfft=1+cplex*(ifft-1) 1890 rhomag_(1:cplex,1:nspden)=rhomag_(1:cplex,1:nspden)+rhor(jfft:jfft+cplex-1,1:nspden) 1891 end do 1892 end if 1893 1894 rhomag_(1:cplex,1:nspden)=rhomag_(1:cplex,1:nspden)*ucvol/dble(nfftot) 1895 1896 !MPI parallelization 1897 if(mpi_enreg%nproc_fft>1)then 1898 call timab(48,1,tsec) 1899 call xmpi_sum(rhomag_,mpi_enreg%comm_fft,ierr) 1900 call timab(48,2,tsec) 1901 end if 1902 1903 if(present(dentot))then 1904 dentot(:)=rhomag_(1,:) 1905 endif 1906 1907 if(present(rhomag))then 1908 rhomag(:,:)=rhomag_(:,:) 1909 endif 1910 endif 1911 1912 !DEBUG BUT KEEP 1913 if(.false.)then 1914 call printmagvtk(mpi_enreg,cplex,nspden,nfft,ngfft,rhor,rprimd,'DEN.vtk') 1915 endif 1916 !ENDDEBUG 1917 1918 end subroutine calcdenmagsph
m_dens/constrained_dft_free [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
constrained_dft_free
FUNCTION
Free the constrained_dft datastructure.
INPUTS
constrained_dft=datastructure that contain the needed information to enforce the density and magnetization constraints
OUTPUT
SOURCE
726 subroutine constrained_dft_free(constrained_dft) 727 728 !Arguments ------------------------------------ 729 !scalars 730 type(constrained_dft_t),intent(inout):: constrained_dft 731 732 !Local variables------------------------------- 733 734 ! *********************************************************************************************** 735 736 ABI_SFREE(constrained_dft%chrgat) 737 ABI_SFREE(constrained_dft%constraint_kind) 738 ABI_SFREE(constrained_dft%intgf2) 739 ABI_SFREE(constrained_dft%ratsph) 740 ABI_SFREE(constrained_dft%spinat) 741 ABI_SFREE(constrained_dft%typat) 742 ABI_SFREE(constrained_dft%ziontypat) 743 744 end subroutine constrained_dft_free
m_dens/constrained_dft_ini [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
constrained_dft_ini
FUNCTION
Initialize the constrained_dft datastructure. Mostly copying already available (dtset) information, but also computing intgf2
INPUTS
chrgat(natom) = target charge for each atom. Not always used, it depends on the value of constraint_kind constraint_kind(ntypat)=for each type of atom, 0=no constraint, 1=fix only the magnetization direction, following spinat direction, 2=fix the magnetization vector to be the spinat one, 3=fix the magnetization amplitude to be the spinat one, but does not fix its direction other future values will constrain the local atomic charge and possibly mix constraints if needed. magconon=type of penalty function (so, not constrained DFT). magcon_lambda=strength of the atomic spherical constraint mpi_enreg=mpi structure with communicator info natom=number of atoms nfft=number of points in standard fft grid ngfft=FFT grid dimensions nspden = number of spin densities (1 2 or 4) ntypat=number of types of atoms ratsm=smearing width for ratsph ratsph(ntypat)=radii for muffin tin spheres of each atom rprimd=lattice vectors (dimensioned) spinat(3,natom)=magnetic moments vectors, possible targets according to the value of constraint_kind typat(natom)=types of atoms xred(3,natom)=reduced atomic positions ziontypat(ntypat)=ionic charge, per type of atom
OUTPUT
constrained_dft=datastructure that contain the needed information to enforce the density and magnetization constraints Most of the data are simply copied from dtset, but also constrained_dft%intgf2(natom,natom) is computed from the available data.
SOURCE
632 subroutine constrained_dft_ini(chrgat,constrained_dft,constraint_kind,& 633 & magconon,magcon_lambda,mpi_enreg,natom,nfftf,ngfftf,nspden,ntypat,& 634 & ratsm,ratsph,rprimd,spinat,typat,xred,ziontypat) 635 636 !Arguments ------------------------------------ 637 !scalars 638 integer,intent(in) :: magconon,natom,nfftf,nspden,ntypat 639 real(dp),intent(in) :: magcon_lambda,ratsm 640 type(MPI_type),intent(in) :: mpi_enreg 641 type(constrained_dft_t),intent(out):: constrained_dft 642 !arrays 643 integer,intent(in) :: constraint_kind(ntypat) 644 integer,intent(in) :: ngfftf(18) 645 integer,intent(in) :: typat(natom) 646 real(dp),intent(in) :: chrgat(natom) 647 real(dp),intent(in) :: ratsph(ntypat) 648 real(dp),intent(in) :: rprimd(3,3) 649 real(dp),intent(in) :: spinat(3,natom) 650 real(dp),intent(in) :: xred(3,natom) 651 real(dp),intent(in) :: ziontypat(ntypat) 652 653 !Local variables------------------------------- 654 !scalars 655 integer :: cplex1=1 656 real(dp) :: ucvol 657 !arrays 658 real(dp), allocatable :: intgf2(:,:) ! natom,natom 659 real(dp), allocatable :: rhor_dum(:,:) ! nfftf,nspden 660 real(dp) :: gprimd(3,3),rmet(3,3),gmet(3,3) 661 662 ! *********************************************************************************************** 663 664 ABI_MALLOC(intgf2,(natom,natom)) 665 666 !We need the metric because it is needed in calcdenmagsph.F90 667 call metric(gmet,gprimd,-1,rmet,rprimd,ucvol) 668 669 if(any(constraint_kind(:)/=0))then 670 !We need to precompute intgf2 671 ABI_MALLOC(rhor_dum,(nfftf,nspden)) 672 rhor_dum(:,:)=zero 673 call calcdenmagsph(mpi_enreg,natom,nfftf,ngfftf,nspden,ntypat,& 674 & ratsm,ratsph,rhor_dum,rprimd,typat,xred,0,cplex1,intgf2=intgf2) 675 ABI_FREE(rhor_dum) 676 else 677 intgf2=zero 678 endif 679 680 constrained_dft%magconon =magconon 681 constrained_dft%magcon_lambda =magcon_lambda 682 constrained_dft%natom =natom 683 constrained_dft%nfftf =nfftf 684 constrained_dft%ngfftf =ngfftf 685 constrained_dft%nspden =nspden 686 constrained_dft%ntypat =ntypat 687 constrained_dft%ratsm =ratsm 688 constrained_dft%rprimd =rprimd 689 690 ABI_MALLOC(constrained_dft%chrgat,(natom)) 691 ABI_MALLOC(constrained_dft%constraint_kind,(ntypat)) 692 ABI_MALLOC(constrained_dft%intgf2,(natom,natom)) 693 ABI_MALLOC(constrained_dft%ratsph,(ntypat)) 694 ABI_MALLOC(constrained_dft%spinat,(3,natom)) 695 ABI_MALLOC(constrained_dft%typat,(natom)) 696 ABI_MALLOC(constrained_dft%ziontypat,(ntypat)) 697 698 constrained_dft%chrgat =chrgat 699 constrained_dft%constraint_kind =constraint_kind 700 constrained_dft%intgf2 =intgf2 701 constrained_dft%ratsph =ratsph 702 constrained_dft%spinat =spinat 703 constrained_dft%typat =typat 704 constrained_dft%ziontypat =ziontypat 705 706 ABI_FREE(intgf2) 707 708 end subroutine constrained_dft_ini
m_dens/constrained_dft_t [ Types ]
NAME
constrained_dft_t
FUNCTION
Structure gathering the relevant information for constrained DFT calculations
SOURCE
65 type,public :: constrained_dft_t 66 67 !scalars 68 integer :: natom ! Number of atoms 69 integer :: nfftf ! Number of FFT grid points (for this processor) for the "fine" grid 70 integer :: nspden ! Number of spin-density components 71 integer :: ntypat ! Number of type of atoms 72 73 real(dp) :: magcon_lambda ! Strength of the atomic spherical constraint 74 real(dp) :: ratsm ! Smearing width for ratsph 75 76 integer :: magconon ! Turn on the penalty function constraint instead of the more powerful constrainedDFT algorithm 77 78 !arrays 79 80 integer :: ngfftf(18) ! Number of FFT grid points (for this processor) for the "fine" grid 81 82 integer,allocatable :: typat(:) 83 ! typat(natom) 84 ! Type of each natom 85 86 integer,allocatable :: constraint_kind(:) 87 ! constraint_kind(ntypat) 88 ! Constraint kind to be applied to each type of atom. See corresponding input variable 89 90 real(dp) :: rprimd(3,3) 91 ! Direct lattice vectors, Bohr units. 92 93 real(dp),allocatable :: chrgat(:) 94 ! chrgat(natom) 95 ! Target charge for each atom. Not always used, it depends on the value of constraint_kind 96 97 real(dp),allocatable :: intgf2(:,:) 98 ! intgf2(natom,natom) 99 ! Overlap of the spherical integrating functions, for each atom. 100 ! Initialized using some xred values, will not change during the SCF cycles, except for exotic algorithms, not in production, 101 102 real(dp),allocatable :: ratsph(:) 103 ! ratsph(ntypat) 104 ! Radius of the atomic sphere for each type of atom 105 106 real(dp),allocatable :: spinat(:,:) 107 ! spinat(3,natom) 108 ! Target magnetization for each atom. Possibly only the direction or the magnitude, depending on constraint_kind 109 110 real(dp),allocatable :: ziontypat(:) 111 ! ziontypat(ntypat) 112 ! Ionic charge, per type of atom 113 114 end type constrained_dft_t
m_dens/constrained_residual [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
constrained_residual
FUNCTION
Recompute the residual to take into account the constraints, within constrained DFT. The kind of constraint is given by constraint_kind, and the target values are given by spinat, for the local atomic magnetization, and chrgat minus the ionic charge, for the local atomic charge.
INPUTS
c_dft <type(constrained_dft_t)>=datastructure for the information related to constrained DFT ! chrgat(natom) = target charge for each atom. Not always used, it depends on the value of constraint_kind ! constraint_kind(ntypat)=for each type of atom, 0=no constraint, ! 1=fix only the magnetization direction, following spinat direction, ! 2=fix the magnetization vector to be the spinat one, ! 3=fix the magnetization amplitude to be the spinat one, but does not fix its direction ! other future values will constrain the local atomic charge and possibly mix constraints if needed. ! intgf2(natom,natom)=(precomputed) overlap of the spherical integration functions for each atom in a sphere of radius ratsph. ! magcon_lambda=strength of the atomic spherical constraint ! natom=number of atoms ! nfftf=number of points in fine fft grid ! ngfftf=FFT grid dimensions ! nspden = number of spin densities (1 2 or 4) ! ntypat=number of types of atoms ! ratsm=smearing width for ratsph ! ratsph(ntypat)=radii for muffin tin spheres of each atom ! rprimd=lattice vectors (dimensioned) ! spinat(3,natom)=magnetic moments vectors, possible targets according to the value of constraint_kind ! typat(natom)=types of atoms ! ziontypat(ntypat)= ionic charge, per type of atom mpi_enreg=mpi structure with communicator info rhor(nfft,nspden)=array for electron density in el./bohr**3. At output it will be constrained. xred(3,natom)=reduced atomic positions
OUTPUT
e_constrained_dft=correction to the total energy, to make it variational grcondft(3,natom)=d(E_constrained_DFT)/d(xred) (hartree) intgres(nspden,natom)=integrated residuals from constrained DFT. They are also Lagrange parameters, or gradients with respect to constraints. strscondft(6)=stress due to constraints = -d(E_constrained_DFT)/d(strain) / ucvol (hartree/Bohr^3)
SIDE EFFECTS
vresid(nfft,nspden)==array for potential residual in real space At output it will be modified: projected onto the space orthogonal to the atomic spherical functions (if there is a related constrained, and augmented by such atomic spherical functions multiplied by the difference between the actual integrated charge or magnetization and the target ones.
SOURCE
797 subroutine constrained_residual(c_dft,e_constrained_dft,grcondft,intgres,mpi_enreg,rhor,strscondft,vresid,xred) 798 799 !Arguments ------------------------------------ 800 !scalars 801 real(dp),intent(out) :: e_constrained_dft 802 type(constrained_dft_t),intent(in) :: c_dft 803 type(MPI_type),intent(in) :: mpi_enreg 804 !arrays 805 real(dp),intent(out) :: grcondft(:,:) ! 3,natom 806 real(dp),intent(out) :: intgres(:,:) ! nspden,natom 807 real(dp),intent(in) :: rhor(c_dft%nfftf,c_dft%nspden) 808 real(dp),intent(out) :: strscondft(6) 809 real(dp),intent(inout) :: vresid(c_dft%nfftf,c_dft%nspden) 810 real(dp),intent(in) :: xred(3,c_dft%natom) 811 812 !Local variables------------------------------- 813 !scalars 814 integer :: conkind,iatom,ii,jatom,info,natom,nfftf,nspden,ntypat,option 815 integer :: cplex1=1 816 real(dp) :: intgd,intgden_norm,intgden_proj,intgres_proj,norm,scprod 817 !arrays 818 integer :: ipiv(c_dft%natom) 819 real(dp) :: corr_denmag(4),gr_intgd(3),strs_intgd(6) 820 real(dp), allocatable :: coeffs_constr_dft(:,:) ! nspden,natom 821 real(dp), allocatable :: gr_intgden(:,:,:) ! 3,nspden,natom 822 real(dp), allocatable :: intgden(:,:) ! nspden,natom 823 real(dp), allocatable :: intgden_delta(:,:) ! nspden,natom 824 real(dp), allocatable :: intgres_tmp(:,:) ! nspden,natom 825 real(dp), allocatable :: intgr(:,:) ! natom,nspden 826 real(dp), allocatable :: strs_intgden(:,:,:) ! 6,nspden,natom 827 real(dp) :: intgf2(c_dft%natom,c_dft%natom),rhomag(2,c_dft%nspden),work(2*c_dft%natom) 828 real(dp) :: intgden_normed(3) 829 real(dp) :: spinat_normed(3) 830 831 ! *********************************************************************************************** 832 833 !DEBUG 834 !write(std_out,*) ' constrained_residual : enter ' 835 !ENDDEBUG 836 837 natom=c_dft%natom 838 nfftf=c_dft%nfftf 839 nspden=c_dft%nspden 840 ntypat=c_dft%ntypat 841 842 !We need the integrated magnetic moments 843 ABI_MALLOC(intgden,(nspden,natom)) 844 ABI_MALLOC(gr_intgden,(3,nspden,natom)) 845 ABI_MALLOC(strs_intgden,(6,nspden,natom)) 846 call calcdenmagsph(mpi_enreg,natom,nfftf,c_dft%ngfftf,nspden,ntypat,c_dft%ratsm,c_dft%ratsph,rhor,c_dft%rprimd,c_dft%typat,& 847 & xred,1,cplex1,intgden=intgden,gr_intgden=gr_intgden,rhomag=rhomag,strs_intgden=strs_intgden) 848 call prtdenmagsph(cplex1,intgden,natom,nspden,ntypat,std_out,1,c_dft%ratsm,c_dft%ratsph,rhomag,c_dft%typat) 849 850 !DEBUG 851 !write(std_out,*) ' intgden(1:nspden,1:natom)=',intgden(1:nspden,1:natom) 852 !ENDDEBUG 853 854 !We need the integrated residuals 855 ABI_MALLOC(intgres_tmp,(nspden,natom)) 856 intgres_tmp(:,:)=zero 857 call calcdenmagsph(mpi_enreg,natom,nfftf,c_dft%ngfftf,nspden,ntypat,& 858 & c_dft%ratsm,c_dft%ratsph,vresid,c_dft%rprimd,c_dft%typat,xred,11,cplex1,intgden=intgres_tmp,rhomag=rhomag) 859 860 !DEBUG 861 !write(std_out,*) ' intgres_tmp(1:nspden,1:natom)=',intgres_tmp(1:nspden,1:natom) 862 !ENDDEBUG 863 864 !Make the proper combination of intgres_tmp, to single out the scalar potential residual and the magnetic field potential residuals for x,y,z. 865 intgres(:,:)=zero 866 do iatom=1,natom 867 if(nspden==1)then 868 intgres(1,iatom)=intgres_tmp(1,iatom) 869 else if(nspden==2)then 870 intgres(1,iatom)=half*(intgres_tmp(1,iatom)+intgres_tmp(2,iatom)) 871 intgres(2,iatom)=half*(intgres_tmp(1,iatom)-intgres_tmp(2,iatom)) 872 else if(nspden==4)then 873 !Change the potential residual to the density+magnetization convention 874 intgres(1,iatom)=half*(intgres_tmp(1,iatom)+intgres_tmp(2,iatom)) 875 intgres(2,iatom)= intgres_tmp(3,iatom) 876 intgres(3,iatom)=-intgres_tmp(4,iatom) 877 intgres(4,iatom)=half*(intgres_tmp(1,iatom)-intgres_tmp(2,iatom)) 878 endif 879 conkind=c_dft%constraint_kind(c_dft%typat(iatom)) 880 if(conkind <10)intgres(1,iatom)=zero 881 if( mod(conkind,10)==0 .and. nspden>1)intgres(2:nspden,iatom)=zero 882 enddo 883 !Print the potential residuals 884 call prtdenmagsph(cplex1,intgres,natom,nspden,ntypat,std_out,11,c_dft%ratsm,c_dft%ratsph,rhomag,c_dft%typat) 885 ABI_FREE(intgres_tmp) 886 887 !Also exchanges the spin and atom indices to prepare the solution of the linear system of equation 888 ABI_MALLOC(intgr,(natom,nspden)) 889 do iatom=1,natom 890 intgr(iatom,1:nspden)=intgres(1:nspden,iatom) 891 enddo 892 893 !In case there is an overlap between spheres, must solve the linear system of equations 894 !and take into account non-diagonal elements only for the set of atoms for which there is a constraint. 895 !This can be different for the 896 !charge residual or for the spin residual (but for the spin constraints, the set of atoms is inclusive of all constraints) 897 do ii=1,2 ! Charge, then spin 898 intgf2(:,:)=zero 899 do iatom=1,natom 900 intgf2(iatom,iatom)=c_dft%intgf2(iatom,iatom) 901 enddo 902 do iatom=1,natom-1 903 do jatom=iatom,natom 904 if(c_dft%intgf2(iatom,jatom)>tol8)then 905 !In the charge case, must have both atoms with constraints bigger than 10 906 if(ii==1)then 907 if(c_dft%constraint_kind(c_dft%typat(iatom))>=10 .and. & 908 & c_dft%constraint_kind(c_dft%typat(jatom))>=10 )then 909 intgf2(iatom,jatom)=c_dft%intgf2(iatom,jatom) 910 intgf2(jatom,iatom)=c_dft%intgf2(iatom,jatom) 911 endif 912 endif 913 !In the spin case, must have both atoms with constraints not ending with 0 914 if(ii==2)then 915 if(mod(c_dft%constraint_kind(c_dft%typat(iatom)),10)/=0 .and. & 916 & mod(c_dft%constraint_kind(c_dft%typat(jatom)),10)/=0 )then 917 intgf2(iatom,jatom)=c_dft%intgf2(iatom,jatom) 918 intgf2(jatom,iatom)=c_dft%intgf2(iatom,jatom) 919 endif 920 endif 921 endif 922 enddo 923 enddo 924 925 !Solve the linear system of equation, for the different spins 926 call dsytrf('U',natom,intgf2,natom,ipiv,work,2*natom,info) 927 ! call dsytri('U',natom,intgf2,natom,ipiv,work,info) 928 if(ii==1)then 929 call dsytrs('U',natom,1,intgf2,natom,ipiv,intgr,natom,info) 930 else if(ii==2 .and. nspden>1)then 931 call dsytrs('U',natom,nspden-1,intgf2,natom,ipiv,intgr(1:natom,2:nspden),natom,info) 932 endif 933 934 !Store the new residuals 935 do iatom=1,natom 936 if(ii==1)intgres(1,iatom)=intgr(iatom,1) 937 if(ii==2)intgres(2:nspden,iatom)=intgr(iatom,2:nspden) 938 enddo 939 940 enddo 941 942 !DEBUG 943 !write(std_out,*) ' after multiplication by ftt-1 , so, torque :' 944 !write(std_out,*) ' intgres(1:nspden,1:natom)=',intgres(1:nspden,1:natom) 945 !ENDDEBUG 946 947 !Compute the delta of the integrated dens with respect to the target 948 !Compute the energy correction, to make the energy functional variational 949 !Also projects the residual in case constraint_kind 2 950 e_constrained_dft=zero 951 grcondft=zero 952 strscondft=zero 953 ABI_MALLOC(intgden_delta,(nspden,natom)) 954 intgden_delta(:,:)=zero 955 do iatom=1,natom 956 957 ! The integrated density must be in the total density+magnetization representation 958 if(nspden==2)then 959 intgd =intgden(1,iatom)+intgden(2,iatom) 960 intgden(2,iatom)=intgden(1,iatom)-intgden(2,iatom) 961 intgden(1,iatom)=intgd 962 do ii=1,3 963 gr_intgd(ii) =gr_intgden(ii,1,iatom)+gr_intgden(ii,2,iatom) 964 gr_intgden(ii,2,iatom)=gr_intgden(ii,1,iatom)-gr_intgden(ii,2,iatom) 965 gr_intgden(ii,1,iatom)=gr_intgd(ii) 966 enddo 967 do ii=1,6 968 strs_intgd(ii) =strs_intgden(ii,1,iatom)+strs_intgden(ii,2,iatom) 969 strs_intgden(ii,2,iatom)=strs_intgden(ii,1,iatom)-strs_intgden(ii,2,iatom) 970 strs_intgden(ii,1,iatom)=strs_intgd(ii) 971 enddo 972 endif 973 974 !Comparison with the target value, and computation of the correction in terms of density and magnetization coefficients. 975 conkind=c_dft%constraint_kind(c_dft%typat(iatom)) 976 977 if(conkind >=10)then 978 !The electronic constraint is such that the ziontypat charge minus (the electronic charge is negative) the atomic electronic density 979 !intgden gives the target charge chrgat. 980 intgden_delta(1,iatom)=intgden(1,iatom)+c_dft%chrgat(iatom)-c_dft%ziontypat(c_dft%typat(iatom)) 981 ! Uses the usual electronic charge definition, instead of the total nucleus-electronic charge 982 ! intgden_delta(1,iatom)=intgden(1,iatom)-c_dft%chrgat(iatom) 983 endif 984 985 if( mod(conkind,10)==1 .and. nspden>1)then 986 !Fix the different components of the magnetization vector 987 if(nspden==2)intgden_delta(2,iatom)=intgden(2,iatom)-c_dft%spinat(3,iatom) 988 if(nspden==4)intgden_delta(2:4,iatom)=intgden(2:4,iatom)-c_dft%spinat(1:3,iatom) 989 else if( ( mod(conkind,10)>=2 .and. mod(conkind,10)<=4) .and. nspden>1)then 990 norm = sqrt(sum(c_dft%spinat(:,iatom)**2)) 991 if (norm > tol10) then 992 if( mod(conkind,10)==2 )then 993 !Fix the axis of the magnetization vector 994 if(nspden==4)then 995 spinat_normed(:) = c_dft%spinat(:,iatom) / norm 996 !Calculate the scalar product of the fixed mag. mom. vector and calculated mag. mom. vector 997 !This is actually the size of the projection of the calc. mag. mom. vector on the fixed mag. mom. vector 998 intgden_proj=spinat_normed(1)*intgden(2,iatom)+ & 999 & spinat_normed(2)*intgden(3,iatom)+ & 1000 & spinat_normed(3)*intgden(4,iatom) 1001 intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)-spinat_normed(1:3)*intgden_proj 1002 !Also projects the residual, so that the usual optimization is done is the largest possible space 1003 intgres_proj=spinat_normed(1)*intgres(2,iatom)+ & 1004 & spinat_normed(2)*intgres(3,iatom)+ & 1005 & spinat_normed(3)*intgres(4,iatom) 1006 intgres(2:nspden,iatom)=intgres(2:nspden,iatom)-spinat_normed(1:3)*intgres_proj 1007 else if(nspden==2)then 1008 !The direction must be correct, collinear, so no change. 1009 intgden_delta(2,iatom)=zero 1010 endif 1011 else if( mod(conkind,10)==3 )then 1012 !Fix the amplitude of the magnetization vector 1013 intgden_norm = sqrt(sum(intgden(2:nspden,iatom)**2)) 1014 intgden_delta(2:nspden,iatom)=(one-norm/intgden_norm)*intgden(2:nspden,iatom) 1015 else if( mod(conkind,10)==4 )then 1016 !Fix the direction of the magnetization vector 1017 if(nspden==4)then 1018 spinat_normed(:) = c_dft%spinat(:,iatom) / norm 1019 intgden_norm = sqrt(sum(intgden(2:nspden,iatom)**2)) 1020 intgden_normed(:) = intgden(2:nspden,iatom)/intgden_norm 1021 !Calculate the difference vector between the actual magnetization vectoro, times the scalar product between the 1022 !directions of present magnetization and target one, and the target magnetization direction renormalized by the magnetization length. 1023 !See notes 12 October 2021 1024 !DEBUG First possibility 1025 ! intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)-spinat_normed(1:3)*intgden_norm 1026 !ENDDEBUG 1027 !DEBUG Second possibility 1028 scprod=sum(spinat_normed(:)*intgden_normed(:)) 1029 intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom)*scprod-spinat_normed(1:3)*intgden_norm 1030 !ENDDEBUG 1031 !Also projects the residual. There might be some misalignement of the intgden_delta with the correct space of allowed variations 1032 !(not exactly perpendicular to spinat_normed or intgden_normed, or even frankly not at all perpendicular), 1033 !but when close to fulfilling the constraint, this difference becomes negligible. 1034 !The present choice, couple with the above definition of intgden_delta aligns both. 1035 !DEBUG First possibility 1036 intgres_proj=intgden_normed(1)*intgres(2,iatom)+ & 1037 & intgden_normed(2)*intgres(3,iatom)+ & 1038 & intgden_normed(3)*intgres(4,iatom) 1039 intgres(2:nspden,iatom)=intgres(2:nspden,iatom)-intgden_normed(1:3)*intgres_proj 1040 !ENDDEBUG 1041 !DEBUG Second possibility 1042 ! intgres_proj=spinat_normed(1)*intgres(2,iatom)+ & 1043 !& spinat_normed(2)*intgres(3,iatom)+ & 1044 !& spinat_normed(3)*intgres(4,iatom) 1045 ! intgres(2:nspden,iatom)=intgres(2:nspden,iatom)-spinat_normed(1:3)*intgres_proj 1046 !ENDDEBUG 1047 else if(nspden==2)then 1048 !This case is ill-defined ... What follows is rather arbitrary. 1049 !When the actual magnetization and the target magnetization have same sign, the intgden_delta is zero. 1050 ! Otherwise, intgres is set to the difference between the present intgden and the target 1051 intgden_delta(2,iatom)=zero 1052 if(c_dft%spinat(2,iatom)*intgden(2,iatom)<-tol10)intgden_delta(2,iatom)=c_dft%spinat(2,iatom)-intgden(2,iatom) 1053 endif 1054 endif 1055 else 1056 !In this case (norm of constraint vanishes), we set the atomic magnetization to zero. 1057 intgden_delta(2:nspden,iatom)=intgden(2:nspden,iatom) 1058 endif 1059 end if 1060 ! Lagrange energy contribution. Note that intgres is the derivative with respect to the chrgat and spinat constraints, 1061 ! because chrgat and spinat have directly been used in the definition of intgden_delta. 1062 ! WOOPS : chrgat comes with a POSITIVE sign in intgden_delta ?!?! 1063 e_constrained_dft=e_constrained_dft-sum(intgden_delta(:,iatom)*intgres(:,iatom)) 1064 do ii=1,3 1065 grcondft(ii,iatom)=grcondft(ii,iatom)-sum(gr_intgden(ii,:,iatom)*intgres(:,iatom)) 1066 enddo 1067 ! For the stress, this is the place where the summation over atoms is performed. 1068 do ii=1,6 1069 strscondft(ii)=strscondft(ii)-sum(strs_intgden(ii,:,iatom)*intgres(:,iatom)) 1070 enddo 1071 1072 !DEBUG 1073 ! write(6,*)' calcdenmagsph/constrained_residual, line 1058 : iatom=',iatom 1074 ! write(6,*)' e_constrained_dft,intgden_delta(:,iatom),intgres(:,iatom)=',e_constrained_dft,intgden_delta(:,iatom),intgres(:,iatom) 1075 ! write(6,*)' grcondft(1,iatom),gr_intgden(1,:,iatom),intgres(:,iatom)=',grcondft(1,iatom),gr_intgden(1,:,iatom),intgres(:,iatom) 1076 ! write(6,*)' strscondft(1),strs_intgden(1,:,iatom),intgres(:,iatom)=',strscondft(1),strs_intgden(1,:,iatom),intgres(:,iatom) 1077 ! call flush(6) 1078 ! stop 1079 !ENDDEBUG 1080 1081 enddo 1082 1083 ABI_FREE(gr_intgden) 1084 ABI_FREE(strs_intgden) 1085 1086 ABI_MALLOC(coeffs_constr_dft,(nspden,natom)) 1087 coeffs_constr_dft=zero 1088 1089 !With the delta of the integrated density and the atomic residual, compute the atomic correction to be applied to the potential 1090 !See the Eqs.(31), (33) and (34) of notes. 1091 do iatom=1,natom 1092 1093 !Computation of the correction in terms of density and magnetization coefficients. 1094 conkind=c_dft%constraint_kind(c_dft%typat(iatom)) 1095 corr_denmag(:)=zero 1096 1097 if(conkind >=10)then 1098 corr_denmag(1)=intgden_delta(1,iatom)*c_dft%magcon_lambda - intgres(1,iatom) 1099 endif 1100 1101 if( mod(conkind,10)==1 .and. nspden>1)then 1102 1103 !Fix the different components of the magnetization vector 1104 if(nspden==2)corr_denmag(2)=intgden_delta(2,iatom)*c_dft%magcon_lambda - intgres(2,iatom) 1105 if(nspden==4)corr_denmag(2:4)=intgden_delta(2:4,iatom)*c_dft%magcon_lambda - intgres(2:4,iatom) 1106 1107 else if( ( mod(conkind,10)>=2 .and. mod(conkind,10)<=4) .and. nspden>1)then 1108 1109 norm = sqrt(sum(c_dft%spinat(:,iatom)**2)) 1110 if (norm > tol10) then 1111 1112 if( mod(conkind,10)==2 .or. mod(conkind,10)==4)then 1113 !Fix the axis/direction of the magnetization vector 1114 if(nspden==4 .or. mod(conkind,10)==4)then 1115 corr_denmag(2:nspden)=intgden_delta(2:nspden,iatom)*c_dft%magcon_lambda -intgres(2:nspden,iatom) 1116 else if(nspden==2 .and. mod(conkind,10)==2)then 1117 !The direction must be correct, collinear, so no change. 1118 corr_denmag(2)=zero 1119 endif 1120 1121 else if( mod(conkind,10)==3 )then 1122 1123 !Fix the amplitude of the magnetization vector 1124 !This is a special case, one does not work (at present) with the intgden_delta, while one should ... 1125 intgden(2:nspden,iatom)=intgden(2:nspden,iatom) - intgres(2:nspden,iatom)/c_dft%magcon_lambda 1126 intgden_norm = sqrt(sum(intgden(2:nspden,iatom)**2)) 1127 corr_denmag(2:nspden)=(one-norm/intgden_norm)*intgden(2:nspden,iatom) 1128 corr_denmag(2:nspden)=corr_denmag(2:nspden)*c_dft%magcon_lambda 1129 1130 endif 1131 1132 else 1133 !In this case, we set the atomic magnetization to zero. 1134 corr_denmag(2:nspden)=intgden_delta(2:nspden,iatom)*c_dft%magcon_lambda - intgres(2,iatom) 1135 endif 1136 1137 end if 1138 1139 !Convert from density/magnetization constraint residual to actual coefficient that will multiply the spherical function for the potential 1140 if(nspden==1)then 1141 !From charge to potential 1142 coeffs_constr_dft(1,iatom)=corr_denmag(1) 1143 else if(nspden==2 .or. nspden==4)then 1144 !From charge and magnetization to potential 1145 coeffs_constr_dft(1,iatom)=corr_denmag(1)+corr_denmag(nspden) 1146 coeffs_constr_dft(2,iatom)=corr_denmag(1)-corr_denmag(nspden) 1147 if(nspden==4)then 1148 coeffs_constr_dft(3,iatom)= corr_denmag(2) 1149 coeffs_constr_dft(4,iatom)=-corr_denmag(3) 1150 endif 1151 endif 1152 1153 enddo 1154 1155 !Now compute the new residual, by adding the spherical functions 1156 option=1 1157 call add_atomic_fcts(natom,nspden,c_dft%rprimd,mpi_enreg,nfftf,c_dft%ngfftf,ntypat,option,& 1158 & c_dft%ratsph,c_dft%ratsm,c_dft%typat,coeffs_constr_dft,vresid,xred) ! Ben change: add ratsm 1159 1160 ABI_FREE(coeffs_constr_dft) 1161 ABI_FREE(intgden) 1162 ABI_FREE(intgden_delta) 1163 ABI_FREE(intgr) 1164 1165 end subroutine constrained_residual
m_dens/dens_hirsh [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
dens_hirsh
FUNCTION
Compute the Hirshfeld charges
INPUTS
mpoint=Maximum number of points in radial meshes. radii(mpoint, ntypat)=Radial meshes for each type aeden(mpoint, nytpat)=All-electron densities. npoint(ntypat)=The number of the last point with significant density is stored in npoint(itypat) minimal_den=Tolerance on the minum value of the density grid_den(nrx,nry,nrz)= density on the grid natom = number of atoms in the unit cell nrx,nry,nrz= number of points in the grid for the three directions ntypat=number of types of atoms in unit cell. rprimd(3,3)=dimensional primitive translations in real space (bohr) typat(natom)=type of each atom xcart(3,natom) = different positions of the atoms in the unit cell zion=(ntypat)gives the ionic charge for each type of atom prtcharge=1 to write the Hirshfeld charge decomposition
OUTPUT
hcharge(natom), hden(natom), hweight(natom)= Hirshfeld charges, densities, weights.
SOURCE
150 subroutine dens_hirsh(mpoint,radii,aeden,npoint,minimal_den,grid_den, & 151 natom,nrx,nry,nrz,ntypat,rprimd,xcart,typat,zion,prtcharge,hcharge,hden,hweight) 152 153 !Arguments ------------------------------------ 154 !scalars 155 integer,intent(in) :: natom,nrx,nry,nrz,ntypat,prtcharge,mpoint 156 real(dp),intent(in) :: minimal_den 157 !arrays 158 integer,intent(in) :: typat(natom),npoint(ntypat) 159 real(dp),intent(in) :: grid_den(nrx,nry,nrz),rprimd(3,3),zion(ntypat) 160 real(dp),intent(in) :: xcart(3,natom) 161 real(dp),intent(in) :: radii(mpoint,ntypat),aeden(mpoint,ntypat) 162 real(dp),intent(out) :: hcharge(natom),hden(natom),hweight(natom) 163 164 !Local variables ------------------------- 165 !scalars 166 integer :: i1,i2,i3,iatom,icell,igrid,ii,inmax,inmin,istep,itypat 167 integer :: k1,k2,k3,mcells,nfftot,ngoodpoints,npt 168 real(dp) :: aa,bb,coeff1,coeff2,coeff3,den,factor,h_inv,hh,maxrad 169 real(dp) :: rr,rr2,total_charge,total_weight,total_zion,ucvol 170 real(dp) :: yp1,ypn 171 !arrays 172 integer :: highest(3),lowest(3) 173 integer,allocatable :: ncells(:) 174 real(dp) :: coordat(3),coord23_1,coord23_2,coord23_3,diff1,diff2,diff3,gmet(3,3),gprimd(3,3),rmet(3,3) 175 real(dp) :: vperp(3),width(3) 176 real(dp),allocatable :: coord1(:,:),local_den(:,:,:,:) 177 real(dp),allocatable :: step(:,:),sum_den(:,:,:) 178 real(dp),allocatable :: xcartcells(:,:,:),xred(:,:),yder2(:) 179 180 ! ********************************************************************* 181 182 !1. Read the 1D all-electron atomic files 183 !Store the radii in radii(:,itypat), and the all-electron 184 !densities in aeden(:,itypat). The number of the last 185 !point with significant density is stored in npoint(itypat) 186 187 !2. Compute the list of atoms that are sufficiently close to the cell 188 189 call metric(gmet,gprimd,-1,rmet,rprimd,ucvol) 190 nfftot=nrx*nry*nrz 191 192 ABI_MALLOC(xred,(3,natom)) 193 call xcart2xred(natom,rprimd,xcart,xred) 194 195 !Compute the widths of the cell 196 !First width : perpendicular vector length 197 vperp(:)=rprimd(:,1)-rprimd(:,2)*rmet(1,2)/rmet(2,2) -rprimd(:,3)*rmet(1,3)/rmet(3,3) 198 width(1)=sqrt(dot_product(vperp,vperp)) 199 !Second width 200 vperp(:)=rprimd(:,2)-rprimd(:,1)*rmet(2,1)/rmet(1,1) -rprimd(:,3)*rmet(2,3)/rmet(3,3) 201 width(2)=sqrt(dot_product(vperp,vperp)) 202 !Third width 203 vperp(:)=rprimd(:,3)-rprimd(:,1)*rmet(3,1)/rmet(1,1) -rprimd(:,2)*rmet(3,2)/rmet(2,2) 204 width(3)=sqrt(dot_product(vperp,vperp)) 205 206 !Compute the number of cells that will make up the supercell 207 ABI_MALLOC(ncells,(natom)) 208 mcells=0 209 do iatom=1,natom 210 itypat=typat(iatom) 211 maxrad=radii(npoint(itypat),itypat) 212 ! Compute the lower and higher indices of the supercell 213 ! for this atom 214 do ii=1,3 215 lowest(ii)=floor(-xred(ii,iatom)-maxrad/width(ii)) 216 highest(ii)=ceiling(-xred(ii,iatom)+maxrad/width(ii)+1) 217 ! Next coding, still incorrect 218 ! lowest(ii)=floor(xred(ii,iatom)-maxrad/width(ii))-1 219 ! highest(ii)=ceiling(xred(ii,iatom)+maxrad/width(ii))+1 220 ! Old coding incorrect 221 ! lowest(ii)=ceiling(-xred(ii,iatom)-maxrad/width(ii)) 222 ! highest(ii)=floor(-xred(ii,iatom)+maxrad/width(ii)+1) 223 end do 224 ncells(iatom)=(highest(1)-lowest(1)+1)* & 225 & (highest(2)-lowest(2)+1)* & 226 & (highest(3)-lowest(3)+1) 227 ! DEBUG 228 ! write(std_out,*)' maxrad=',maxrad 229 ! write(std_out,*)' lowest(:)=',lowest(:) 230 ! write(std_out,*)' highest(:)=',highest(:) 231 ! write(std_out,*)' ncells(iatom)=',ncells(iatom) 232 ! ENDDEBUG 233 end do 234 mcells=maxval(ncells(:)) 235 236 !Compute, for each atom, the set of image atoms in the whole supercell 237 ABI_MALLOC(xcartcells,(3,mcells,natom)) 238 do iatom=1,natom 239 itypat=typat(iatom) 240 maxrad=radii(npoint(itypat),itypat) 241 ! Compute the lower and higher indices of the supercell 242 ! for this atom 243 244 do ii=1,3 245 lowest(ii)=floor(-xred(ii,iatom)-maxrad/width(ii)) 246 highest(ii)=ceiling(-xred(ii,iatom)+maxrad/width(ii)+1) 247 end do 248 icell=0 249 do i1=lowest(1),highest(1) 250 do i2=lowest(2),highest(2) 251 do i3=lowest(3),highest(3) 252 icell=icell+1 253 xcartcells(:,icell,iatom)=xcart(:,iatom)+i1*rprimd(:,1)+i2*rprimd(:,2)+i3*rprimd(:,3) 254 end do 255 end do 256 end do 257 end do 258 259 !Compute, for each atom, the all-electron pro-atom density 260 !at each point in the primitive cell 261 ABI_MALLOC(local_den,(nrx,nry,nrz,natom)) 262 ABI_MALLOC(step,(2,mpoint)) 263 ABI_MALLOC(yder2,(mpoint)) 264 ABI_MALLOC(coord1,(3,nrx)) 265 coeff1=one/nrx 266 coeff2=one/nry 267 coeff3=one/nrz 268 269 do iatom=1,natom 270 itypat=typat(iatom) 271 npt=npoint(itypat) 272 maxrad=radii(npt,itypat) 273 ! write(std_out,*) 274 ! write(std_out,'(a,i4)' )' hirsh : accumulating density for atom ',iatom 275 ! write(std_out,*)' ncells(iatom)=',ncells(iatom) 276 do istep=1,npt-1 277 step(1,istep)=radii(istep+1,itypat) - radii(istep,itypat) 278 step(2,istep)=one/step(1,istep) 279 end do 280 ! Approximate first derivative for small radii 281 yp1=(aeden(2,itypat)-aeden(1,itypat))/(radii(2,itypat)-radii(1,itypat)) 282 ypn=zero 283 call spline(radii(1:npt,itypat),aeden(1:npt,itypat),npt,yp1,ypn,yder2) 284 285 local_den(:,:,:,iatom)=zero 286 287 ! Big loop on the cells 288 do icell=1,ncells(iatom) 289 ! write(std_out,*)' icell=',icell 290 coordat(:)=xcartcells(:,icell,iatom) 291 292 ! Big loop on the grid points 293 do k1 = 1,nrx 294 coord1(:,k1)=rprimd(:,1)*(k1-1)*coeff1 295 end do 296 do k3 = 1, nrz 297 do k2 = 1, nry 298 coord23_1=rprimd(1,2)*(k2-1)*coeff2+rprimd(1,3)*(k3-1)*coeff3-coordat(1) 299 coord23_2=rprimd(2,2)*(k2-1)*coeff2+rprimd(2,3)*(k3-1)*coeff3-coordat(2) 300 coord23_3=rprimd(3,2)*(k2-1)*coeff2+rprimd(3,3)*(k3-1)*coeff3-coordat(3) 301 do k1 = 1, nrx 302 diff1=coord1(1,k1)+coord23_1 303 diff2=coord1(2,k1)+coord23_2 304 diff3=coord1(3,k1)+coord23_3 305 rr2=diff1**2+diff2**2+diff3**2 306 if(rr2<maxrad**2)then 307 308 rr=sqrt(rr2) 309 ! Find the index of the radius by bissection 310 if (rr < radii(1,itypat)) then 311 ! Linear extrapolation 312 den=aeden(1,itypat)+(rr-radii(1,itypat))/(radii(2,itypat)-radii(1,itypat))& 313 & *(aeden(2,itypat)-aeden(1,itypat)) 314 else 315 ! Use the spline interpolation 316 ! Find the index of the radius by bissection 317 inmin=1 318 inmax=npt 319 igrid=1 320 do 321 if(inmax-inmin==1)exit 322 igrid=(inmin+inmax)/2 323 if(rr>=radii(igrid,itypat))then 324 inmin=igrid 325 else 326 inmax=igrid 327 end if 328 end do 329 igrid=inmin 330 ! write(std_out,*)' igrid',igrid 331 332 hh=step(1,igrid) 333 h_inv=step(2,igrid) 334 aa= (radii(igrid+1,itypat)-rr)*h_inv 335 bb= (rr-radii(igrid,itypat))*h_inv 336 den = aa*aeden(igrid,itypat) + bb*aeden(igrid+1,itypat) & 337 & +( (aa*aa*aa-aa)*yder2(igrid) & 338 & +(bb*bb*bb-bb)*yder2(igrid+1) ) *hh*hh*sixth 339 end if ! Select small radius or spline 340 341 local_den(k1,k2,k3,iatom)=local_den(k1,k2,k3,iatom)+den 342 end if ! dist2<maxrad 343 344 end do ! k1 345 end do ! k2 346 end do ! k3 347 348 end do ! icell 349 end do ! iatom 350 351 !Compute, the total all-electron density at each point in the primitive cell 352 ABI_MALLOC(sum_den,(nrx,nry,nrz)) 353 sum_den(:,:,:)=zero 354 do iatom=1,natom 355 sum_den(:,:,:)=sum_den(:,:,:)+local_den(:,:,:,iatom) 356 end do 357 358 !Accumulate the integral of the density, to get Hirshfeld charges 359 !There is a minus sign because the electron has a negative charge 360 ngoodpoints = 0 361 hcharge(:)=zero 362 hweight(:)=zero 363 do k3=1,nrz 364 do k2=1,nry 365 do k1=1,nrx 366 ! Use minimal_den in order to avoid divide by zero 367 if (abs(sum_den(k1,k2,k3)) > minimal_den) then 368 ngoodpoints = ngoodpoints+1 369 factor=grid_den(k1,k2,k3)/(sum_den(k1,k2,k3)+minimal_den) 370 do iatom=1,natom 371 hden(iatom)=hden(iatom)+local_den(k1,k2,k3,iatom) 372 hcharge(iatom)=hcharge(iatom)-local_den(k1,k2,k3,iatom)*factor 373 hweight(iatom)=hweight(iatom)+local_den(k1,k2,k3,iatom)/(sum_den(k1,k2,k3)+minimal_den) 374 end do 375 end if 376 end do 377 end do 378 end do 379 380 !DEBUG 381 !do iatom=1,natom 382 !write(std_out,'(i9,3es17.6)' )iatom,hden(iatom),hcharge(iatom),hweight(iatom) 383 !end do 384 !ENDDEBUG 385 386 hcharge(:)=hcharge(:)*ucvol/dble(nfftot) 387 hweight(:)=hweight(:)/dble(nfftot) 388 389 !Check on the total charge 390 total_zion=sum(zion(typat(1:natom))) 391 total_charge=sum(hcharge(1:natom)) 392 total_weight=sum(hweight(1:natom)) 393 394 !DEBUG 395 !write(std_out,*)' ngoodpoints = ', ngoodpoints, ' out of ', nfftot 396 !write(std_out,*)' total_weight=',total_weight 397 !write(std_out,*)' total_weight=',total_weight 398 !ENDDEBUG 399 400 !Output 401 if (prtcharge == 1) then 402 write(std_out,*) 403 write(std_out,*)' Hirshfeld analysis' 404 write(std_out,*)' Atom Zion Electron Charge Net charge ' 405 write(std_out,*) 406 do iatom=1,natom 407 write(std_out,'(i9,3es17.6)' )& 408 & iatom,zion(typat(iatom)),hcharge(iatom),hcharge(iatom)+zion(typat(iatom)) 409 end do 410 write(std_out,*) 411 write(std_out,'(a,3es17.6)')' Total',total_zion,total_charge,total_charge+total_zion 412 write(std_out,*) 413 end if 414 415 ABI_FREE(coord1) 416 ABI_FREE(local_den) 417 ABI_FREE(ncells) 418 ABI_FREE(step) 419 ABI_FREE(sum_den) 420 ABI_FREE(xcartcells) 421 ABI_FREE(xred) 422 ABI_FREE(yder2) 423 424 end subroutine dens_hirsh
m_dens/mag_penalty [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
mag_penalty
FUNCTION
This routine is called to compute the potential corresponding to constrained magnetic moments using the penalty function algorithm.
INPUTS
c_dft <type(constrained_dft_t)>=datastructure for the information related to constrained DFT ! magconon=constraining option (on/off); 1=fix only the direction, 2=fix the direction and size ! magcon_lambda=strength of the atomic spherical constraint ! natom=number of atoms ! nfftf=number of points in fine fft grid ! ngfftf=FFT grid dimensions ! nspden = number of spin densities (1 2 or 4) ! ntypat=number of types of atoms ! ratsm=smearing width for ratsph ! ratsph(ntypat)=radii for muffin tin spheres of each atom ! rprimd=lattice vectors (dimensioned) ! spinat(3,natom)=magnetic moments vectors, possible targets according to the value of constraint_kind ! typat(natom)=types of atoms mpi_enreg=mpi structure with communicator info rhor=density in real space xred=reduced atomic positions
OUTPUT
nv_constr_dft_r=the constrained potential
NOTES
based on html notes for the VASP implementation at http://cms.mpi.univie.ac.at/vasp/vasp/Constraining_direction_magnetic_moments.html
SOURCE
1202 subroutine mag_penalty(c_dft,mpi_enreg,rhor,nv_constr_dft_r,xred) 1203 1204 !Arguments ------------------------------------ 1205 !scalars 1206 type(constrained_dft_t),intent(in) :: c_dft 1207 real(dp),intent(out) :: nv_constr_dft_r(c_dft%nfftf,c_dft%nspden) 1208 type(MPI_type),intent(in) :: mpi_enreg 1209 !arrays 1210 real(dp),intent(in) :: rhor(c_dft%nfftf,c_dft%nspden) 1211 real(dp),intent(in) :: xred(3,c_dft%natom) 1212 1213 !Local variables------------------------------- 1214 !scalars 1215 integer :: iatom,magconon,natom,nfftf,nspden,ntypat,option 1216 integer :: cplex1=1 1217 real(dp):: cmm_x,cmm_y,cmm_z 1218 real(dp) :: intgden_proj,norm 1219 !arrays 1220 real(dp), allocatable :: coeffs_constr_dft(:,:) ! nspden,natom 1221 real(dp), allocatable :: intgden(:,:) ! nspden,natom 1222 real(dp) :: rhomag(2,c_dft%nspden),spinat_normed(3) 1223 1224 ! *********************************************************************************************** 1225 1226 magconon=c_dft%magconon 1227 natom=c_dft%natom 1228 nfftf=c_dft%nfftf 1229 nspden=c_dft%nspden 1230 ntypat=c_dft%ntypat 1231 1232 ABI_MALLOC(coeffs_constr_dft,(nspden,natom)) 1233 ABI_MALLOC(intgden,(nspden,natom)) 1234 1235 !We need the integrated magnetic moments and the smoothing function 1236 call calcdenmagsph(mpi_enreg,natom,nfftf,c_dft%ngfftf,nspden,ntypat,& 1237 & c_dft%ratsm,c_dft%ratsph,rhor,c_dft%rprimd,c_dft%typat,xred,1,cplex1,intgden=intgden,rhomag=rhomag) 1238 call prtdenmagsph(cplex1,intgden,natom,nspden,ntypat,std_out,1,c_dft%ratsm,c_dft%ratsph,rhomag,c_dft%typat) 1239 1240 !Loop over atoms 1241 !------------------------------------------- 1242 do iatom=1,natom 1243 1244 norm = sqrt(sum(c_dft%spinat(:,iatom)**2)) 1245 spinat_normed(:) = zero 1246 if (norm > tol10) then 1247 spinat_normed(:) = c_dft%spinat(:,iatom) / norm 1248 else if (magconon == 1) then 1249 ! if spinat = 0 and we are imposing the direction only, skip this atom 1250 cycle 1251 end if 1252 1253 ! Calculate the x- and y-components of the square bracket term 1254 cmm_x = zero 1255 cmm_y = zero 1256 cmm_z = zero 1257 intgden_proj = zero 1258 if (nspden == 4) then 1259 if (magconon==1) then 1260 ! Calculate the scalar product of the fixed mag. mom. vector and calculated mag. mom. vector 1261 ! This is actually the size of the projection of the calc. mag. mom. vector on the fixed mag. mom. vector 1262 intgden_proj=spinat_normed(1)*intgden(2,iatom)+ & 1263 & spinat_normed(2)*intgden(3,iatom)+ & 1264 & spinat_normed(3)*intgden(4,iatom) 1265 1266 cmm_x=intgden(2,iatom) 1267 cmm_x=cmm_x-spinat_normed(1)*intgden_proj 1268 1269 cmm_y=intgden(3,iatom) 1270 cmm_y=cmm_y-spinat_normed(2)*intgden_proj 1271 1272 else if (magconon==2 .and. nspden == 4) then 1273 cmm_x=intgden(2,iatom)-c_dft%spinat(1,iatom) 1274 cmm_y=intgden(3,iatom)-c_dft%spinat(2,iatom) 1275 end if 1276 1277 ! Calculate the constraining potential for x- and y- components of the mag. mom. vector 1278 ! Eric Bousquet has derived the relationship between spin components and potential spin matrix elements: 1279 ! 1 = up up = +z 1280 ! 2 = down down = -z 1281 ! 3 = up down = +x 1282 ! 4 = down up = -y 1283 coeffs_constr_dft(3,iatom)= 2*c_dft%magcon_lambda*cmm_x 1284 coeffs_constr_dft(4,iatom)=-2*c_dft%magcon_lambda*cmm_y 1285 end if ! nspden 4 1286 1287 ! Calculate the z-component of the square bracket term 1288 if (magconon==1) then 1289 if (nspden == 4) then 1290 ! This apparently enforces the axis of magnetization, not its direction. 1291 ! m_z - spinat_z * <m | spinat> 1292 cmm_z = intgden(4,iatom) - spinat_normed(3)*intgden_proj 1293 else if (nspden == 2) then 1294 ! This apparently enforces the direction of the magnetization. So, the behaviour differs in nspden=4 and 2 cases . 1295 ! this will be just a sign +/- : are we in the same direction as spinat_z? 1296 ! need something more continuous??? To make sure the gradient pushes the state towards FM/AFM? 1297 cmm_z = -sign(one, (intgden(1,iatom)-intgden(2,iatom))*spinat_normed(3)) 1298 end if 1299 else if (magconon==2) then 1300 if (nspden == 4) then 1301 cmm_z=intgden(4,iatom)-c_dft%spinat(3,iatom) 1302 else if (nspden == 2) then 1303 ! this is up spins - down spins - requested moment ~ 0 1304 ! EB: note that intgden comes from calcdenmagsph, which, in nspden=2 case, returns 1305 ! intgden(1)=rho_up=n+m 1306 ! intgden(2)=rho_dn=n-m 1307 ! Then, is the following line be 1308 ! cmm_z=half*(intgden(1,iatom)-intgden(2,iatom)) - spinat(3,iatom) 1309 ! ?? 1310 cmm_z=intgden(1,iatom)-intgden(2,iatom) - c_dft%spinat(3,iatom) 1311 end if 1312 endif 1313 1314 ! Calculate the constraining potential for z-component of the mag. mom. vector 1315 coeffs_constr_dft(1,iatom)= 2*c_dft%magcon_lambda*cmm_z 1316 coeffs_constr_dft(2,iatom)=-2*c_dft%magcon_lambda*cmm_z 1317 1318 enddo ! iatom 1319 1320 !Now compute the potential in real space 1321 option=0 1322 call add_atomic_fcts(natom,nspden,c_dft%rprimd,mpi_enreg,nfftf,c_dft%ngfftf,ntypat,option,c_dft%ratsph, & 1323 c_dft%ratsm,c_dft%typat,coeffs_constr_dft,nv_constr_dft_r,xred) ! Ben change: add ratsm 1324 1325 ABI_FREE(coeffs_constr_dft) 1326 ABI_FREE(intgden) 1327 1328 end subroutine mag_penalty
m_dens/mag_penalty_e [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
mag_penalty_e
FUNCTION
Compute the energy corresponding to constrained magnetic moments.
INPUTS
magconon=constraining option (on/off); 1=fix only the direction, 2=fix the direction and size spinat=fixed magnetic moments vectors magcon_lambda=the size of the penalty terms
OUTPUT
Epen=penalty contribution to the total energy corresponding to the constrained potential Econstr=??? Eexp=???
SOURCE
1351 subroutine mag_penalty_e(magconon,magcon_lambda,mpi_enreg,natom,nfft,ngfft,nspden,ntypat,ratsm,ratsph,rhor,rprimd,spinat,typat,xred) 1352 1353 !Arguments ------------------------------------ 1354 !scalars 1355 integer,intent(in) :: natom,magconon,nspden,nfft,ntypat 1356 real(dp),intent(in) :: magcon_lambda,ratsm 1357 !arrays 1358 integer, intent(in) :: ngfft(18),typat(natom) 1359 real(dp),intent(in) :: spinat(3,natom), rprimd(3,3) 1360 real(dp),intent(in) :: ratsph(ntypat),rhor(nfft,nspden),xred(3,natom) 1361 type(MPI_type),intent(in) :: mpi_enreg 1362 1363 !Local variables------------------------------- 1364 !scalars 1365 integer :: iatom,ii 1366 integer :: cplex1=1 ! dummy argument for calcdenmagsph 1367 real(dp) :: intgden_proj, Epen,Econstr,lVp, norm 1368 !arrays 1369 real(dp) :: intmm(3), mag_1atom(3) 1370 real(dp), allocatable :: intgden(:,:) 1371 real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3),ucvol 1372 real(dp) :: rhomag(2,nspden),spinat_normed(3) 1373 character(len=500) :: msg 1374 1375 ! ********************************************************************* 1376 1377 !We need the metric because it is needed in calcdenmagsph.F90 1378 call metric(gmet,gprimd,-1,rmet,rprimd,ucvol) 1379 1380 ABI_MALLOC(intgden, (nspden,natom)) 1381 1382 !We need the integrated magnetic moments 1383 cplex1=1 1384 call calcdenmagsph(mpi_enreg,natom,nfft,ngfft,nspden,ntypat,ratsm,ratsph,rhor,rprimd,typat,xred,& 1385 & 1,cplex1,intgden=intgden,rhomag=rhomag) 1386 call prtdenmagsph(cplex1,intgden,natom,nspden,ntypat,std_out,1,ratsm,ratsph,rhomag,typat) 1387 1388 Epen=0 1389 Econstr=0 1390 lVp=0 1391 1392 !Loop over atoms 1393 !------------------------------------------- 1394 do iatom=1,natom 1395 1396 norm = sqrt(sum(spinat(:,iatom)**2)) 1397 spinat_normed(:) = zero 1398 if (norm > tol10) then 1399 spinat_normed(:) = spinat(:,iatom) / norm 1400 else if (magconon == 1) then 1401 ! if spinat = 0 and we are imposing the direction only, skip this atom 1402 cycle 1403 end if 1404 ! Calculate the scalar product of the fixed mag. mom. vector and calculated mag. mom. vector 1405 ! This is actually the size of the projection of the calc. mag. mom. vector on the fixed mag. mom. vector 1406 1407 ! for the collinear spin case, set up a fictitious 3D vector along z 1408 if (nspden == 4) then 1409 mag_1atom(1:3) = intgden(2:4,iatom) 1410 else if (nspden == 2) then 1411 mag_1atom = zero 1412 mag_1atom(3) = intgden(1,iatom)-intgden(2,iatom) 1413 end if 1414 1415 intgden_proj = zero 1416 intmm = zero 1417 ! Calculate the square bracket term 1418 if (magconon==1) then 1419 intgden_proj=spinat_normed(1)*mag_1atom(1)+ & 1420 & spinat_normed(2)*mag_1atom(2)+ & 1421 & spinat_normed(3)*mag_1atom(3) 1422 1423 do ii=1,3 1424 intmm(ii)=mag_1atom(ii)-spinat_normed(ii)*intgden_proj 1425 end do 1426 1427 ! Calculate the energy Epen corresponding to the constraining potential 1428 ! Econstr and lVp do not have a clear meaning (yet) 1429 Epen=Epen+magcon_lambda*(intmm(1)*intmm(1)+intmm(2)*intmm(2)+intmm(3)*intmm(3)) 1430 Econstr=Econstr-magcon_lambda*(intmm(1)*mag_1atom(1)+intmm(2)*mag_1atom(2)+intmm(3)*mag_1atom(3)) 1431 lVp=lVp+2*magcon_lambda*(intmm(1)*mag_1atom(1)+intmm(2)*mag_1atom(2)+intmm(3)*mag_1atom(3)) 1432 1433 else if (magconon==2) then 1434 do ii=1,3 1435 intmm(ii)=mag_1atom(ii)-spinat(ii,iatom) 1436 end do 1437 1438 ! Calculate the energy Epen corresponding to the constraining potential 1439 ! Epen = -Econstr - lVp 1440 ! Econstr = -M**2 + spinat**2 1441 ! lVp = +2 M \cdot spinat 1442 Epen=Epen+magcon_lambda*(intmm(1)*intmm(1)+intmm(2)*intmm(2)+intmm(3)*intmm(3)) 1443 Econstr=Econstr-magcon_lambda*(mag_1atom(1)*mag_1atom(1)+& 1444 & mag_1atom(2)*mag_1atom(2)+& 1445 & mag_1atom(3)*mag_1atom(3)) & 1446 & +magcon_lambda*(spinat(1,iatom)*spinat(1,iatom)+& 1447 & spinat(2,iatom)*spinat(2,iatom)+& 1448 & spinat(3,iatom)*spinat(3,iatom)) 1449 lVp=lVp+2*magcon_lambda*(intmm(1)*mag_1atom(1)+intmm(2)*mag_1atom(2)+intmm(3)*mag_1atom(3)) 1450 end if 1451 1452 write(msg, *) 'atom constraining magnetic field' 1453 call wrtout(std_out,msg,'COLL') 1454 write(msg, '(I3,A2,E12.5,A2,E12.5,A2,E12.5)') & 1455 iatom,' ',magcon_lambda*intmm(1),' ',magcon_lambda*intmm(2),' ',magcon_lambda*intmm(3) 1456 call wrtout(std_out,msg,'COLL') 1457 1458 ! End loop over atoms 1459 ! ------------------------------------------- 1460 end do 1461 1462 !Printing 1463 write(msg, '(A17,E10.3)' ) ' magcon_lambda = ',magcon_lambda 1464 call wrtout(std_out,msg,'COLL') 1465 write(msg, '(A17,E12.5)' ) ' Lagrange penalty = ',Epen 1466 call wrtout(std_out,msg,'COLL') 1467 write(msg, '(A17,E12.5)' ) ' E_constraint = ',Econstr 1468 call wrtout(std_out,msg,'COLL') 1469 write(msg, '(A17,E12.5)' ) ' lVp = ',lVp 1470 call wrtout(std_out,msg,'COLL') 1471 1472 ABI_FREE(intgden) 1473 1474 end subroutine mag_penalty_e
m_dens/prtdenmagsph [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
prtdenmagsph
FUNCTION
Print integral of total density inside spheres around atoms, and optionally integral of potential residual (also gradient of the constraint energy wrt constraint).
INPUTS
intgden(nspden, natom)=integrated rhor or potential residual, for each atom in a sphere of radius ratsph. if option <10, intgden is a density (+magnetization) Representation differs according to nspden : if nspden=1, total density if nspden=2, spin up, then spin down if nspden=4, total density, then mag_x, mag_y, mag_z if 20>option>=10, intgden is a potential residual (+spin magnetic field residual). Representation is: first, mean potential; then (if nspden>=2) B_z for nspden=2, B_x, B_y and B_z for nspden=4. if option>=20, intgden is a a gradient wrt target (=torque), also potential residual (+spin magnetic field residual) multiplied by f-1. natom=number of atoms in cell. nspden=number of spin-density components ntypat=number of atom types nunit=number of the unit for printing 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.. When 1, 11, 21, the default printing is on (to unit nunit), if -1, 2, 3, 4, special printing options, if 0 no printing. ratsm=smearing width for ratsph ratsph(ntypat)=radius of spheres around atoms rhomag(2,nspden)=integral of charge or magnetization over the whole cell (also taking into account a possible imaginary part for DFPT). typat(natom)=type of each atom ziontypat(ntypat)= --optional-- ionic charge of each atomic type
OUTPUT
Printing
SOURCE
1956 subroutine prtdenmagsph(cplex,intgden,natom,nspden,ntypat,nunit,option,ratsm,ratsph,rhomag,typat,ziontypat) 1957 1958 !Arguments --------------------------------------------- 1959 !scalars 1960 integer,intent(in) :: natom,nspden,ntypat,nunit 1961 real(dp),intent(in) :: ratsm 1962 integer ,intent(in) :: option 1963 integer, intent(in) :: cplex 1964 !arrays 1965 integer,intent(in) :: typat(natom) 1966 real(dp),intent(in) :: intgden(nspden,natom) 1967 real(dp),intent(in) :: ratsph(ntypat),rhomag(2,nspden) 1968 real(dp),intent(in),optional :: ziontypat(ntypat) 1969 !Local variables ------------------------------ 1970 !scalars 1971 integer :: iatom,ix 1972 real(dp) :: mag_coll , mag_x, mag_y, mag_z ! EB 1973 real(dp) :: mag_coll_im, mag_x_im, mag_y_im, mag_z_im ! SPr 1974 real(dp) :: rho_tot, rho_tot_im 1975 real(dp) :: sum_mag, sum_mag_x,sum_mag_y,sum_mag_z,sum_rho_up,sum_rho_dn,sum_rho_tot ! EB 1976 character(len=500) :: msg,msg1 1977 1978 ! ************************************************************************* 1979 1980 !DEBUG 1981 !write(ab_out,*)' prtdenmagsph : enter, rhomag(1,2)=',rhomag(1,2) 1982 !ENDDEBUG 1983 1984 if(nspden==2)then 1985 rho_tot=rhomag(1,1) ; mag_coll=rhomag(1,2) 1986 if(cplex==2)then 1987 rho_tot_im=rhomag(2,1) ; mag_coll_im=rhomag(2,2) 1988 endif 1989 else if(nspden==4)then 1990 rho_tot=rhomag(1,1) ; mag_x=rhomag(1,2) ; mag_y=rhomag(1,3) ; mag_z=rhomag(1,4) 1991 if(cplex==2)then 1992 rho_tot_im=rhomag(2,1) ; mag_x_im=rhomag(2,2) ; mag_y_im=rhomag(2,3) ; mag_z_im=rhomag(2,4) 1993 endif 1994 endif 1995 1996 if(option/=0)then 1997 1998 !Printing 1999 sum_mag=zero 2000 sum_mag_x=zero 2001 sum_mag_y=zero 2002 sum_mag_z=zero 2003 sum_rho_up=zero 2004 sum_rho_dn=zero 2005 sum_rho_tot=zero 2006 2007 if(option==1 .or. option==11 .or. option==21) then 2008 2009 if(nspden==1) then 2010 if(option== 1)msg1=' Integrated electronic density in atomic spheres:' 2011 if(option==11)msg1=ch10//' Integrated potential residual in atomic spheres:' 2012 if(option==21)msg1=ch10//' Gradient with respect to target (=torque) :' 2013 write(msg, '(3a)' ) trim(msg1),ch10,' ------------------------------------------------' 2014 call wrtout(nunit,msg,'COLL') 2015 if(ratsm>tol8)then 2016 write(msg, '(a,f8.4,a)' ) ' Radius=ratsph(iatom), smearing ratsm=',ratsm,'.' 2017 call wrtout(nunit,msg,'COLL') 2018 endif 2019 if(option== 1)then 2020 msg=' Atom Sphere_radius Integrated_density' 2021 if(present(ziontypat)) write(msg,'(a,a)')trim(msg),' Atomic charge' 2022 endif 2023 if(option==11)msg=' Atom Sphere_radius Integrated_potresid' 2024 if(option==21)msg=' Atom Sphere_radius Torque' 2025 call wrtout(nunit,msg,'COLL') 2026 do iatom=1,natom 2027 write(msg, '(i5,f15.5,f20.8)' ) iatom,ratsph(typat(iatom)),intgden(1,iatom) 2028 if(option==21)then 2029 ! There is a change of sign to get the gradient wrt chrgat. 2030 write(msg, '(i5,f15.5,f20.8)' ) iatom,ratsph(typat(iatom)),-intgden(1,iatom) 2031 endif 2032 !If option=1, print atomic charge 2033 if(option==1 .and. present(ziontypat))then 2034 write(msg, '(a,f20.8)' ) trim(msg),ziontypat(typat(iatom))-intgden(1,iatom) 2035 endif 2036 call wrtout(nunit,msg,'COLL') 2037 end do 2038 endif 2039 2040 if(nspden==2 .or. nspden==4) then 2041 2042 if(option== 1)msg1=' Integrated electronic and magnetization densities in atomic spheres:' 2043 if(option==11)msg1=ch10//' Integrated potential residual in atomic spheres (scalar + magnetic field):' 2044 if(option==21)msg1=ch10//' Gradient with respect to target (=torque) (scalar + magnetic field):' 2045 write(msg, '(3a)' ) trim(msg1),ch10,' ---------------------------------------------------------------------' 2046 call wrtout(nunit,msg,'COLL') 2047 2048 if(option== 1 .and. nspden==2) msg1='. Diff(up-dn)=approximate z local magnetic moment.' 2049 if(option== 1 .and. nspden==4) msg1='. mag(i)=approximate local magnetic moment.' 2050 if(option==11 .or. option==21) msg1='.' 2051 write(msg, '(a,f8.4,a)' ) ' Radius=ratsph(iatom), smearing ratsm=',ratsm,trim(msg1) 2052 call wrtout(nunit,msg,'COLL') 2053 2054 if(option==1)then 2055 if(nspden==2) msg=' Atom Radius up_density dn_density Total(up+dn) Diff(up-dn)' 2056 if(nspden==4) msg=' Atom Radius Total density mag(x) mag(y) mag(z) ' 2057 if(present(ziontypat))msg=trim(msg)//' Atomic charge' 2058 else if(option==11)then 2059 if(nspden==2) msg=' Atom Radius Potential B(z) up pot down pot' 2060 if(nspden==4) msg=' Atom Radius Potential B(x) B(y) B(z) ' 2061 else if(option==21)then 2062 if(nspden==2) msg=' Atom Radius grchrg T(z) up torque down torque' 2063 if(nspden==4) msg=' Atom Radius Torque T(x) T(y) T(z) ' 2064 endif 2065 call wrtout(nunit,msg,'COLL') 2066 2067 endif 2068 2069 if(nspden==2)then 2070 do iatom=1,natom 2071 if(option/=21)then 2072 write(msg,'(i5,f10.5,2f13.6,a,f12.6,a,f12.6)' ) iatom,ratsph(typat(iatom)),intgden(1,iatom),intgden(2,iatom) 2073 else 2074 write(msg,'(i5,f10.5,2f13.6,a,f12.6,a,f12.6)' ) iatom,ratsph(typat(iatom)),-intgden(1,iatom),intgden(2,iatom) 2075 endif 2076 write(msg,'(a,a,f12.6,a,f12.6)')trim(msg),' ',(intgden(1,iatom)+intgden(2,iatom)),' ',(intgden(1,iatom)-intgden(2,iatom)) 2077 if(option==1 .and. present(ziontypat))& 2078 & write(msg, '(a,f14.6)') trim(msg),ziontypat(typat(iatom))-(intgden(1,iatom)+intgden(2,iatom)) 2079 call wrtout(nunit,msg,'COLL') 2080 ! Compute the sum of the magnetization 2081 sum_mag=sum_mag+intgden(1,iatom)-intgden(2,iatom) 2082 sum_rho_up=sum_rho_up+intgden(1,iatom) 2083 sum_rho_dn=sum_rho_dn+intgden(2,iatom) 2084 sum_rho_tot=sum_rho_tot+intgden(1,iatom)+intgden(2,iatom) 2085 end do 2086 write(msg, '(a)') ' ---------------------------------------------------------------------' 2087 call wrtout(nunit,msg,'COLL') 2088 write(msg, '(a,2f13.6,a,f12.6,a,f12.6)') ' Sum: ', sum_rho_up,sum_rho_dn,' ',sum_rho_tot,' ',sum_mag 2089 call wrtout(nunit,msg,'COLL') 2090 2091 if(option==1)then 2092 write(msg, '(a,f14.6)') ' Total magnetization (from the atomic spheres): ', sum_mag 2093 call wrtout(nunit,msg,'COLL') 2094 write(msg, '(a,f14.6)') ' Total magnetization (exact up - dn): ', mag_coll 2095 call wrtout(nunit,msg,'COLL') 2096 endif 2097 2098 elseif(nspden==4) then 2099 2100 do iatom=1,natom 2101 if(option/=21)then 2102 write(msg, '(i5,f10.5,f16.6,a,3f12.6)' ) iatom,ratsph(typat(iatom)),intgden(1,iatom),' ',(intgden(ix,iatom),ix=2,4) 2103 else 2104 write(msg, '(i5,f10.5,f16.6,a,3f12.6)' ) iatom,ratsph(typat(iatom)),-intgden(1,iatom),' ',(intgden(ix,iatom),ix=2,4) 2105 endif 2106 if(option==1 .and. present(ziontypat))& 2107 & write(msg, '(a,f14.6)') trim(msg),ziontypat(typat(iatom))-intgden(1,iatom) 2108 call wrtout(nunit,msg,'COLL') 2109 ! Compute the sum of the magnetization in x, y and z directions 2110 sum_mag_x=sum_mag_x+intgden(2,iatom) 2111 sum_mag_y=sum_mag_y+intgden(3,iatom) 2112 sum_mag_z=sum_mag_z+intgden(4,iatom) 2113 end do 2114 write(msg, '(a)') ' ---------------------------------------------------------------------' 2115 call wrtout(nunit,msg,'COLL') 2116 2117 if(option==1)then 2118 write(msg, '(a,f12.6,f12.6,f12.6)') ' Total magnetization (spheres) ', sum_mag_x,sum_mag_y,sum_mag_z 2119 call wrtout(nunit,msg,'COLL') 2120 write(msg, '(a,f12.6,f12.6,f12.6)') ' Total magnetization (exact) ', mag_x,mag_y,mag_z 2121 call wrtout(nunit,msg,'COLL') 2122 endif 2123 2124 end if 2125 2126 elseif(option==-1) then 2127 2128 write(msg, '(2a)') ch10,' ------------------------------------------------------------------------' 2129 call wrtout(nunit,msg,'COLL') 2130 2131 if(nspden==1) then 2132 write(msg, '(4a)' ) & 2133 & ' Fermi level charge density n_f:',ch10,& 2134 & ' ------------------------------------------------------------------------',ch10 2135 else 2136 write(msg, '(4a)' ) & 2137 & ' Fermi level charge density n_f and magnetization m_f:',ch10,& 2138 & ' ------------------------------------------------------------------------',ch10 2139 end if 2140 call wrtout(nunit,msg,'COLL') 2141 2142 if(cplex==1) then 2143 write(msg, '(a,f13.8)') ' n_f = ',rho_tot 2144 else 2145 write(msg, '(a,f13.8,a,f13.8)') ' Re[n_f]= ', rho_tot," Im[n_f]= ",rho_tot_im 2146 end if 2147 call wrtout(nunit,msg,'COLL') 2148 if(nspden==2) then 2149 if(cplex==1) then 2150 write(msg, '(a,f13.8)') ' m_f = ', mag_coll 2151 else 2152 write(msg, '(a,f13.8,a,f13.8)') ' Re[m_f]= ', mag_coll," Im[m_f]= ",mag_coll_im 2153 end if 2154 call wrtout(nunit,msg,'COLL') 2155 elseif (nspden==4) then 2156 write(msg, '(a,f13.8)') ' mx_f = ',mag_x 2157 call wrtout(nunit,msg,'COLL') 2158 write(msg, '(a,f13.8)') ' my_f = ',mag_y 2159 call wrtout(nunit,msg,'COLL') 2160 write(msg, '(a,f13.8)') ' mz_f = ',mag_z 2161 call wrtout(nunit,msg,'COLL') 2162 end if 2163 2164 write(msg, '(3a)') ch10,' ------------------------------------------------------------------------',ch10 2165 call wrtout(nunit,msg,'COLL') 2166 2167 2168 else if (option==2 .or. option==3 .or. option==4) then 2169 ! Used in the DFPT case, option=idir+1 2170 2171 if(abs(rho_tot)<1.0d-10) then 2172 rho_tot=0 2173 end if 2174 2175 write(msg, '(2a)') ch10,' ------------------------------------------------------------------------' 2176 call wrtout(nunit,msg,'COLL') 2177 2178 if(nspden==1) then 2179 write(msg, '(4a)' ) & 2180 & ' Integral of the first order density n^(1):',ch10,& 2181 & ' ------------------------------------------------------------------------',ch10 2182 else 2183 write(msg, '(4a)' ) & 2184 & ' Integrals of the first order density n^(1) and magnetization m^(1):',ch10,& 2185 & ' ------------------------------------------------------------------------',ch10 2186 end if 2187 call wrtout(nunit,msg,'COLL') 2188 2189 if(cplex==1) then 2190 write(msg, '(a,e16.8)') ' n^(1) = ', rho_tot 2191 else 2192 write(msg, '(a,e16.8,a,e16.8)') ' Re[n^(1)] = ', rho_tot," Im[n^(1)] = ",rho_tot_im 2193 end if 2194 call wrtout(nunit,msg,'COLL') 2195 2196 if(nspden==2) then 2197 2198 if(cplex==1) then 2199 write(msg, '(a,e16.8)') ' m^(1) = ', mag_coll 2200 else 2201 write(msg, '(a,e16.8,a,e16.8)') ' Re[m^(1)] = ', mag_coll," Im[m^(1)] = ",mag_coll_im 2202 end if 2203 call wrtout(nunit,msg,'COLL') 2204 2205 elseif (nspden==4) then 2206 if(cplex==1) then 2207 write(msg, '(a,e16.8)') ' mx^(1) = ', mag_x 2208 call wrtout(nunit,msg,'COLL') 2209 write(msg, '(a,e16.8)') ' my^(1) = ', mag_y 2210 call wrtout(nunit,msg,'COLL') 2211 write(msg, '(a,e16.8)') ' mz^(1) = ', mag_z 2212 call wrtout(nunit,msg,'COLL') 2213 else 2214 write(msg, '(a,e16.8,a,e16.8)') ' Re[mx^(1)]= ', mag_x, " Im[mx^(1)]= ", mag_x_im 2215 call wrtout(nunit,msg,'COLL') 2216 write(msg, '(a,e16.8,a,e16.8)') ' Re[my^(1)]= ', mag_y, " Im[my^(1)]= ", mag_y_im 2217 call wrtout(nunit,msg,'COLL') 2218 write(msg, '(a,e16.8,a,e16.8)') ' Re[mz^(1)]= ', mag_z, " Im[mz^(1)]= ", mag_z_im 2219 call wrtout(nunit,msg,'COLL') 2220 end if 2221 end if 2222 2223 write(msg, '(3a)') ch10,' ------------------------------------------------------------------------',ch10 2224 call wrtout(nunit,msg,'COLL') 2225 2226 end if 2227 2228 end if ! option/=0 2229 2230 end subroutine prtdenmagsph
m_dens/radsmear [ Functions ]
[ Top ] [ m_dens ] [ Functions ]
NAME
radsmear
FUNCTION
As a function of the argument xarg (a positive number), return a function fsm that is zero beyond some cut-off value xcut, one for xarg smaller than xcut-xsmear, and interpolates smoothly between one and zero in the region from xcut-xsmear to xcut. Also returns the derivative of this function, called dfsm. The function fsm is twice differentiable at xcut (the first derivative is continuous, not the second), and three times differentiable at xcut-xsmear (the second derivative is continuous, not the third).
INPUTS
xarg=argument of the function (should be positive) xcut=largest value for which the function is non-zero xsmear=defined the smearing region, between xcut-xsmear and xcut
OUTPUT
fsm=value of the function dfsm=derivative of the function with respect to xarg (zero, except in the smearing region).
SOURCE
2257 subroutine radsmear(dfsm,fsm,xarg,xcut,xsmear) 2258 2259 !Arguments ------------------------------------ 2260 !scalars 2261 real(dp), intent(out) :: dfsm,fsm 2262 real(dp), intent(in) :: xarg, xcut, xsmear 2263 2264 !Local variables ------------------------------ 2265 !scalars 2266 real(dp) :: xsmearinv,xx 2267 2268 !****************************************************************** 2269 2270 fsm = zero 2271 dfsm=zero 2272 if (xarg < xcut - xsmear - tol12) then 2273 fsm = one 2274 else if (xarg < xcut - tol12) then 2275 xsmearinv=one/xsmear 2276 xx = (xcut - xarg) * xsmearinv 2277 fsm = xx**2*(3+xx*(1+xx*(-6+3*xx))) 2278 dfsm = -(xx*(6+xx*(3+xx*(-24+15*xx))))*xsmearinv 2279 end if 2280 2281 end subroutine radsmear