@@ -105,6 +105,22 @@ def get_basis_data(cell, kpts, ecut_wf, ecut_rho=None, wf_mesh=None,
105105 return np .array (wf_mesh ), np .array (xc_mesh ), wf2xc , basis_data
106106
107107
108+ def ewald_correction (moe_ks , mocc_ks , madelung ):
109+ if isinstance (moe_ks [0 ][0 ], float ): # RHF
110+ nkpts = len (moe_ks )
111+ moe_ks_new = [None ] * nkpts
112+ for k in range (nkpts ):
113+ moe_ks_new [k ] = moe_ks [k ].copy ()
114+ moe_ks_new [k ][:] -= 0.5 * mocc_ks [k ] * madelung
115+ else : # UHF
116+ ncomp = len (moe_ks )
117+ moe_ks_new = [None ] * ncomp
118+ for comp in range (ncomp ):
119+ moe_ks_new [comp ] = ewald_correction (moe_ks [comp ], mocc_ks [comp ],
120+ ncomp * madelung )
121+ return moe_ks_new
122+
123+
108124def wf_fft (C_k_R , mesh , basis = None ):
109125 """
110126 Fourier transform a wave function from real to reciprocal space.
@@ -468,9 +484,20 @@ def gto2cpw(cell, basis, kpts, amin=None, amax=None, ke_or_mesh=None, out=None):
468484 return out
469485
470486
487+ def _reduce_fock_to_moe (fockao , mo_coeff ):
488+ return [np .einsum ("ai,ai->i" , mo .conj (), fockao [k ].dot (mo )).real
489+ for k , mo in enumerate (mo_coeff )]
490+
491+
471492def gtomf2pwmf (mf , chkfile = None ):
472493 """
494+ Create a PW HF calculation from a GTO HF calculation.
495+ If mf.exxdiv is "ewald", the returned PW HF object
496+ has exxdiv="ewald", otherwise exxdiv=None.
497+
473498 Args:
499+ mf:
500+ GTO HF calculation
474501 chkfile (str):
475502 A hdf5 file to store chk variables (mo_energy, mo_occ, etc.).
476503 If not provided, a temporary file is generated.
@@ -484,44 +511,79 @@ def gtomf2pwmf(mf, chkfile=None):
484511 nkpts = len (kpts )
485512# transform GTO MO coeff to PW MO coeff
486513 Cgto_ks = mf .mo_coeff
514+
515+ exxdiv = "ewald" if mf .exxdiv == "ewald" else None
516+ if mf .exxdiv is not None :
517+ dm = mf .make_rdm1 (mf .mo_coeff , mf .mo_occ )
518+ with lib .temporary_env (mf , exxdiv = None ):
519+ # Calculate veff without the exxdiv
520+ vhf = mf .get_veff (cell , dm )
521+ fockao = mf .get_hcore () + vhf
522+
487523 if isinstance (mf , scf .khf .KRHF ):
488- pwmf = pwscf .KRHF (cell , kpts )
524+ pwmf = pwscf .KRHF (cell , kpts , exxdiv = exxdiv )
489525 nmo_ks = [Cgto_ks [k ].shape [1 ] for k in range (nkpts )]
490526 pwmf .mo_coeff = C_ks = get_C_ks_G (cell , kpts , Cgto_ks , nmo_ks )
491- pwmf .mo_energy = moe_ks = mf .mo_energy
527+ if mf .exxdiv is None :
528+ pwmf .mo_energy = moe_ks = mf .mo_energy
529+ else :
530+ pwmf .mo_energy = moe_ks = _reduce_fock_to_moe (fockao , mf .mo_coeff )
492531 pwmf .mo_occ = mocc_ks = mf .mo_occ
493532 pwmf .e_tot = mf .e_tot
494533 elif isinstance (mf , scf .kuhf .KUHF ):
495- pwmf = pwscf .KUHF (cell , kpts )
534+ pwmf = pwscf .KUHF (cell , kpts , exxdiv = exxdiv )
496535 C_ks = [None ] * 2
497536 for s in [0 ,1 ]:
498537 nmo_ks = [Cgto_ks [s ][k ].shape [1 ] for k in range (nkpts )]
499538 C_ks [s ] = get_C_ks_G (cell , kpts , Cgto_ks [s ], nmo_ks )
500539 pwmf .mo_coeff = C_ks
501- pwmf .mo_energy = moe_ks = mf .mo_energy
540+ if mf .exxdiv is None :
541+ pwmf .mo_energy = moe_ks = mf .mo_energy
542+ else :
543+ pwmf .mo_energy = moe_ks = [
544+ _reduce_fock_to_moe (fockao [0 ], mf .mo_coeff [0 ]),
545+ _reduce_fock_to_moe (fockao [1 ], mf .mo_coeff [1 ]),
546+ ]
502547 pwmf .mo_occ = mocc_ks = mf .mo_occ
503548 pwmf .e_tot = mf .e_tot
504549 elif isinstance (mf , scf .hf .RHF ):
505- pwmf = pwscf .KRHF (cell , kpts )
550+ pwmf = pwscf .KRHF (cell , kpts , exxdiv = exxdiv )
506551 nmo_ks = [Cgto_ks .shape [1 ]]
507552 C_ks = get_C_ks_G (cell , kpts , [Cgto_ks ], nmo_ks )
508553 pwmf .mo_coeff = C_ks
509- pwmf .mo_energy = moe_ks = [mf .mo_energy ]
554+ if mf .exxdiv is None :
555+ pwmf .mo_energy = moe_ks = [mf .mo_energy ]
556+ else :
557+ pwmf .mo_energy = moe_ks = _reduce_fock_to_moe (
558+ [fockao ], [mf .mo_coeff ]
559+ )
510560 pwmf .mo_occ = mocc_ks = [mf .mo_occ ]
511561 pwmf .e_tot = mf .e_tot
512562 elif isinstance (mf , scf .uhf .UHF ):
513- pwmf = pwscf .KUHF (cell , kpts )
563+ pwmf = pwscf .KUHF (cell , kpts , exxdiv = exxdiv )
514564 C_ks = [None ] * 2
515565 for s in [0 ,1 ]:
516566 nmo_ks = [Cgto_ks [s ].shape [1 ]]
517567 C_ks [s ] = get_C_ks_G (cell , kpts , [Cgto_ks [s ]], nmo_ks )
518568 pwmf .mo_coeff = C_ks
519- pwmf .mo_energy = moe_ks = [[mf .mo_energy [s ]] for s in [0 ,1 ]]
569+ if mf .exxdiv is None :
570+ pwmf .mo_energy = moe_ks = [[mf .mo_energy [s ]] for s in [0 ,1 ]]
571+ else :
572+ pwmf .mo_energy = moe_ks = [
573+ _reduce_fock_to_moe ([fockao [0 ]], [mf .mo_coeff [0 ]]),
574+ _reduce_fock_to_moe ([fockao [1 ]], [mf .mo_coeff [1 ]]),
575+ ]
520576 pwmf .mo_occ = mocc_ks = [[mf .mo_occ [s ]] for s in [0 ,1 ]]
521577 pwmf .e_tot = mf .e_tot
522578 else :
523579 raise TypeError
524- # update chkfile
580+
581+ if exxdiv == "ewald" :
582+ pwmf .mo_energy = moe_ks = ewald_correction (
583+ pwmf .mo_energy , pwmf .mo_occ , pwmf .madelung
584+ )
585+
586+ # update chkfile
525587 if chkfile is None :
526588 swapfile = tempfile .NamedTemporaryFile (dir = lib .param .TMPDIR )
527589 chkfile = swapfile .name
0 commit comments