oimeitei / quemb

QuEmb is an open-source tool for efficient quantum chemistry simulation of large molecules and solids (1D and 2D periodic systems) via bootstrap embedding technique.
Apache License 2.0
4 stars 6 forks source link

Enable whole testsuite #53

Open mcocdawc opened 2 days ago

mcocdawc commented 2 days ago

Merge after https://github.com/oimeitei/quemb/pull/51

mcocdawc commented 2 hours ago

Currently the test-suite fails with

FAILED ube-oneshot_test.py::TestOneShot_Unrestricted::test_hexene_anion_sto3g_frz_ben - AttributeError: /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/site-packages/pyscf/lib/libao2mo.so: undefined symbol: AO2MOrestore_nr4to1_gen
FAILED ube-oneshot_test.py::TestOneShot_Unrestricted::test_hexene_anion_sto3g_unfrz_ben - AttributeError: /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/site-packages/pyscf/lib/libao2mo.so: undefined symbol: AO2MOrestore_nr4to1_gen
FAILED ube-oneshot_test.py::TestOneShot_Unrestricted::test_hexene_cation_sto3g_frz_ben - AttributeError: /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/site-packages/pyscf/lib/libao2mo.so: undefined symbol: AO2MOrestore_nr4to1_gen
FAILED ube-oneshot_test.py::TestOneShot_Unrestricted::test_hexene_cation_sto3g_unfrz_ben - AttributeError: /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/site-packages/pyscf/lib/libao2mo.so: undefined symbol: AO2MOrestore_nr4to1_gen

after talking to @mscho527 this can be fixed after doing some custom changes to pyscf in the UHF code.

It would be great if one could install QuEmb just by writing pip install without any fiddling around. I see basically three possibilities how to achieve this (ordered from most to least preferred):

  1. Merge the QuEmb changes back to pyscf. (assuming they are advantageous in general)
  2. Monkey-patch the particular function inside the QuEmb code, and overwriting the imported pyscf function.
  3. Get a custom fork of pyscf, do the modifications there and refer to that repo as dependency of QuEmb. As done here for the custom libdmet

What do you @lweisburn @mscho527 think? As far as I know you are the most knowledgeable about this part of the code.

mcocdawc commented 2 hours ago

@ShaunWeatherly Unfortunately tests/dmrg_molBE_test.py is also failing :-(

FAILED dmrg_molBE_test.py::TestBE_DMRG::test_h8_sto3g_pipek - UnboundLocalError: cannot access local variable 'rdm1_tmp' where it is not associated with a value
ShaunWeatherly commented 1 hour ago

@ShaunWeatherly Unfortunately tests/dmrg_molBE_test.py is also failing :-(

FAILED dmrg_molBE_test.py::TestBE_DMRG::test_h8_sto3g_pipek - UnboundLocalError: cannot access local variable 'rdm1_tmp' where it is not associated with a value

@mcocdawc Unfortunately I think the easiest way to satisfy all the test conditions and enable a simple pip install quemb is to just ignore the optional dependencies.

I'm not 100% sure but I think your test is failing because you're missing the core dmrg kernels, which you have to install and configure separately as block2 or stackblock. Pyscf's dmrgscf module is just a kind of wrapper to these packages, and so won't work without them.

But rather than requiring the user to find, configure, and install all these optional dependencies, I think it makes the most sense to keep them optional and skip their associated unit tests if the dependencies aren't found (imo).

oimeitei commented 1 hour ago

@mcocdawc can you change the name src to python instead? I think moving the two into this should not create a problem as long as you can do import kbe or import molbe. Otherwise there are many part of the codes of that test does not touch and so should check it.

mcocdawc commented 1 hour ago

@oimeitei

can you change the name src to python instead?

The whole python ecosystem assumes either a flat-layout, which we had before, or a src-layout, which is recommended for larger projects. We make our life unnecessarily difficult if we deviate from this tooling.

I think moving the two into this should not create a problem as long as you can do import kbe or import molbe. Otherwise there are many part of the codes of that test does not touch and so should check it.

The whole point of this change is that you cannot do import kbe or import molbe without installing. This prevents some "it-runs-fine-on-my-machine"-problems. In particular there was recently an undergraduate working together with @ShaunWeatherly , who encountered such a problem, because we never did pip install as part of testing. For more thorough examples see the discussion here.

Otherwise there are many part of the codes of that test does not touch and so should check it.

As soon as you installed it, the whole test-suite can be executed. (minus the optional packages, but that has nothing to do with flat-layout vs. src-layout.)

mcocdawc commented 1 hour ago

@ShaunWeatherly

But rather than requiring the user to find, configure, and install all these optional dependencies, I think it makes the most sense to keep them optional and skip their associated unit tests if the dependencies aren't found (imo).

I fully agree that a new user of BE, who is interested in running it with just CCSD should not be required to compile Block or other DMRG codes. So keeping it optional really makes sense for this case.

Still, if we can compile Block as part of our test-suite, or obtain precompiled binaries, or obtain a docker image with precompiled Block, then I think it makes sense to test dmrg_molBE_test.py automatically.

mscho527 commented 48 minutes ago

@ShaunWeatherly

But rather than requiring the user to find, configure, and install all these optional dependencies, I think it makes the most sense to keep them optional and skip their associated unit tests if the dependencies aren't found (imo).

I fully agree that a new user of BE, who is interested in running it with just CCSD should not be required to compile Block or other DMRG codes. So keeping it optional really makes sense for this case.

Still, if we can compile Block as part of our test-suite, or obtain precompiled binaries, or obtain a docker image with precompiled Block, then I think it makes sense to test dmrg_molBE_test.py automatically.

@ShaunWeatherly would adding pip install block2 resolve the issue @mcocdawc is seeing? if the only concern is the time it takes for github action to install the dependencies, the caches (which we already have) should minimize the impact. i would support activating the test if this is the case.

mcocdawc commented 44 minutes ago

@ShaunWeatherly would adding pip install block2 resolve the issue @mcocdawc is seeing?

I am testing this right now. If one additionally defines BLOCKEXE = 'block2main' for the dmrgscf settings, then one can actually run it. But the error of

FAILED tests/dmrg_molBE_test.py::TestBE_DMRG::test_h8_sto3g_pipek - UnboundLocalError: cannot access local variable 'rdm1_tmp' where it is not associated with a value

persists. :-(

PS: the installation via pip install block2 is super fast.

ShaunWeatherly commented 40 minutes ago

@ShaunWeatherly would adding pip install block2 resolve the issue @mcocdawc is seeing?

I am testing this right now. If one additionally defines BLOCKEXE = 'block2main' for the dmrgscf settings, then one can actually run it. But the error of

FAILED tests/dmrg_molBE_test.py::TestBE_DMRG::test_h8_sto3g_pipek - UnboundLocalError: cannot access local variable 'rdm1_tmp' where it is not associated with a value

persists. :-(

A tragedy! Would you mind giving some more info so I can try and recreate the issue? eg what does your settings.py look like and do you modify block2 at all after doing pip install block2?

Also, are you able to get pyscf.dmrgscf to run isolated from quemb?

mcocdawc commented 15 minutes ago

So the reason for the failing test is that DMRG itself is failing. rdm1_tmp is not defined, since that error is only printed and not raised. Currently we have:

            try:
                rdm1_tmp, rdm2s = solve_block2(fobj._mf,
                                                fobj.nsocc,
                                                frag_scratch = tmp,
                                                **solver_kwargs_)
            except Exception as inst:
                print(f"Fragment DMRG solver failed with Exception: {type(inst)}\n", inst, flush=True)

            finally:
                if solver_kwargs_.pop('force_cleanup', False):
                    os.system('rm -r '+ os.path.join(tmp,'F.*'))
                    os.system('rm -r '+ os.path.join(tmp,'FCIDUMP*'))
                    os.system('rm -r '+ os.path.join(tmp,'node*'))

if the error is actually raised

            try:
                rdm1_tmp, rdm2s = solve_block2(
                    fobj._mf, fobj.nsocc, frag_scratch = tmp, **solver_kwargs_)
            except Exception as inst:
                raise inst
            finally:
                  # cleanup steps are still executed

then the error gets immediately obvious at the point of solve_block2 where it errors out with

schedule                  Sweep   0-   9 : Mmps =    25 Noise =     0.001 DavTol =     1e-05
                          Sweep  10-  19 : Mmps =    50 Noise =     0.001 DavTol =     1e-05
                          Sweep  20-  29 : Mmps =   100 Noise =    0.0001 DavTol =     1e-06
                          Sweep  30-  39 : Mmps =   100 Noise =     1e-05 DavTol =     1e-07
                          Sweep  40-  49 : Mmps =   100 Noise =     1e-05 DavTol =     1e-08
                          Sweep  50-  59 : Mmps =   100 Noise =         0 DavTol =     1e-08
irrep                                                            1
********************************** INPUT END   **********************************

SPIN ADAPTED - REAL DOMAIN - DOUBLE PREC
qc mpo type =  QCTypes.Conventional
Traceback (most recent call last):
  File "/home/mcocdawc/.venv/bin/block2main", line 653, in <module>
    init_memory(isize=int(memory * 0.1),
MemoryError: std::bad_alloc

Steps to reproduce: Care: the first command will uninstall your current quemb etc. stack

# I assume you reside in `quemb/` and have `enable_whole_testsuite` checked out

# CARE with the next command
pip uninstall dmrgscf block2 libdmet quemb

pip install block2
pip install git+https://github.com/pyscf/dmrgscf
PYSCFHOME=$(pip show pyscf-dmrgscf | grep 'Location' | tr ' ' '\n' | tail -n 1)
vi ${PYSCFHOME}/pyscf/dmrgscf/settings.py    # replace with the settings.py shown below
pip install .
pytest tests/dmrg_molBE_test.py

my settings.py

#
# This file is an example to set the environment.
# The configs will be used in dmrgci.py and chemps2.py
#

import os
from pyscf import lib

# To install Block as the FCI solver for CASSCF, see
#       http://sunqm.github.io/Block/build.html
#       https://github.com/sanshar/Block
BLOCKEXE = 'block2main'
BLOCKEXE_COMPRESS_NEVPT = 'block2main'
#BLOCKSCRATCHDIR = os.path.join('./scratch', str(os.getpid()))
BLOCKSCRATCHDIR = os.path.join(lib.param.TMPDIR, str(os.getpid()))
#BLOCKRUNTIMEDIR = '.'
BLOCKRUNTIMEDIR = str(os.getpid())
MPIPREFIX = ''  # change to srun for SLURM job system
BLOCKVERSION = None

# Use ChemPS2 as the FCI solver for CASSCF
# building PyChemPS2, a python module will be generated in
#       /path/to/ChemPS2/build/PyChemPS2
# see more details in the ChemPS2 document
#       https://github.com/SebWouters/CheMPS2
PYCHEMPS2BIN = '/path/to/CheMPS2/build/PyCheMPS2/PyCheMPS2.so'