62 TYPE(
atom_p_type),
DIMENSION(:, :),
POINTER :: atom_info
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
79 TYPE(
atom_orbitals),
POINTER :: admm1_orbs, admm2_orbs, admmq_orbs, &
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---------------------------!'