Line data Source code
1 : !!****m* ABINIT/m_rttddft_properties
2 : !! NAME
3 : !! m_rttddft_properties
4 : !!
5 : !! FUNCTION
6 : !! Contains most of the subroutines to compute
7 : !! properties (energy, occupations, eigenvalues..)
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2021-2026 ABINIT group (FB)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : module m_rttddft_properties
24 :
25 : use defs_basis
26 : use defs_abitypes, only: MPI_type
27 : use defs_datatypes, only: pseudopotential_type
28 :
29 : use m_bandfft_kpt, only: bandfft_kpt_type
30 : use m_cgprj, only: ctocprj
31 : use m_cgtools, only: dotprod_g
32 : use m_dtfil, only: datafiles_type
33 : use m_dtset, only: dataset_type
34 : use m_energies, only: energies_type
35 : use m_fourier_interpol, only: transgrid
36 : use m_hamiltonian, only: gs_hamiltonian_type
37 : use m_mkrho, only: mkrho
38 : use m_nonlop, only: nonlop
39 : use m_pawcprj, only: pawcprj_type, pawcprj_alloc, pawcprj_get, &
40 : & pawcprj_free, pawcprj_mpi_allgather
41 : use m_paw_optics, only: optics_paw
42 : use m_paw_mkrho, only: pawmkrho
43 : use m_paw_occupancies, only: pawmkrhoij
44 : use m_pawrhoij, only: pawrhoij_type, pawrhoij_free, &
45 : & pawrhoij_alloc, pawrhoij_inquire_dim
46 : use m_profiling_abi, only: abimem_record
47 : use m_rttddft_tdks, only: tdks_type
48 : use m_spacepar, only: meanvalue_g
49 : use m_xmpi, only: xmpi_sum, xmpi_comm_rank
50 : use m_dft_energy, only: entropy
51 :
52 : implicit none
53 :
54 : private
55 : !!***
56 :
57 : public :: rttddft_calc_density
58 : public :: rttddft_calc_etot
59 : public :: rttddft_calc_eig
60 : public :: rttddft_calc_enl
61 : public :: rttddft_calc_kin
62 : public :: rttddft_calc_occ
63 : public :: rttddft_calc_current
64 : !!***
65 :
66 : contains
67 : !!***
68 :
69 : !!****f* m_rttddft_properties/rttddft_calc_density
70 : !!
71 : !! NAME
72 : !! rttddft_calc_density
73 : !!
74 : !! FUNCTION
75 : !! Compute electronic density (in 1/bohr^3) from the WF (cg coefficients)
76 : !!
77 : !! INPUTS
78 : !! dtset <type(dataset_type)> = all input variables for this dataset
79 : !! mpi_enreg <MPI_type> = MPI-parallelisation information
80 : !! psps <type(pseudopotential_type)> = variables related to pseudopotentials
81 : !! tdks <type(tdks_type)> = Main RT-TDDFT object
82 : !!
83 : !! OUTPUT
84 : !!
85 : !! SOURCE
86 1417 : subroutine rttddft_calc_density(dtset, mpi_enreg, psps, tdks)
87 :
88 : !Arguments ------------------------------------
89 : !scalars
90 : type(tdks_type), intent(inout) :: tdks
91 : type(dataset_type), intent(in) :: dtset
92 : type(MPI_type), intent(inout) :: mpi_enreg
93 : type(pseudopotential_type), intent(in) :: psps
94 :
95 : !Local variables-------------------------------
96 : !scalars
97 : integer, parameter :: cplex=1
98 : integer :: cplex_rhoij
99 : integer :: ipert, idir
100 : integer :: my_natom
101 : integer :: nspden_rhoij
102 : integer :: tim_mkrho
103 : real(dp) :: compch_fft
104 : !arrays
105 : real(dp) :: qpt(3)
106 1417 : real(dp),allocatable :: rhowfg(:,:), rhowfr(:,:)
107 1417 : type(pawrhoij_type),pointer :: pawrhoij_unsym(:)
108 : logical :: printout
109 :
110 : ! ***********************************************************************
111 :
112 1417 : my_natom=mpi_enreg%my_natom
113 :
114 1417 : tim_mkrho=1
115 :
116 1417 : printout = (dtset%prtvol /= 0)
117 :
118 1417 : if (psps%usepaw==1) then
119 :
120 3561 : ABI_MALLOC(rhowfg,(2,dtset%nfft))
121 4748 : ABI_MALLOC(rhowfr,(dtset%nfft,dtset%nspden))
122 :
123 : ! 1-Compute density from WFs (without compensation charge density nhat)
124 : call mkrho(tdks%cg,dtset,tdks%gprimd,tdks%irrzon,tdks%kg,tdks%mcg,mpi_enreg, &
125 : & tdks%npwarr,tdks%occ0,tdks%paw_dmft,tdks%phnons,rhowfg,rhowfr, &
126 : & tdks%rprimd,tim_mkrho,tdks%ucvol,tdks%wvl%den,tdks%wvl%wfs, &
127 1187 : & printout=printout)
128 :
129 : ! 2-Compute cprj = <\psi_{n,k}|p_{i,j}>
130 : call ctocprj(tdks%atindx,tdks%cg,1,tdks%cprj,tdks%gmet,tdks%gprimd,0,0,0, &
131 : & dtset%istwfk,tdks%kg,tdks%tdef%kpa,tdks%mcg,tdks%mcprj,dtset%mgfft, &
132 : & dtset%mkmem,mpi_enreg,psps%mpsang,dtset%mpw,dtset%natom,tdks%nattyp, &
133 : & dtset%nband,dtset%natom,dtset%ngfft,dtset%nkpt,dtset%nloalg, &
134 : & tdks%npwarr,dtset%nspinor,dtset%nsppol,dtset%nsppol,psps%ntypat, &
135 : & dtset%paral_kgb,tdks%ph1d,psps,tdks%rmet,dtset%typat,tdks%ucvol, &
136 1187 : & tdks%unpaw,tdks%xred,tdks%ylm,tdks%ylmgr)
137 :
138 : !paral atom
139 1187 : if (my_natom/=dtset%natom) then
140 0 : ABI_MALLOC(pawrhoij_unsym,(dtset%natom))
141 : call pawrhoij_inquire_dim(cplex_rhoij=cplex_rhoij,nspden_rhoij=nspden_rhoij, &
142 : & nspden=dtset%nspden,spnorb=dtset%pawspnorb, &
143 0 : & cpxocc=dtset%pawcpxocc)
144 : call pawrhoij_alloc(pawrhoij_unsym,cplex_rhoij,nspden_rhoij,dtset%nspinor, &
145 0 : & dtset%nsppol,dtset%typat,pawtab=tdks%pawtab,use_rhoijp=0)
146 : else
147 1187 : pawrhoij_unsym => tdks%pawrhoij
148 : end if
149 :
150 : ! 3-Compute pawrhoij = \rho_{i,j} = \sum_{n,k}f_{n,k} \tilde{c}^{i,*}_{n,k} \tilde{c}^{j}_{n,k}
151 : call pawmkrhoij(tdks%atindx,tdks%atindx1,tdks%cprj,tdks%dimcprj_srt,dtset%istwfk, &
152 : & dtset%kptopt,dtset%mband,tdks%mband_cprj,tdks%mcprj,dtset%mkmem, &
153 : & mpi_enreg,dtset%natom,dtset%nband,dtset%nkpt,dtset%nspden, &
154 : & dtset%nspinor,dtset%nsppol,tdks%occ0,dtset%paral_kgb,tdks%paw_dmft, &
155 1187 : & pawrhoij_unsym,tdks%unpaw,dtset%usewvl,dtset%wtk)
156 :
157 : ! 4-Symetrize rhoij, compute nhat and add it to rhor
158 : ! Note pawrhoij_unsym and pawrhoij are the same, which means that pawrhoij
159 : ! cannot be distributed over different atomic sites.
160 1187 : ipert=0; idir=0; qpt(:)=zero; compch_fft=-1e-5_dp
161 17014939 : tdks%nhat = zero
162 : call pawmkrho(1,compch_fft,cplex,tdks%gprimd,idir,tdks%indsym,ipert,mpi_enreg, &
163 : & my_natom,dtset%natom,dtset%nspden,dtset%nsym,dtset%ntypat, &
164 : & dtset%paral_kgb,tdks%pawang,tdks%pawfgr,tdks%pawfgrtab, &
165 : & dtset%pawprtvol,tdks%pawrhoij,pawrhoij_unsym,tdks%pawtab,qpt, &
166 : & rhowfg,rhowfr,tdks%rhor,tdks%rprimd,dtset%symafm,tdks%symrec, &
167 : & dtset%typat,tdks%ucvol,dtset%usewvl,tdks%xred,pawnhat=tdks%nhat, &
168 1187 : & rhog=tdks%rhog)
169 :
170 : ! 5-Take care of kinetic energy density
171 1187 : if(dtset%usekden==1)then
172 : call mkrho(tdks%cg,dtset,tdks%gprimd,tdks%irrzon,tdks%kg,tdks%mcg,mpi_enreg, &
173 : & tdks%npwarr,tdks%occ0,tdks%paw_dmft,tdks%phnons,rhowfg,rhowfr, &
174 0 : & tdks%rprimd,tim_mkrho,tdks%ucvol,tdks%wvl%den,tdks%wvl%wfs,option=1)
175 :
176 : !FB: Useful?
177 : call transgrid(1,mpi_enreg,dtset%nspden,+1,1,1,dtset%paral_kgb,tdks%pawfgr, &
178 0 : & rhowfg,tdks%taug,rhowfr,tdks%taur)
179 : end if
180 :
181 1187 : ABI_FREE(rhowfg)
182 1187 : ABI_FREE(rhowfr)
183 :
184 1187 : if (my_natom/=dtset%natom) then
185 0 : call pawrhoij_free(pawrhoij_unsym)
186 0 : ABI_FREE(pawrhoij_unsym)
187 : else
188 : pawrhoij_unsym => NULL()
189 : end if
190 :
191 : else
192 :
193 : ! 1-Compute density from WFs
194 : call mkrho(tdks%cg,dtset,tdks%gprimd,tdks%irrzon,tdks%kg,tdks%mcg,mpi_enreg, &
195 : & tdks%npwarr,tdks%occ0,tdks%paw_dmft,tdks%phnons,tdks%rhog,tdks%rhor, &
196 230 : & tdks%rprimd,tim_mkrho,tdks%ucvol,tdks%wvl%den,tdks%wvl%wfs)
197 : ! 2-Take care of kinetic energy density
198 230 : if(dtset%usekden==1)then
199 : call mkrho(tdks%cg,dtset,tdks%gprimd,tdks%irrzon,tdks%kg,tdks%mcg,mpi_enreg, &
200 : & tdks%npwarr,tdks%occ0,tdks%paw_dmft,tdks%phnons,tdks%taug,tdks%taur, &
201 0 : & tdks%rprimd,tim_mkrho,tdks%ucvol,tdks%wvl%den,tdks%wvl%wfs,option=1)
202 : end if
203 :
204 : endif
205 :
206 1417 : end subroutine rttddft_calc_density
207 : !!***
208 :
209 : !!****f* m_rttddft_properties/rttddft_calc_etot
210 : !!
211 : !! NAME
212 : !! rttddft_calc_energy
213 : !!
214 : !! FUNCTION
215 : !! Computes total energy
216 : !!
217 : !! INPUTS
218 : !! dtset <type(dataset_type)> = all input variables for this dataset
219 : !! energies <energies_type> = contains the different contribution ot the total energy
220 : !! occ <real(nband*nkpt*nsspol)> = occupation numbers at time t
221 : !!
222 : !! OUTPUT
223 : !! etotal <real(dp)> = the total energy
224 : !!
225 : !! SOURCE
226 1341 : subroutine rttddft_calc_etot(dtset, energies, etotal, occ)
227 :
228 : !Arguments ------------------------------------
229 : !scalars
230 : type(dataset_type), intent(in) :: dtset
231 : type(energies_type), intent(inout) :: energies
232 : real(dp), intent(out) :: etotal
233 : !arrays
234 : real(dp), intent(in) :: occ(:)
235 :
236 : ! ***********************************************************************
237 :
238 : ! Compute electronic entropy
239 1341 : call rttddft_calc_ent(energies%entropy_ks, dtset, occ)
240 :
241 1341 : call entropy(dtset,energies)
242 :
243 : etotal = energies%e_kinetic &
244 : & + energies%e_hartree &
245 : & + energies%e_xc &
246 : & + energies%e_localpsp &
247 : & + energies%e_corepsp &
248 : & + energies%e_ewald &
249 : & + energies%e_vdw_dftd &
250 : & + energies%e_nlpsp_vfock &
251 1341 : & + energies%paw%epaw
252 : ! & + energies%e_entropy
253 : !FB: @MT Should one add the last e_paw contribution or not?
254 : !FB: Seeems like all the other contributions are not relevant here @MT?
255 : ! & + energies%e_chempot &
256 : ! & + energies%e_elecfield &
257 : ! & + energies%e_magfield &
258 : ! & + energies%e_nucdip &
259 : ! & + energies%e_hybcomp_E0 &
260 : ! & - energies%e_hybcomp_v0 &
261 : ! & + energies%e_hybcomp_v &
262 : ! & + energies%e_constrained_dft
263 :
264 : !if (psps%usepaw==0) etotal = etotal + energies%e_nlpsp_vfock - energies%e_fock0
265 : !if (psps%usepaw==1) etotal = etotal + energies%e_paw + energies%e_fock
266 :
267 1341 : end subroutine rttddft_calc_etot
268 : !!***
269 :
270 : !!****f* m_rttddft_properties/rttddft_calc_eig
271 : !!
272 : !! NAME
273 : !! rttddft_calc_eig
274 : !!
275 : !! FUNCTION
276 : !! Computes eigenvalues from cg and ghc = <G|H|C>
277 : !! and gsc = <G|S|C> if paw
278 : !!
279 : !! INPUTS
280 : !! cg <real(2,npw*nspinor*nband)> = the wavefunction coefficients
281 : !! ghc <real(2,npw*nspinor*nband)> = <G|H|C>
282 : !! istwf_k <integer> = option describing the storage of wfs at k
283 : !! nband <integer> = number of bands
284 : !! npw <integer> = number of plane waves
285 : !! nspinor <integer> = dimension of spinors
286 : !! me_g0 <integer> = if set to 1 current proc contains G(0,0,0)
287 : !! comm <integer> = MPI communicator
288 : !! gsc <real(2,npw*nspinor*nband)> = <G|S|C> (optional - only in PAW)
289 : !!
290 : !! OUTPUT
291 : !! eig <real(nband)> = the eigenvalues
292 : !!
293 : !! SOURCE
294 0 : subroutine rttddft_calc_eig(cg,eig,ghc,istwf_k,nband,npw,nspinor,me_g0,comm,gsc)
295 :
296 : !Arguments ------------------------------------
297 : !scalars
298 : integer, intent(in) :: istwf_k
299 : integer, intent(in) :: nband
300 : integer, intent(in) :: npw
301 : integer, intent(in) :: nspinor
302 : integer, intent(in) :: me_g0
303 : integer, intent(in) :: comm
304 : !arrays
305 : real(dp), intent(in) :: cg(2,npw*nspinor*nband)
306 : real(dp), intent(out) :: eig(nband)
307 : real(dp), intent(in) :: ghc(2,npw*nspinor*nband)
308 : real(dp), intent(in), optional :: gsc(2,npw*nspinor*nband)
309 :
310 : !Local variables-------------------------------
311 : !scalars
312 : integer :: iband
313 : integer :: shift
314 : real(dp) :: dprod_r, dprod_i
315 : !arrays
316 :
317 : ! ***********************************************************************
318 :
319 0 : do iband=1, nband
320 0 : shift = npw*nspinor*(iband-1)
321 : !Compute eigenvalues
322 : call dotprod_g(eig(iband),dprod_i,istwf_k,npw*nspinor,1, &
323 : & ghc(:, shift+1:shift+npw*nspinor), &
324 : & cg(:, shift+1:shift+npw*nspinor), &
325 0 : & me_g0, comm)
326 0 : if (present(gsc)) then
327 : call dotprod_g(dprod_r,dprod_i,istwf_k,npw*nspinor,1, &
328 : & gsc(:, shift+1:shift+npw*nspinor), &
329 : & cg(:, shift+1:shift+npw*nspinor), &
330 0 : & me_g0, comm)
331 0 : eig(iband) = eig(iband)/dprod_r
332 : end if
333 : end do
334 :
335 0 : end subroutine rttddft_calc_eig
336 : !!***
337 :
338 : !!****f* m_rttddft_properties/rttddft_calc_kin
339 : !!
340 : !! NAME
341 : !! rttddft_calc_kin
342 : !!
343 : !! FUNCTION
344 : !! Computes the NL part of energy in NC case
345 : !!
346 : !! INPUTS
347 : !! cg <real(2,npw*nspinor*nband)> = the wavefunction coefficients
348 : !! dtset <type(dataset_type)> = all input variables for this dataset
349 : !! ham_k <gs_hamiltonian_type> = hamiltonian at point k
350 : !! nband <integer> = number of bands
351 : !! npw <integer> = number of plane waves
352 : !! nspinor <integer> = dimension of spinors
353 : !! occ0 <real(nband)> = initial occupations
354 : !! wk <real> = weight of associated kpt
355 : !! mpi_enreg <MPI_type> = MPI-parallelisation information
356 : !! bandfft_kpt <bandfft_kpt_type> = additional info on parallelisation
357 : !! for the associated kpt
358 : !!
359 : !! OUTPUT
360 : !! kin <real(nband)> = the non local part of the energy in NC case
361 : !!
362 : !! SIDE EFFECTS
363 : !!
364 : !! SOURCE
365 16508 : subroutine rttddft_calc_kin(kin,cg,dtset,ham_k,nband,npw,nspinor,occ0,wk,mpi_enreg,bandfft)
366 :
367 : !Arguments ------------------------------------
368 : !scalars
369 : integer, intent(in) :: nband
370 : integer, intent(in) :: npw
371 : integer, intent(in) :: nspinor
372 : real(dp), intent(in) :: wk
373 : type(dataset_type), intent(in) :: dtset
374 : type(gs_hamiltonian_type), intent(in) :: ham_k
375 : type(MPI_type), intent(in) :: mpi_enreg
376 : type(bandfft_kpt_type), pointer, intent(in) :: bandfft
377 : !arrays
378 : real(dp), intent(in) :: cg(2,npw*nspinor*nband)
379 : real(dp), intent(inout) :: kin
380 : real(dp), intent(in) :: occ0(nband)
381 :
382 : !Local variables-------------------------------
383 : !scalars
384 : integer :: displ
385 : integer :: iband, ipw
386 : integer :: jpw
387 : integer :: me_bandfft
388 : integer :: shift
389 : real(dp) :: ar
390 : !arrays
391 :
392 : ! ***********************************************************************
393 :
394 16508 : if (dtset%paral_kgb /= 1) then
395 : displ = 0
396 : else
397 6560 : me_bandfft = xmpi_comm_rank(mpi_enreg%comm_bandspinorfft)
398 6560 : displ = bandfft%rdispls(me_bandfft+1)
399 : end if
400 :
401 159132 : do iband=1, nband
402 159132 : if (abs(occ0(iband))>tol8) then
403 72392 : shift = npw*nspinor*(iband-1)
404 : !FB: meanvalue_g does the mpi_sum over the bands inside, that's not very efficient since
405 : !FB: we could do it only once at the end
406 : !FB: From Lucas: meanvalue_g seems slow
407 : !FB: It maybe useful not to use meanvalue_g at all here
408 : !call meanvalue_g(ar,ham_k%kinpw_k(1+displ:displ+npw*nspinor),0,1,mpi_enreg,npw,nspinor, &
409 : ! & cg(:,1+shift:shift+npw*nspinor),cg(:,1+shift:shift+npw*nspinor),0)
410 72392 : ar = zero
411 12927604 : do ipw = 1, npw
412 12927604 : ar = ar + ham_k%kinpw_k(displ+ipw)*(cg(1,shift+ipw)*cg(1,shift+ipw)+cg(2,shift+ipw)*cg(2,shift+ipw))
413 : end do
414 72392 : if(nspinor==2)then
415 0 : do ipw = 1+npw, 2*npw
416 0 : jpw = ipw - npw
417 0 : ar = ar + ham_k%kinpw_k(displ+jpw)*(cg(1,shift+ipw)*cg(1,shift+ipw)+cg(2,shift+ipw)*cg(2,shift+ipw))
418 : end do
419 : end if
420 72392 : kin = kin + wk*occ0(iband)*ar
421 : end if
422 : end do
423 :
424 16508 : end subroutine rttddft_calc_kin
425 : !!***
426 :
427 : !!****f* m_rttddft_properties/rttddft_calc_enl
428 : !!
429 : !! NAME
430 : !! rttddft_calc_enl
431 : !!
432 : !! FUNCTION
433 : !! Computes the NL part of energy in NC case
434 : !!
435 : !! INPUTS
436 : !! cg <real(2,npw*nspinor*nband)> = the wavefunction coefficients
437 : !! ham_k <gs_hamiltonian_type> = hamiltonian at point k
438 : !! nband <integer> = number of bands
439 : !! npw <integer> = number of plane waves
440 : !! nspinor <integer> = dimension of spinors
441 : !! mpi_enreg <MPI_type> = MPI-parallelisation information
442 : !!
443 : !! OUTPUT
444 : !! enl <real(nband)> = the non local part of the energy in NC case
445 : !!
446 : !! SIDE EFFECTS
447 : !!
448 : !! SOURCE
449 320 : subroutine rttddft_calc_enl(cg,enl,ham_k,nband,npw,nspinor,mpi_enreg)
450 :
451 : !Arguments ------------------------------------
452 : !scalars
453 : integer, intent(in) :: nband
454 : integer, intent(in) :: npw
455 : integer, intent(in) :: nspinor
456 : type(gs_hamiltonian_type), intent(in) :: ham_k
457 : type(MPI_type), intent(in) :: mpi_enreg
458 : !arrays
459 : real(dp), intent(inout) :: cg(2,npw*nspinor*nband)
460 : real(dp), intent(out) :: enl(nband)
461 :
462 : !Local variables-------------------------------
463 : !scalars
464 : integer, parameter :: choice=1
465 : integer, parameter :: cpopt=-1
466 : integer, parameter :: paw_opt=0
467 : integer, parameter :: signs=1
468 : integer, parameter :: tim_getghc = 5
469 : !arrays
470 320 : type(pawcprj_type), allocatable :: cprj_dummy(:,:)
471 320 : real(dp), allocatable :: eig_dummy(:)
472 320 : real(dp), allocatable :: gvnlxc_dummy(:,:)
473 320 : real(dp), allocatable :: gsc_dummy(:,:)
474 : ! ***********************************************************************
475 :
476 640 : ABI_MALLOC(cprj_dummy,(ham_k%natom,0))
477 320 : ABI_MALLOC(gsc_dummy,(0,0))
478 320 : ABI_MALLOC(gvnlxc_dummy, (0, 0))
479 960 : ABI_MALLOC(eig_dummy,(nband))
480 : call nonlop(choice,cpopt,cprj_dummy,enl,ham_k,0,eig_dummy,mpi_enreg,nband, &
481 320 : & 1,paw_opt,signs,gsc_dummy,tim_getghc,cg,gvnlxc_dummy)
482 320 : ABI_FREE(cprj_dummy)
483 320 : ABI_FREE(gsc_dummy)
484 320 : ABI_FREE(eig_dummy)
485 320 : ABI_FREE(gvnlxc_dummy)
486 :
487 320 : end subroutine rttddft_calc_enl
488 : !!***
489 :
490 : !!****f* m_rttddft_properties/rttddft_calc_occ
491 : !!
492 : !! NAME
493 : !! rttddft_calc_occ
494 : !!
495 : !! FUNCTION
496 : !! Computes occupations at time t from cg(t), cg0 and occ0
497 : !! In NC:
498 : !! f_{n,k}(t) = \sum_{m} f_{m,k}(0) <\psi_m(0)|\psi_n(t)>
499 : !! In PAW:
500 : !! f_{n,k}(t) = \sum_{m} f_{m,k}(0) <\psi_m(0)|S|\psi_n(t)>
501 : !! = \sum_{m} f_{m,k}(0) [ <\psi_m(0)|\psi_n(t)> +
502 : !! \sum_{i} <\psi_m(0)|p_{i}>\sum_jS_{i,j}<p_{j}|\psi_n(t)> ]
503 : !!
504 : !! INPUTS
505 : !! cg <real(2,npw*nspinor*nband)> = the wavefunction coefficients
506 : !! cg0 <real(2,npw*nspinor*nband)> = the initial wavefunction coefficients
507 : !! dtset <type(dataset_type)> = all input variables for this dataset
508 : !! ham_k <gs_hamiltonian_type> = hamiltonian at point k
509 : !! ikpt <integer> = indice of the considered k-point
510 : !! ibg <integer> = indice of the considered k-point for cprj
511 : !! isppol <integer> = indice of the considered spin-polarization
512 : !! mpi_enreg <MPI_type> = MPI-parallelisation information
513 : !! nband_k <integer> = number of bands
514 : !! npw_k <integer> = number of plane waves
515 : !! nspinor <integer> = dimension of spinors
516 : !! occ0 <real(nband)> = initial occupations
517 : !! tdks <type(tdks_type)> = Main RT-TDDFT object
518 : !!
519 : !! OUTPUT
520 : !! occ <real(nband)> = the occupations at time t
521 : !!
522 : !! SOURCE
523 16508 : subroutine rttddft_calc_occ(cg,cg0,dtset,ham_k,ikpt,ibg,isppol,mpi_enreg,nband_k,npw_k,nspinor,occ,occ0,tdks)
524 :
525 : !Arguments ------------------------------------
526 : !scalars
527 : integer, intent(in) :: ikpt
528 : integer, intent(in) :: ibg
529 : integer, intent(in) :: isppol
530 : integer, intent(in) :: nband_k
531 : integer, intent(in) :: npw_k
532 : integer, intent(in) :: nspinor
533 : type(dataset_type), intent(in) :: dtset
534 : type(gs_hamiltonian_type), intent(in) :: ham_k
535 : type(MPI_type), intent(in) :: mpi_enreg
536 : type(tdks_type), target, intent(in) :: tdks
537 : !arrays
538 : real(dp), intent(inout) :: cg(2,npw_k*nspinor*nband_k)
539 : real(dp), intent(in) :: cg0(2,npw_k*nspinor*nband_k)
540 : real(dp), intent(out) :: occ(nband_k)
541 : real(dp), intent(in) :: occ0(nband_k)
542 :
543 : !Local variables-------------------------------
544 : !scalars
545 : integer :: iband, jband, ierr, ind
546 : integer :: nband_cprj_k
547 : integer :: natom
548 : integer :: shift
549 : !parameters for nonlop
550 : integer, parameter :: cpopt = 2
551 : integer, parameter :: choice = 1
552 : integer, parameter :: idir = 1
553 : integer, parameter :: nnlout = 1
554 : integer, parameter :: paw_opt = 3
555 : integer, parameter :: signs = 1
556 : integer, parameter :: tim_nonlop = 16
557 : logical :: cprj_paral_band
558 : !arrays
559 33016 : real(dp) :: csc(2*nband_k)
560 16508 : real(dp),allocatable :: gsc(:,:),gvnlxc(:,:)
561 16508 : real(dp),allocatable :: enlout(:),enlout_im(:)
562 16508 : type(pawcprj_type), pointer :: cprj(:,:), cprj_k(:,:)
563 16508 : type(pawcprj_type), pointer :: cprj0(:,:), cprj0_k(:,:)
564 :
565 : ! ***********************************************************************
566 :
567 : !Prepare cprj in PAW case
568 16508 : cprj_paral_band=.false.
569 16508 : if (ham_k%usepaw == 1) then
570 : ! Determine if cprj datastructure is distributed over bands
571 16188 : cprj_paral_band=(tdks%mband_cprj<dtset%mband)
572 16188 : nband_cprj_k=nband_k; if (cprj_paral_band) nband_cprj_k=mpi_enreg%bandpp
573 16188 : natom = dtset%natom
574 : ! Extract the right cprj for this k-point
575 16188 : if (dtset%mkmem*dtset%nsppol/=1) then
576 406224 : ABI_MALLOC(cprj_k,(natom,nspinor*nband_cprj_k))
577 390036 : ABI_MALLOC(cprj0_k,(natom,nspinor*nband_cprj_k))
578 16188 : call pawcprj_alloc(cprj_k,0,tdks%dimcprj)
579 16188 : call pawcprj_alloc(cprj0_k,0,tdks%dimcprj)
580 : call pawcprj_get(tdks%atindx1,cprj_k,tdks%cprj,natom,1,ibg,ikpt,0,isppol, &
581 : & tdks%mband_cprj,dtset%mkmem,natom,nband_cprj_k,nband_cprj_k, &
582 : & nspinor,dtset%nsppol,tdks%unpaw,mpicomm=mpi_enreg%comm_kpt, &
583 16188 : & proc_distrb=mpi_enreg%proc_distrb)
584 : call pawcprj_get(tdks%atindx1,cprj0_k,tdks%cprj0,natom,1,ibg,ikpt,0,isppol, &
585 : & tdks%mband_cprj,dtset%mkmem,natom,nband_cprj_k,nband_cprj_k, &
586 : & nspinor,dtset%nsppol,tdks%unpaw,mpicomm=mpi_enreg%comm_kpt, &
587 16188 : & proc_distrb=mpi_enreg%proc_distrb)
588 : else
589 0 : cprj_k => tdks%cprj
590 0 : cprj0_k => tdks%cprj0
591 : end if
592 : ! If cprj are distributed over bands, gather them (because we need to mix bands)
593 16188 : if (cprj_paral_band) then
594 179200 : ABI_MALLOC(cprj,(natom,nspinor*nband_k))
595 172800 : ABI_MALLOC(cprj0,(natom,nspinor*nband_k))
596 6400 : call pawcprj_alloc(cprj,0,tdks%dimcprj)
597 6400 : call pawcprj_alloc(cprj0,0,tdks%dimcprj)
598 : call pawcprj_mpi_allgather(cprj_k,cprj,natom,nspinor*nband_cprj_k,mpi_enreg%bandpp, &
599 : & tdks%dimcprj,0,mpi_enreg%nproc_band,mpi_enreg%comm_band, &
600 6400 : & ierr,rank_ordered=.false.)
601 : call pawcprj_mpi_allgather(cprj0_k,cprj0,natom,nspinor*nband_cprj_k,mpi_enreg%bandpp, &
602 : & tdks%dimcprj,0,mpi_enreg%nproc_band,mpi_enreg%comm_band, &
603 6400 : & ierr,rank_ordered=.false.)
604 : else
605 9788 : cprj => cprj_k
606 9788 : cprj0 => cprj0_k
607 : end if
608 :
609 : !allocate necessary arrays for nonlop
610 16188 : ABI_MALLOC(gsc,(0,0))
611 16188 : ABI_MALLOC(gvnlxc,(0,0))
612 48564 : ABI_MALLOC(enlout,(nband_k))
613 32376 : ABI_MALLOC(enlout_im,(nband_k))
614 : end if
615 :
616 301756 : csc = zero
617 159132 : do iband = 1, nband_k
618 : !* 1 - Compute csc = <cg0|cg>
619 142624 : shift = npw_k*nspinor*(iband-1)
620 : call zgemv('C',npw_k*nspinor,nband_k,cone,cg0,npw_k*nspinor, &
621 142624 : & cg(:,shift+1:shift+npw_k*nspinor),1,czero,csc,1)
622 : !If band parallel then reduce csc
623 142624 : if (mpi_enreg%nproc_band > 1) then
624 55040 : call xmpi_sum(csc,mpi_enreg%comm_bandfft,ierr)
625 : end if
626 : !* 2 - If PAW, add the additional term \sum_i cprj_i \sum_j S_{i,j} cprj_j
627 142624 : if (ham_k%usepaw == 1) then
628 : call nonlop(choice,cpopt,cprj(:,iband:iband+(nspinor-1)),enlout, &
629 : & ham_k,idir,(/zero/),mpi_enreg,1,nnlout,paw_opt,signs, &
630 : & gsc,tim_nonlop,cg(:,shift+1:shift+npw_k*nspinor),gvnlxc, &
631 134944 : & cprjin_left=cprj0,enlout_im=enlout_im,ndat_left=nband_k)
632 1442976 : do jband = 1, nband_k
633 1308032 : csc(2*jband-1) = csc(2*jband-1) + enlout(jband)
634 1442976 : csc(2*jband) = csc(2*jband) + enlout_im(jband)
635 : end do
636 : end if
637 : !* 3 - Calc occupations from csc and occ0
638 1651484 : do jband = 1, nband_k
639 1492352 : ind = 2*jband
640 1634976 : occ(iband) = occ(iband) + occ0(jband)*(csc(ind-1)**2+csc(ind)**2)
641 : end do
642 : end do
643 :
644 16508 : if (ham_k%usepaw == 1) then
645 16188 : ABI_FREE(gsc)
646 16188 : ABI_FREE(gvnlxc)
647 16188 : ABI_FREE(enlout)
648 16188 : ABI_FREE(enlout_im)
649 16188 : if (cprj_paral_band) then
650 6400 : call pawcprj_free(cprj)
651 6400 : ABI_FREE(cprj)
652 6400 : call pawcprj_free(cprj0)
653 6400 : ABI_FREE(cprj0)
654 : end if
655 16188 : if (dtset%mkmem*dtset%nsppol/=1) then
656 16188 : call pawcprj_free(cprj_k)
657 16188 : ABI_FREE(cprj_k)
658 16188 : call pawcprj_free(cprj0_k)
659 16188 : ABI_FREE(cprj0_k)
660 : end if
661 : end if
662 :
663 33016 : end subroutine rttddft_calc_occ
664 : !!***
665 :
666 : !!****f* m_rttddft_properties/rttddft_calc_ent
667 : !!
668 : !! NAME
669 : !! rttddft_calc_ent
670 : !!
671 : !! FUNCTION
672 : !! Computes electronic entropy from occupation numbers f_{nk}
673 : !! S = -2 \sum_k \sum_n w(k) [ f_{nk}*ln(f_{nk}) + (1-f_{nk})*ln(1-f_{nk}) ]
674 : !!
675 : !! INPUTS
676 : !! dtset <type(dataset_type)> = all input variables for this dataset
677 : !! occ <real(nband*nkpt*nsspol)> = occupation numbers at time t
678 : !!
679 : !! OUTPUT
680 : !! entropy <real>
681 : !!
682 : !! SOURCE
683 1341 : subroutine rttddft_calc_ent(entropy,dtset,occ)
684 :
685 : !Arguments ------------------------------------
686 : !scalars
687 : real(dp), intent(out) :: entropy
688 : type(dataset_type), intent(in) :: dtset
689 : !arrays
690 : real(dp), intent(in) :: occ(:)
691 :
692 : !Local variables-------------------------------
693 : !scalars
694 : integer :: band_index
695 : integer :: iband, isppol, ikpt
696 : integer :: nband_k
697 : real(dp) :: fnk
698 :
699 : ! ***********************************************************************
700 :
701 1341 : entropy = zero
702 1341 : band_index=0
703 :
704 2682 : do isppol = 1, dtset%nsppol
705 38870 : do ikpt = 1, dtset%nkpt
706 36188 : nband_k = dtset%nband(ikpt+(isppol-1)*dtset%nkpt)
707 343932 : do iband = 1, nband_k
708 307744 : fnk = occ(iband+band_index)*0.5_dp
709 343932 : if( fnk>tol16 .and. (one-fnk)>tol16 ) then
710 274073 : entropy = entropy - two*dtset%wtk(ikpt)*(fnk*log(fnk)+(one-fnk)*log(one-fnk))
711 : end if
712 : end do
713 37529 : band_index = band_index + nband_k
714 : end do
715 : end do
716 :
717 1341 : end subroutine rttddft_calc_ent
718 : !!***
719 :
720 : !!****f* m_rttddft_properties/rttddft_calc_current
721 : !!
722 : !! NAME
723 : !! rttddft_calc_current
724 : !!
725 : !! FUNCTION
726 : !! Computes macroscopic current density
727 : !! In NC:
728 : !! J(t) = -1/Omega Im[\sum_{n,k} f_{nk}(0) <\tilde{psi}_{nk}|\nabla|\tilde{psi}_{nk}>] - A N_v/Omega
729 : !! + Gauge-dependent terms?
730 : !! In PAW:
731 : !! J(t) = -1/Omega Im[ \sum_{n,k} f_{nk}(0) <\tilde{psi}_{nk}|\nabla|\tilde{psi}_{nk}> +
732 : !! \sum_{aij} \rho_{aij} <\phi_{aij}|\nabla|\phi_{aij}> -
733 : !! \sum_{aij} \rho_{aij} <\tilde{\phi}_{aij}|\nabla|\tilde{\phi}_{aij}> ]
734 : !! - A/Omega \int \tilde{n}(r,t)dr
735 : !! INPUTS
736 : !! tdks <type(tdks_type)> = Main RT-TDDFT object
737 : !! dtset <type(dataset_type)> = all input variables for this dataset
738 : !! mpi_enreg <MPI_type> = MPI-parallelisation information
739 : !!
740 : !! OUTPUT
741 : !! current = the macroscopic current
742 : !!
743 : !! NOTES
744 : !! Im[<\tilde{psi}_{nk}|\nabla|\tilde{psi}_{nk}>] = <\tilde{psi}_{nk}|-i\nabla|\tilde{psi}_{nk}>
745 : !!
746 : !! SOURCE
747 1121 : subroutine rttddft_calc_current(tdks, dtset, dtfil, psps, mpi_enreg)
748 :
749 : !Arguments ------------------------------------
750 : !scalars
751 : type(tdks_type), target, intent(inout) :: tdks
752 : type(dataset_type), intent(in) :: dtset
753 : type(datafiles_type), intent(in) :: dtfil
754 : type(pseudopotential_type), intent(in) :: psps
755 : type(MPI_type), intent(in) :: mpi_enreg
756 :
757 : !Local variables-------------------------------
758 : !scalars
759 : integer :: iband, ikpt, isppol, bdtot_index, nband_k
760 : real(dp) :: current_k(3)
761 : !arrays
762 2242 : real(dp), target :: psinablapsi(2,3,dtset%mband,dtset%nkpt)
763 :
764 : ! ***********************************************************************
765 :
766 1121 : if (psps%usepaw==1) then
767 : ! 1 - Computes <\psi_{nk}|v|\psi_{nk}> = <\psi_{nk}|-i\nabla|\psi_{nk}> = Im[<\tilde{psi}_{nk}|\nabla|\tilde{psi}_{nk}>]
768 : call optics_paw(tdks%atindx1,tdks%cg,tdks%cprj,tdks%dimcprj,dtfil,dtset,tdks%eigen,tdks%gprimd,tdks%hdr, &
769 : & tdks%kg,dtset%mband,tdks%mcg,tdks%mcprj,dtset%mkmem,mpi_enreg,psps%mpsang,dtset%mpw, &
770 : & dtset%natom,dtset%nkpt,tdks%npwarr,dtset%nsppol,tdks%pawang,tdks%pawrad,tdks%pawrhoij, &
771 1121 : & tdks%pawtab,dtset%znucl,psinablapsi)
772 :
773 : ! 2 - Sum over bands and k-points
774 5605 : tdks%current = 0.0_dp
775 1121 : bdtot_index=0
776 : !Loop over spins
777 2242 : do isppol=1, dtset%nsppol
778 : !Loop over kpoints
779 36993 : do ikpt = 1, dtset%nkpt
780 35872 : current_k = 0.0_dp
781 35872 : nband_k=dtset%nband(ikpt+(isppol-1)*dtset%nkpt)
782 322848 : do iband = 1, nband_k
783 286976 : current_k(1) = current_k(1) + tdks%occ0(bdtot_index+iband)*psinablapsi(1,1,iband,ikpt)
784 286976 : current_k(2) = current_k(2) + tdks%occ0(bdtot_index+iband)*psinablapsi(1,2,iband,ikpt)
785 322848 : current_k(3) = current_k(3) + tdks%occ0(bdtot_index+iband)*psinablapsi(1,3,iband,ikpt)
786 : end do
787 143488 : tdks%current(:,isppol) = tdks%current(:,isppol) + dtset%wtk(ikpt)*current_k(:)
788 36993 : bdtot_index = bdtot_index + nband_k
789 : end do !nkpt
790 :
791 : ! 3 - Add last contribution from vector potential times integral of the density
792 : tdks%current(:,isppol) = tdks%current(:,isppol) + &
793 16092947 : & tdks%tdef%vecpot(:)*sum(tdks%rhor(:,isppol)-tdks%nhat(:,isppol))*tdks%ucvol/tdks%nfftf
794 :
795 5605 : tdks%current(:,isppol) = -tdks%current(:,isppol)/tdks%ucvol
796 :
797 : end do !nsspol
798 :
799 : end if
800 :
801 1121 : end subroutine rttddft_calc_current
802 : !!***
803 :
804 : end module m_rttddft_properties
805 : !!***
|