JoonhoLee-Group / ipie

ipie stands for Intelligent Python-based Imaginary-time Evolution with a focus on simplicity and speed.
Apache License 2.0
44 stars 22 forks source link

Adjusting QMC parameters does not change them for a calculation. #314

Open Koberard opened 1 week ago

Koberard commented 1 week ago

Describe the bug Using afqmc.params adjusts my parameters when printing, rint(afqmc.params), but does not adjust them for my afqmc calculation. adjusting the time step and number of blocks makes no changes to my output energy.

To Reproduce import numpy as np from pyscf import gto, scf from ipie.config import MPI from ipie.utils.from_pyscf import gen_ipie_input_from_pyscf_chk from ipie.estimators.energy import EnergyEstimator, local_energy_batch GA_global = None GB_global = None Local_En_global = None Counter_global = None import os Dir = os.getcwd()+'/Mols/' Mol = os.listdir(Dir) print(Mol) for i in Mol: molecule = Dir + i

print(molecule)
mol = gto.M(
    atom=molecule,
    basis="sto-3g",
    verbose=4,
    unit="Angstrom",

)
mf = scf.UHF(mol)
mf.max_cycle=200
mf.chkfile = "scf.chk"
mf.kernel()
gen_ipie_input_from_pyscf_chk(mf.chkfile, verbose=0) 
comm = MPI.COMM_WORLD
from ipie.qmc.calc import build_afqmc_driver
from ipie.analysis.extraction import extract_observable
from ipie.estimators.estimator_base import EstimatorBase
from ipie.estimators.greens_function import greens_function
from ipie.estimators.local_energy import local_energy_G
Runs = 1
Blocks = 20
nsteps = 100
Walkers = 64
num_iterations = 100
timestep = 0.000001
num_steps_per_block=50
nsample = 100

for i in range (Runs):
    afqmc = build_afqmc_driver(comm, nelec=mol.nelec)
    afqmc.params.num_steps_per_block=num_steps_per_block
    afqmc.params.num_iterations = num_iterations
    afqmc.params.nsteps = nsteps
    afqmc.params.num_blocks = Blocks
    afqmc.params.num_walkers = Walkers
    afqmc.params.timestep = timestep
    afqmc.params.nsample = nsample
    afqmc.run()
    # We can extract the qmc data as as a pandas data frame like so
    from ipie.analysis.extraction import extract_observable

    qmc_data = extract_observable(afqmc.estimators.filename, "energy")
    y = qmc_data["ETotal"]
    y = y[1:]  # discard first 1 block
    from ipie.analysis.autocorr import reblock_by_autocorr
    df = reblock_by_autocorr(y, verbose=1)
    print(df)

Expected behavior ETotal_ac, and ETotal_error_ac should decrease with a smaller timestep

Screenshots If applicable, add screenshots to help explain your problem.

Other information:

Additional context Add any othe r context about the problem here. Bug_2.zip

fdmalone commented 1 week ago

Yes that's correct, you need to rebuild the driver which will build the propagator (which depends on the timestep).

fdmalone commented 1 week ago

Also the timestep you're using of 1e-6 is way too small

Koberard commented 1 week ago

If I rebuild the driver I the calculation just continues to run past my set number of blocks and I get a population control error. What is the correct syntax for rebuilding. I am doing the following.

     Blocks = 10
    Walkers = 100
    timestep = 0.01
    num_steps_per_block=25
    afqmc = build_afqmc_driver(comm, nelec=mol.nelec)
    from ipie.qmc.options import QMCOpts
    afqmc.params.num_steps_per_block=num_steps_per_block
    afqmc.params.num_blocks = Blocks
    afqmc.params.num_walkers = Walkers
    afqmc.params.timestep = timestep
    afqmc.params.dt = timestep
    afqmc = build_afqmc_driver(comm, nelec=mol.nelec)
fdmalone commented 1 week ago

The factory method you're using will build a new instance of AFQMC class so setting the parameters of the previous instance (afqmc) will have no effect. One option would be using the more direct builders (factory method) (e.g. https://github.com/JoonhoLee-Group/ipie/blob/develop/examples/17-ghf_afqmc/run_afqmc.py#L94). You can also use the build_from_hdf5 factory method if you want to read the integrals from the files you generated from the pyscf objects.

fdmalone commented 1 week ago

Note many of the arguments are optional so you don't need to specify walkers etc, just typically the hamiltonian and trial wavefunction (or paths to the files containing them)

Koberard commented 1 week ago

I have attempted to use a similar structure to that seen in example 17 which results in the problem I describe in issue 313 https://github.com/JoonhoLee-Group/ipie/issues/313

I do see that the parameters are updated when I run afqmc.params. Why would these not be included in my afqmc run? Is there any other way to rebuild the driver so that it contains these parameters for the run?

fdmalone commented 1 week ago

It's very surprising that the parameters are updated after calling build_afqmc_driver, are you sure:

afqmc.params.dt = timestep
afqmc = build_afqmc_driver(comm, nelec=mol.nelec)
assert afqmc.params.dt == timestep

doesn't result in an assertion error?

Re #313: Are you saying that:

gen_ipie_input_from_pyscf_chk(mf.chkfile, verbose=0) 

does not return an error while

ham = generate_hamiltonian(
    mol,
    mf.mo_coeff,
    mf.get_hcore(),
    mf.mo_coeff,  # should be optional
)

does (for the same molecule)? This is helpful to know.

fdmalone commented 1 week ago

You need to be very careful with generate_hamiltonian and the 4th argument (basis_change_matrix). You're doing a UHF simulation and typically we either use the orthogonalized AO OR use the alpha coefficients: https://github.com/JoonhoLee-Group/ipie/blob/bc74f33751487a034e41a31bd470fe17ccfb0cbf/ipie/utils/from_pyscf.py#L71 you would then need to be very careful to ensure your initial wavefunction is in the correct basis. gen_ipi_input_from_pyscf_chk handles all of this for you, so if you don't want to worry about it I would recomment:


gen_ipie_input_from_pyscf_chk(hamil_file='my-cool-ham.h5', wfn_file='my-cool-wfn.h5')

afqmc = AFQMC.build_from_hdf5(nelec, 'my-cool-ham.h5', 'my-cool-wfn.h5', timestep=my_variable_timestep)
print(afqmc.params.timestep)
fdmalone commented 1 week ago

(this is assuming gen_ipie_input_from_pyscf_chk is working for the molecule you say it fails for in #313

Koberard commented 1 week ago

It's very surprising that the parameters are updated after calling build_afqmc_driver, are you sure:

afqmc.params.dt = timestep
afqmc = build_afqmc_driver(comm, nelec=mol.nelec)
assert afqmc.params.dt == timestep

doesn't result in an assertion error?

Re #313: Are you saying that:

gen_ipie_input_from_pyscf_chk(mf.chkfile, verbose=0) 

does not return an error while

ham = generate_hamiltonian(
    mol,
    mf.mo_coeff,
    mf.get_hcore(),
    mf.mo_coeff,  # should be optional
)

does (for the same molecule)? This is helpful to know.

That is correct, For sime reason building with gen_ipie_input_from_pyscf_chk does not produce an error but using ham = does produce an error for that molecules and some other molecules.

fdmalone commented 1 week ago

Yeah, I imagine there is something funny happening with the MOs. Thanks for raising the issue! We should definitely raise an error if UHF mo coeffs are passed to that function and make error messages more sensible. Does what I suggested work for your workflow? That is, use the gen_ipie_input_from_pyscf_chk and then use afqmc = AFQMC.build_from_hdf5(nelec, 'my-cool-ham.h5', 'my-cool-wfn.h5', timestep=my_variable_timestep) in your script? If so I'll close this and hopefully someone can make the error handling more user friendly.

Koberard commented 1 week ago
print(afqmc.params.timestep)

What do I have to import to run afqmc = AFQMC.build_from_hdf5?

switching from UHF to RHF does not solve the Hamiltonian problem.

fdmalone commented 1 week ago

build_from_hdf5 is a factory method on the AFQMC class: https://github.com/JoonhoLee-Group/ipie/blob/develop/ipie/qmc/afqmc.py#L396 so

from ipie.qmc.afqmc import AFQMC
afqmc = AFQMC.build_from_hdf5(nelec, ham_file, wfn_file, timestep=)
...