def plot_convergence(filename): with h5py.File('afqmc.h5', 'r') as fh5: hcore = fh5['Hamiltonian/hcore'][:].view(numpy.complex128)[:, :, 0] energies = [] errs = [] tau_bps = [] sym_md = get_metadata(filename) bp_md = get_metadata(filename, 'Observables/BackPropagated/') taus = bp_md['BackPropSteps'] for i, t in enumerate(taus): # skip the first block for equilibration skip = 1 nelec = sym_md['NAEA'] + sym_md['NAEB'] # We can extract the averaged 1RDM. rdm_av, rdm_errs = average_one_rdm(filename, eqlb=skip, ix=i) nelec_rdm = (rdm_av[0].trace()).real assert (nelec_rdm - nelec < 1e-12) # Often it is simpler to compute error bars if we first contract the 1RDM. # For example, we can compute the one-body energy from the averaged RDM as. e1b = numpy.einsum('ij,sij->', hcore, rdm_av).real # Or we can instead compute the average of the one-body energies. e1b_series, err = compute_one_body(filename, hcore, skip, i) energies.append(e1b_series) errs.append(err) # get back propagation time tau_bps.append(t * sym_md['Timestep']) assert (e1b - e1b_series < 1e-12) # Finally plot the one-body energy and check the estimator is converged with # respect to back propagation time. if have_mpl: plt.errorbar(tau_bps, energies, yerr=errs, fmt='o') plt.xlabel(r'$\tau_{BP}$') plt.ylabel(r'$E_{1B}$ (Ha)') plt.savefig('h1e_conv.pdf', bbox_inches='tight')
def average_on_top_pdm(filename, estimator='back_propagated', eqlb=1, skip=1, ix=None): """Average on-top pair density matrix. Returns n2(r,r) for a given real space grid. Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. eqlb : int Number of blocks for equilibration. Default 1. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- opdm : :class:`numpy.ndarray` Averaged diagonal on-top pair density matrix. opdm_err : :class:`numpy.ndarray` Error bars for diagonal on-top pair density matrix elements. """ md = get_metadata(filename) mean, err = average_observable(filename, 'on_top_pdm', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) # TODO: Update appropriately. return mean, err
def average_one_rdm(filename, estimator='back_propagated', eqlb=1, skip=1, ix=None): """Average AFQMC 1RDM. Returns P_{sij} = <c_{is}^+ c_{js}^> as a (nspin, M, M) dimensional array. Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. eqlb : int Number of blocks for equilibration. Default 1. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- one_rdm : :class:`numpy.ndarray` Averaged 1RDM. one_rdm_err : :class:`numpy.ndarray` Error bars for 1RDM elements. """ md = get_metadata(filename) mean, err = average_observable(filename, 'one_rdm', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) nbasis = md['NMO'] wt = md['WalkerType'] try: walker = WALKER_TYPE[wt] except IndexError: print('Unknown walker type {}'.format(wt)) if walker == 'closed': return 2 * mean.reshape(1, nbasis, nbasis), err.reshape( 1, nbasis, nbasis) elif walker == 'collinear': return mean.reshape((2, nbasis, nbasis)), err.reshape( (2, nbasis, nbasis)) elif walker == 'non_collinear': return mean.reshape((1, 2 * nbasis, 2 * nbasis)), err.reshape( (1, 2 * nbasis, 2 * nbasis)) else: print('Unknown walker type.') return None
def average_atom_correlations(filename, estimator='back_propagated', eqlb=1, skip=1, ix=None): """Average atom centered correlations. Returns <C(I)>, <S(I)>, <C(I)C(J)> and <S(I)S(J)> for a given set of atomic sites. C = (nup + ndown), S = (nup - ndown) Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. eqlb : int Number of blocks for equilibration. Default 1. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- c_mean : :class:`numpy.ndarray` Averaged charge. c_err : :class:`numpy.ndarray` Error bars for charge. s_mean : :class:`numpy.ndarray` Averaged spin. s_err : :class:`numpy.ndarray` Error bars for spin. cc_mean : :class:`numpy.ndarray` Averaged charge-charge correlation function. cc_err : :class:`numpy.ndarray` Error bars for charge-charge correlation function. ss_mean : :class:`numpy.ndarray` Averaged spin-spin correlation function. ss_err : :class:`numpy.ndarray` Error bars for spin-spin correlation function. """ md = get_metadata(filename) c_mean, c_err = average_observable(filename, 'c_atom_correlation', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) s_mean, s_err = average_observable(filename, 's_atom_correlation', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) m_mean, m_err = average_observable(filename, 'm_atom_correlation', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) cc_mean, cc_err = average_observable(filename, 'cc_atom_correlation', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) ss_mean, ss_err = average_observable(filename, 'ss_atom_correlation', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) # TODO: get npts from metadata local to cc_correlation npts = int(sqrt(cc_mean.shape[0])) return c_mean, c_err, s_mean, s_err, m_mean, m_err, cc_mean.reshape((npts,-1)), cc_err.reshape((npts,-1)), \ ss_mean.reshape((npts,-1)), ss_err.reshape((npts,-1))
def average_two_rdm(filename, estimator='back_propagated', eqlb=1, skip=1, ix=None): """Average AFQMC 2RDM. Returns a list of 2RDMS, where 2RDM[s1s2,i,k,j,l] = <c_{i}^+ c_{j}^+ c_{l} c_{k}>. For closed shell systems, returns [(a,a,a,a),(a,a,b,b)] For collinear systems, returns [(a,a,a,a),(a,a,b,b),(b,b,b,b)] Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. eqlb : int Number of blocks for equilibration. Default 1. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- two_rdm : :class:`numpy.ndarray` List of averaged 2RDM. two_rdm_err : :class:`numpy.ndarray` List of error bars for 2RDM elements. """ md = get_metadata(filename) mean, err = average_observable(filename, 'two_rdm', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) nbasis = md['NMO'] wt = md['WalkerType'] try: walker = WALKER_TYPE[wt] except IndexError: print('Unknown walker type {}'.format(wt)) if walker == 'closed': return mean.reshape(2,nbasis,nbasis,nbasis,nbasis), err.reshape(2,nbasis,nbasis,nbasis,nbasis) elif walker == 'collinear': return mean.reshape(3,nbasis,nbasis,nbasis,nbasis), err.reshape(3,nbasis,nbasis,nbasis,nbasis) elif walker == 'non_collinear': return mean.reshape(2*nbasis,2*nbasis,2*nbasis,2*nbasis), err.reshape(2*nbasis,2*nbasis,2*nbasis, 2*nbasis) else: print('Unknown walker type.') return None
def average_gen_fock(filename, fock_type='plus', estimator='back_propagated', eqlb=1, skip=1, ix=None): """Average AFQMC genralised Fock matrix. Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). fock_type : string Which generalised Fock matrix to extract. Optional (plus/minus). Default: plus. estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. eqlb : int Number of blocks for equilibration. Default 1. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- gfock : :class:`numpy.ndarray` Averaged 1RDM. gfock_err : :class:`numpy.ndarray` Error bars for 1RDM elements. """ md = get_metadata(filename) name = 'gen_fock_' + fock_type mean, err = average_observable(filename, name, eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) nbasis = md['NMO'] wt = md['WalkerType'] try: walker = WALKER_TYPE[wt] except IndexError: print('Unknown walker type {}'.format(wt)) if walker == 'closed': return mean.reshape(1,nbasis,nbasis), err.reshape(1,nbasis, nbasis) elif walker == 'collinear': return mean.reshape((2,nbasis,nbasis)), err.reshape((2, nbasis, nbasis)) elif walker == 'non_collinear': return mean.reshape((1,2*nbasis,2*nbasis)), err.reshape((1,2*nbasis, 2*nbasis)) else: print('Unknown walker type.') return None
def average_observable(filename, name, eqlb=1, estimator='back_propagated', ix=None, skip=1): """Compute mean and error bar for AFQMC HDF5 observable. Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). name : string Name of observable (see estimates.py for list). eqlb : int Number of blocks for equilibration. Default 1. estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- mean : :class:`numpy.ndarray` Averaged quantity. err : :class:`numpy.ndarray` Error bars for quantity. """ md = get_metadata(filename) free_proj = md['FreeProjection'] if free_proj: mean = None err = None print("# Error analysis for free projection not implemented.") else: data = extract_observable(filename, name=name, estimator=estimator, ix=ix) mean = numpy.mean(data[eqlb:len(data):skip], axis=0) err = scipy.stats.sem(data[eqlb:len(data):skip].real, axis=0) return mean, err
def average_diag_two_rdm(filename, estimator='back_propagated', eqlb=1, skip=1, ix=None): """Average diagonal part of 2RDM. Returns <c_{is}^+ c_{jt}^+ c_{jt} c_{is}> as a (2M,2M) dimensional array. Parameters ---------- filename : string QMCPACK output containing density matrix (*.h5 file). estimator : string Estimator type to analyse. Options: back_propagated or mixed. Default: back_propagated. eqlb : int Number of blocks for equilibration. Default 1. skip : int Number of blocks to skip in between measurements equilibration. Default 1 (use all data). ix : int Back propagation path length to average. Optional. Default: None (chooses longest path). Returns ------- two_rdm : :class:`numpy.ndarray` Averaged diagonal 2RDM. two_rdm_err : :class:`numpy.ndarray` Error bars for diagonal 2RDM elements. """ md = get_metadata(filename) mean, err = average_observable(filename, 'diag_two_rdm', eqlb=eqlb, skip=skip, estimator=estimator, ix=ix) nbasis = md['NMO'] wt = md['WalkerType'] try: walker = WALKER_TYPE[wt] except IndexError: print('Unknown walker type {}'.format(wt)) if walker == 'closed': dm_size = nbasis*(2*nbasis-1) - nbasis*(nbasis-1) // 2 assert mean.shape == dm_size two_rdm = numpy.zeros((2*nbasis, 2*nbasis), dtype=mean.dtype) two_rdm_err = numpy.zeros((2*nbasis, 2*nbasis), dtype=mean.dtype) ij = 0 for i in range(nbasis): for j in range(i+1, 2*nbasis): two_rdm[i,j] = mean[ij] two_rdm_err[i,j] = err[ij] two_rdm[j,i] = mean[ij].conj() two_rdm_err[j,i] = err[ij].conj() ij += 1 two_rdm[nbasis:,nbasis:] = two_rdm[:nbasis,:nbasis].copy() elif walker == 'collinear': dm_size = nbasis*(2*nbasis-1) assert mean.shape == dm_size two_rdm = numpy.zeros((2*nbasis, 2*nbasis), dtype=mean.dtype) two_rdm_err = numpy.zeros((2*nbasis, 2*nbasis), dtype=mean.dtype) ij = 0 for i in range(2*nbasis): for j in range(i+1, 2*nbasis): two_rdm[i,j] = mean[ij] two_rdm_err[i,j] = err[ij] two_rdm[j,i] = mean[ij].conj() two_rdm_err[j,i] = err[ij].conj() ij += 1 elif walker == 'non_collinear': print("Non-collinear wavefunction not supported.") return None else: print('Unknown walker type.') return None # Diagonal is zero return two_rdm, two_rdm_err