15 atom_basis_type, atom_integrals, atom_orbitals, atom_p_type, atom_type,
create_atom_orbs, &
40 #include "./base/base_uses.f90"
47 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'atom_admm_methods'
62 TYPE(atom_p_type),
DIMENSION(:, :),
POINTER :: atom_info
63 TYPE(section_vals_type),
POINTER :: admm_section
64 INTEGER,
INTENT(IN) :: iw
66 CHARACTER(LEN=2) :: btyp
67 INTEGER :: i, ifun, j, l, m, maxl, mo, n, na, nb, &
69 LOGICAL :: pp_calc, rhf
70 REAL(kind=
dp) :: admm1_k_energy, admm2_k_energy, admmq_k_energy, dfexc_admm1, dfexc_admm2, &
71 dfexc_admmq, dxc, dxk, el1, el2, elq, elref, fexc_optx_admm1, fexc_optx_admm2, &
72 fexc_optx_admmq, fexc_optx_ref, fexc_pbex_admm1, fexc_pbex_admm2, fexc_pbex_admmq, &
73 fexc_pbex_ref, ref_energy, xsi
74 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: lamat
75 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: admm1_k, admm2_k, admm_xcmat, admm_xcmata, &
76 admm_xcmatb, admmq_k, ovlap, ref_k, ref_xcmat, ref_xcmata, ref_xcmatb, sinv, siref, tmat
77 TYPE(atom_basis_type),
POINTER :: admm_basis, ref_basis
78 TYPE(atom_integrals),
POINTER :: admm_int, ref_int
79 TYPE(atom_orbitals),
POINTER :: admm1_orbs, admm2_orbs, admmq_orbs, &
81 TYPE(atom_type),
POINTER ::
atom
82 TYPE(section_vals_type),
POINTER :: basis_section, xc_fun, xc_fun_section, &
86 WRITE (iw,
'(/,T2,A)') &
87 '!-----------------------------------------------------------------------------!'
88 WRITE (iw,
'(T30,A)')
"Analysis of ADMM approximations"
89 WRITE (iw,
'(T2,A)') &
90 '!-----------------------------------------------------------------------------!'
94 NULLIFY (xc_section, xc_pbex,
xc_optx)
104 IF (.NOT.
ASSOCIATED(xc_fun))
EXIT
120 zval = atom_info(1, 1)%atom%z
121 pp_calc = atom_info(1, 1)%atom%pp_calc
123 IF (pp_calc) btyp =
"PP"
124 ALLOCATE (admm_basis)
126 NULLIFY (admm_basis%grid)
132 ref_basis => atom_info(1, 1)%atom%basis
134 ALLOCATE (ref_int, admm_int)
138 IF (admm_int%n(l) /= admm_int%nne(l))
THEN
139 IF (iw > 0)
WRITE (iw, *)
"ADMM Basis is linear dependent ", l, admm_int%n(l), admm_int%nne(l)
140 cpabort(
"ADMM basis is linear dependent")
144 na = maxval(admm_basis%nbas(:))
145 nb = maxval(ref_basis%nbas(:))
146 ALLOCATE (ovlap(1:na, 1:nb, 0:
lmat))
149 ALLOCATE (sinv(1:na, 1:na, 0:
lmat))
151 n = admm_basis%nbas(l)
153 sinv(1:n, 1:n, l) = admm_int%ovlp(1:n, 1:n, l)
157 ALLOCATE (tmat(1:na, 1:nb, 0:
lmat))
159 n = admm_basis%nbas(l)
160 m = ref_basis%nbas(l)
161 IF (n < 1 .OR. m < 1) cycle
162 tmat(1:n, 1:m, l) = matmul(sinv(1:n, 1:n, l), ovlap(1:n, 1:m, l))
165 ALLOCATE (siref(1:nb, 1:nb, 0:
lmat))
167 n = ref_basis%nbas(l)
169 siref(1:n, 1:n, l) = ref_int%ovlp(1:n, 1:n, l)
173 DO i = 1,
SIZE(atom_info, 1)
174 DO j = 1,
SIZE(atom_info, 2)
175 atom => atom_info(i, j)%atom
177 ref_orbs =>
atom%orbitals
178 ALLOCATE (ref_k(1:nb, 1:nb, 0:
lmat))
179 SELECT CASE (
atom%method_type)
184 CALL eeri_contract(ref_k, ref_int%eeri, ref_orbs%pmat, ref_basis%nbas)
185 ref_energy = 0.5_dp*
atom_trace(ref_k, ref_orbs%pmat)
190 CALL eeri_contract(ref_k, ref_int%eeri, ref_orbs%pmata, ref_basis%nbas)
191 ref_energy =
atom_trace(ref_k, ref_orbs%pmata)
193 CALL eeri_contract(ref_k, ref_int%eeri, ref_orbs%pmatb, ref_basis%nbas)
194 ref_energy = ref_energy +
atom_trace(ref_k, ref_orbs%pmatb)
196 cpabort(
"ADMM not available")
198 cpabort(
"ADMM not available")
202 elref =
atom_trace(ref_int%ovlp, ref_orbs%pmat)
204 mo = maxval(
atom%state%maxn_calc)
205 NULLIFY (admm1_orbs, admm2_orbs, admmq_orbs)
209 ALLOCATE (lamat(1:mo, 1:mo))
210 ALLOCATE (admm1_k(1:na, 1:na, 0:
lmat))
211 ALLOCATE (admm2_k(1:na, 1:na, 0:
lmat))
212 ALLOCATE (admmq_k(1:na, 1:na, 0:
lmat))
215 n = admm_basis%nbas(l)
216 m = ref_basis%nbas(l)
217 mo =
atom%state%maxn_calc(l)
218 IF (n < 1 .OR. m < 1 .OR. mo < 1) cycle
219 admm2_orbs%wfn(1:n, 1:mo, l) = matmul(tmat(1:n, 1:m, l), ref_orbs%wfn(1:m, 1:mo, l))
220 CALL lowdin_matrix(admm2_orbs%wfn(1:n, 1:mo, l), lamat(1:mo, 1:mo), admm_int%ovlp(1:n, 1:n, l))
221 admm1_orbs%wfn(1:n, 1:mo, l) = matmul(admm2_orbs%wfn(1:n, 1:mo, l), lamat(1:mo, 1:mo))
223 CALL atom_denmat(admm1_orbs%pmat, admm1_orbs%wfn, admm_basis%nbas,
atom%state%occupation, &
224 atom%state%maxl_occ,
atom%state%maxn_occ)
225 CALL atom_denmat(admm2_orbs%pmat, admm2_orbs%wfn, admm_basis%nbas,
atom%state%occupation, &
226 atom%state%maxl_occ,
atom%state%maxn_occ)
227 el1 =
atom_trace(admm_int%ovlp, admm1_orbs%pmat)
228 el2 =
atom_trace(admm_int%ovlp, admm2_orbs%pmat)
230 admmq_orbs%pmat = xsi*admm2_orbs%pmat
231 elq =
atom_trace(admm_int%ovlp, admmq_orbs%pmat)
232 admmq_orbs%wfn = sqrt(xsi)*admm2_orbs%wfn
235 CALL eeri_contract(admm1_k, admm_int%eeri, admm1_orbs%pmat, admm_basis%nbas)
236 admm1_k_energy = 0.5_dp*
atom_trace(admm1_k, admm1_orbs%pmat)
238 CALL eeri_contract(admm2_k, admm_int%eeri, admm2_orbs%pmat, admm_basis%nbas)
239 admm2_k_energy = 0.5_dp*
atom_trace(admm2_k, admm2_orbs%pmat)
241 CALL eeri_contract(admmq_k, admm_int%eeri, admmq_orbs%pmat, admm_basis%nbas)
242 admmq_k_energy = 0.5_dp*
atom_trace(admmq_k, admmq_orbs%pmat)
245 n = admm_basis%nbas(l)
246 m = ref_basis%nbas(l)
247 mo =
atom%state%maxn_calc(l)
248 IF (n < 1 .OR. m < 1 .OR. mo < 1) cycle
249 admm2_orbs%wfna(1:n, 1:mo, l) = matmul(tmat(1:n, 1:m, l), ref_orbs%wfna(1:m, 1:mo, l))
250 CALL lowdin_matrix(admm2_orbs%wfna(1:n, 1:mo, l), lamat, admm_int%ovlp(1:n, 1:n, l))
251 admm1_orbs%wfna(1:n, 1:mo, l) = matmul(admm2_orbs%wfna(1:n, 1:mo, l), lamat(1:mo, 1:mo))
252 admm2_orbs%wfnb(1:n, 1:mo, l) = matmul(tmat(1:n, 1:m, l), ref_orbs%wfnb(1:m, 1:mo, l))
253 CALL lowdin_matrix(admm2_orbs%wfnb(1:n, 1:mo, l), lamat, admm_int%ovlp(1:n, 1:n, l))
254 admm1_orbs%wfnb(1:n, 1:mo, l) = matmul(admm2_orbs%wfnb(1:n, 1:mo, l), lamat(1:mo, 1:mo))
256 CALL atom_denmat(admm1_orbs%pmata, admm1_orbs%wfna, admm_basis%nbas,
atom%state%occa, &
257 atom%state%maxl_occ,
atom%state%maxn_occ)
258 CALL atom_denmat(admm1_orbs%pmatb, admm1_orbs%wfnb, admm_basis%nbas,
atom%state%occb, &
259 atom%state%maxl_occ,
atom%state%maxn_occ)
260 admm1_orbs%pmat = admm1_orbs%pmata + admm1_orbs%pmatb
261 CALL atom_denmat(admm2_orbs%pmata, admm2_orbs%wfna, admm_basis%nbas,
atom%state%occa, &
262 atom%state%maxl_occ,
atom%state%maxn_occ)
263 CALL atom_denmat(admm2_orbs%pmatb, admm2_orbs%wfnb, admm_basis%nbas,
atom%state%occb, &
264 atom%state%maxl_occ,
atom%state%maxn_occ)
265 admm2_orbs%pmat = admm2_orbs%pmata + admm2_orbs%pmatb
266 elref =
atom_trace(ref_int%ovlp, ref_orbs%pmata)
267 el2 =
atom_trace(admm_int%ovlp, admm2_orbs%pmata)
269 admmq_orbs%pmata = xsi*admm2_orbs%pmata
270 admmq_orbs%wfna = sqrt(xsi)*admm2_orbs%wfna
271 elref =
atom_trace(ref_int%ovlp, ref_orbs%pmatb)
272 el2 =
atom_trace(admm_int%ovlp, admm2_orbs%pmatb)
274 admmq_orbs%pmatb = xsi*admm2_orbs%pmatb
275 admmq_orbs%wfnb = sqrt(xsi)*admm2_orbs%wfnb
276 admmq_orbs%pmat = admmq_orbs%pmata + admmq_orbs%pmatb
277 el1 =
atom_trace(admm_int%ovlp, admm1_orbs%pmat)
278 el2 =
atom_trace(admm_int%ovlp, admm2_orbs%pmat)
279 elq =
atom_trace(admm_int%ovlp, admmq_orbs%pmat)
280 elref =
atom_trace(ref_int%ovlp, ref_orbs%pmat)
283 CALL eeri_contract(admm1_k, admm_int%eeri, admm1_orbs%pmata, admm_basis%nbas)
284 admm1_k_energy =
atom_trace(admm1_k, admm1_orbs%pmata)
286 CALL eeri_contract(admm1_k, admm_int%eeri, admm1_orbs%pmatb, admm_basis%nbas)
287 admm1_k_energy = admm1_k_energy +
atom_trace(admm1_k, admm1_orbs%pmatb)
289 CALL eeri_contract(admm2_k, admm_int%eeri, admm2_orbs%pmata, admm_basis%nbas)
290 admm2_k_energy =
atom_trace(admm2_k, admm2_orbs%pmata)
292 CALL eeri_contract(admm2_k, admm_int%eeri, admm2_orbs%pmatb, admm_basis%nbas)
293 admm2_k_energy = admm2_k_energy +
atom_trace(admm2_k, admm2_orbs%pmatb)
295 CALL eeri_contract(admmq_k, admm_int%eeri, admmq_orbs%pmata, admm_basis%nbas)
296 admmq_k_energy =
atom_trace(admmq_k, admmq_orbs%pmata)
298 CALL eeri_contract(admmq_k, admm_int%eeri, admmq_orbs%pmatb, admm_basis%nbas)
299 admmq_k_energy = admmq_k_energy +
atom_trace(admmq_k, admmq_orbs%pmatb)
304 maxl =
atom%state%maxl_occ
306 ALLOCATE (ref_xcmat(1:nb, 1:nb, 0:
lmat))
307 ALLOCATE (admm_xcmat(1:na, 1:na, 0:
lmat))
309 CALL atom_vxc_lda(ref_basis, ref_orbs%pmat, maxl, xc_pbex, fexc_pbex_ref, ref_xcmat)
310 CALL atom_vxc_lda(admm_basis, admm1_orbs%pmat, maxl, xc_pbex, fexc_pbex_admm1, admm_xcmat)
311 CALL atom_vxc_lda(admm_basis, admm2_orbs%pmat, maxl, xc_pbex, fexc_pbex_admm2, admm_xcmat)
312 CALL atom_vxc_lda(admm_basis, admmq_orbs%pmat, maxl, xc_pbex, fexc_pbex_admmq, admm_xcmat)
319 CALL atom_dpot_lda(ref_basis, ref_orbs%pmat, admm_basis, admm1_orbs%pmat, &
320 maxl,
"LINX", dfexc_admm1)
321 CALL atom_dpot_lda(ref_basis, ref_orbs%pmat, admm_basis, admm2_orbs%pmat, &
322 maxl,
"LINX", dfexc_admm2)
323 CALL atom_dpot_lda(ref_basis, ref_orbs%pmat, admm_basis, admmq_orbs%pmat, &
324 maxl,
"LINX", dfexc_admmq)
325 DEALLOCATE (ref_xcmat, admm_xcmat)
327 ALLOCATE (ref_xcmata(1:nb, 1:nb, 0:
lmat))
328 ALLOCATE (ref_xcmatb(1:nb, 1:nb, 0:
lmat))
329 ALLOCATE (admm_xcmata(1:na, 1:na, 0:
lmat))
330 ALLOCATE (admm_xcmatb(1:na, 1:na, 0:
lmat))
332 CALL atom_vxc_lsd(ref_basis, ref_orbs%pmata, ref_orbs%pmatb, maxl, xc_pbex, fexc_pbex_ref, &
333 ref_xcmata, ref_xcmatb)
334 CALL atom_vxc_lsd(admm_basis, admm1_orbs%pmata, admm1_orbs%pmatb, maxl, xc_pbex, &
335 fexc_pbex_admm1, admm_xcmata, admm_xcmatb)
336 CALL atom_vxc_lsd(admm_basis, admm2_orbs%pmata, admm2_orbs%pmatb, maxl, xc_pbex, &
337 fexc_pbex_admm2, admm_xcmata, admm_xcmatb)
338 CALL atom_vxc_lsd(admm_basis, admmq_orbs%pmata, admmq_orbs%pmatb, maxl, xc_pbex, &
339 fexc_pbex_admmq, admm_xcmata, admm_xcmatb)
340 CALL atom_vxc_lsd(ref_basis, ref_orbs%pmata, ref_orbs%pmatb, maxl,
xc_optx, fexc_optx_ref, &
341 ref_xcmata, ref_xcmatb)
343 fexc_optx_admm1, admm_xcmata, admm_xcmatb)
345 fexc_optx_admm2, admm_xcmata, admm_xcmatb)
347 fexc_optx_admmq, admm_xcmata, admm_xcmatb)
348 DEALLOCATE (ref_xcmata, ref_xcmatb, admm_xcmata, admm_xcmatb)
353 WRITE (iw,
"(/,A,I3,T48,A,I3)")
" Electronic Structure Setting: ", i, &
354 " Electronic Structure Method: ", j
355 WRITE (iw,
"(' Norm of ADMM Basis projection ',T61,F20.10)") el2/elref
356 WRITE (iw,
"(' Reference Exchange Energy [Hartree]',T61,F20.10)") ref_energy
358 dxk = ref_energy - admm1_k_energy
359 WRITE (iw,
"(A,F20.10,T60,A,F13.10)")
" ADMM1 METHOD: Energy ", admm1_k_energy, &
361 dxc = fexc_pbex_ref - fexc_pbex_admm1
362 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"PBEX Correction ", dxc, dxc/dxk*100._dp, &
363 " Error: ", dxk - dxc
364 dxc = fexc_optx_ref - fexc_optx_admm1
365 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"OPTX Correction ", dxc, dxc/dxk*100._dp, &
366 " Error: ", dxk - dxc
368 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"LINX Correction ", dxc, dxc/dxk*100._dp, &
369 " Error: ", dxk - dxc
371 dxk = ref_energy - admm2_k_energy
372 WRITE (iw,
"(A,F20.10,T60,A,F13.10)")
" ADMM2 METHOD: Energy ", admm2_k_energy, &
374 dxc = fexc_pbex_ref - fexc_pbex_admm2
375 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"PBEX Correction ", dxc, dxc/dxk*100._dp, &
376 " Error: ", dxk - dxc
377 dxc = fexc_optx_ref - fexc_optx_admm2
378 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"OPTX Correction ", dxc, dxc/dxk*100._dp, &
379 " Error: ", dxk - dxc
381 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"LINX Correction ", dxc, dxc/dxk*100._dp, &
382 " Error: ", dxk - dxc
384 dxk = ref_energy - admmq_k_energy
385 WRITE (iw,
"(A,F20.10,T60,A,F13.10)")
" ADMMQ METHOD: Energy ", admmq_k_energy, &
387 dxc = fexc_pbex_ref - fexc_pbex_admmq
388 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"PBEX Correction ", dxc, dxc/dxk*100._dp, &
389 " Error: ", dxk - dxc
390 dxc = fexc_optx_ref - fexc_optx_admmq
391 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"OPTX Correction ", dxc, dxc/dxk*100._dp, &
392 " Error: ", dxk - dxc
394 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"LINX Correction ", dxc, dxc/dxk*100._dp, &
395 " Error: ", dxk - dxc
397 dxk = ref_energy - admmq_k_energy
398 WRITE (iw,
"(A,F20.10,T60,A,F13.10)")
" ADMMS METHOD: Energy ", admmq_k_energy, &
400 dxc = fexc_pbex_ref - fexc_pbex_admmq*xsi**(2._dp/3._dp)
401 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"PBEX Correction ", dxc, dxc/dxk*100._dp, &
402 " Error: ", dxk - dxc
403 dxc = fexc_optx_ref - fexc_optx_admmq*xsi**(2._dp/3._dp)
404 WRITE (iw,
"(T10,A,F12.6,F12.3,'%',T60,A,F13.10)")
"OPTX Correction ", dxc, dxc/dxk*100._dp, &
405 " Error: ", dxk - dxc
408 DEALLOCATE (admm1_k, admm2_k, admmq_k)
421 DEALLOCATE (ref_int, admm_int, admm_basis)
422 DEALLOCATE (ovlap, sinv, tmat, siref)
429 WRITE (iw,
'(/,T2,A)') &
430 '!------------------------------End of ADMM analysis---------------------------!'
441 SUBROUTINE lowdin_matrix(wfn, lamat, ovlp)
442 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: wfn
443 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: lamat
444 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: ovlp
446 INTEGER :: i, j, k, n
447 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: w
448 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: vmat
452 lamat = matmul(transpose(wfn), matmul(ovlp, wfn))
453 ALLOCATE (w(n), vmat(n, n))
454 CALL jacobi(lamat(1:n, 1:n), w(1:n), vmat(1:n, 1:n))
455 w(1:n) = 1.0_dp/sqrt(w(1:n))
460 lamat(i, j) = lamat(i, j) + vmat(i, k)*w(k)*vmat(j, k)
467 END SUBROUTINE lowdin_matrix
subroutine, public atom_admm(atom_info, admm_section, iw)
Analysis of ADMM approximation to exact exchange.
Calculate the atomic operator matrices.
subroutine, public atom_int_setup(integrals, basis, potential, eri_coulomb, eri_exchange, all_nu)
Set up atomic integrals.
subroutine, public atom_basis_projection_overlap(ovlap, basis_a, basis_b)
Calculate overlap matrix between two atomic basis sets.
subroutine, public atom_int_release(integrals)
Release memory allocated for atomic integrals (valence electrons).
Routines that print various information about an atomic kind.
subroutine, public atom_print_basis(atom_basis, iw, title)
Print atomic basis set.
Define the atom type and its sub types.
subroutine, public init_atom_basis(basis, basis_section, zval, btyp)
Initialize the basis for the atomic code.
subroutine, public release_atom_orbs(orbs)
...
integer, parameter, public lmat
subroutine, public release_atom_basis(basis)
...
subroutine, public create_atom_orbs(orbs, mbas, mo)
...
Some basic routines for atomic calculations.
pure subroutine, public atom_denmat(pmat, wfn, nbas, occ, maxl, maxn)
Calculate a density matrix using atomic orbitals.
pure subroutine, public eeri_contract(kmat, erint, pmat, nsize)
Contract exchange Electron Repulsion Integrals.
pure logical function, public atom_consistent_method(method, multiplicity)
Check that the atomic multiplicity is consistent with the electronic structure method.
pure real(kind=dp) function, public atom_trace(opmat, pmat)
Compute Trace[opmat * pmat] == Trace[opmat * pmat^T] .
routines that build the integrals of the Vxc potential calculated for the atomic code
subroutine, public atom_dpot_lda(basis0, pmat0, basis1, pmat1, maxl, functional, dfexc, linxpar)
Estimate the ADMM exchange energy correction term using a model exchange functional.
subroutine, public atom_vxc_lsd(basis, pmata, pmatb, maxl, xc_section, fexc, xcmata, xcmatb)
Alternative subroutine that calculates atomic exchange-correlation potential in spin-polarized case.
subroutine, public atom_vxc_lda(basis, pmat, maxl, xc_section, fexc, xcmat)
Alternative subroutine that calculates atomic exchange-correlation potential in spin-restricted case.
Defines the basic variable types.
integer, parameter, public dp
Collection of simple mathematical functions and subroutines.
subroutine, public jacobi(a, d, v)
Jacobi matrix diagonalization. The eigenvalues are returned in vector d and the eigenvectors are retu...
subroutine, public invmat_symm(a, cholesky_triangle)
returns inverse of real symmetric, positive definite matrix