Git Product home page Git Product logo

renormalizer's People

Contributors

atxy-blip avatar dependabot[bot] avatar jiangtong1000 avatar jjren avatar liwt31 avatar susyustc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

renormalizer's Issues

Documentation

I think it is time to gradually improve the documentation of Renormalizer and make it more accessible to the community.
Let's begin with the module-level docs first!

bug report of the multi-quantum number code

#146 added the multi-quantum number support.
Recently I am using that part and found something weird, I will call the package starting from that commit as new and the version before as old. And here is what I found for electronic structure calculations. Apparently there is a bug.

H10 (3 Bohr)
old: -4.974258044176154 (M=30)
new: -4.967491721857599 (M=30), -4.967422012064133 (M=50)
FCI: -4.974243429294

H20 (3 Bohr)
old: -9.952918380537831 (M=30)
new: -9.945641599914602 (M=30)

And If I use M=50 for H20, there will be quantum number error reported when doing svd_qn.

Canonicalisation and compression for MPO

Currently, the canonicalization and compression for MPO is different from MPS and MPDM, so I open this issue as a reminder of this problem and hope for a better solution.

Decide which content should be in wiki

The doc in #29 seems to work quite well, and it contains some contents from the project wiki. From my point of view, certain contents such as the installation guide should be in the wiki because I wish other people can modify these contents with ease. The doc instead can provide a link to these contents.

IMO, the contents that should be staying in the wiki are:

  • Installation guide
  • How to read the code

And those that should be moved to the doc:

  • How to develop
  • How to use

Another basis for multi electron on one site

The basis BasisMultiElectron features flexibility, and a down side is that lots of default behavior are not well-defined. For example, the gs method for Mps have to be careful with the specific parameter of the basis:

else:
# only "e_0" is occupied
assert mol_list.basis[isite].sigmaqn[0] == 0
logger.warning("The electron occupies e_0 !!")
ms[0,0,0] = 1.

This continues the discussions in #82 .

I propose to add another basis for the case where multi electron is on the same site. The quantum number of the basis is constantly [0] + [1] * (n-1) and thus creation/annihilation operators and the ground state are well defined.
The basis should be very useful at least in charge transport problems, which justifies the necessity to add a specific class.
The new basis could be named as BasisMultiElectronVac to indicate that the basis includes the vacuum state.
The transform from scheme 4 to MolList2 should use this basis by default for maximum backward compatibility. A flag to determine which basis to use might be added if proved necessary.

Removing support for JSON dump format.

In TdMpsJob JSON and npz dump format are supported. In my experience JSON format is rarely useful, because:

  • It costs lots of disk space
  • It does not support complex number

The only good point about JSON format is that the dumped file is directly readable by text editors such as vim, however, the feature is rarely used.

On the other hand, trying to support JSON leads the inconviences such as the over usage of the cast_float function.

If there is no special need for the JSON format, I'm going to remove support for JSON dump format.

bug in mp.py add

def add(self, other: "MatrixProduct"):
assert self.qntot == other.qntot
assert self.site_num == other.site_num
#assert self.qnidx == other.qnidx
new_mps = self.metacopy()
if other.dtype == backend.complex_dtype:
new_mps.dtype = backend.complex_dtype
if self.is_complex:
new_mps.to_complex(inplace=True)
new_mps.compress_config.update(self.compress_config)
if self.is_mps: # MPS
new_mps[0] = dstack([self[0], other[0]])

In the add in mp.py, the coeff of mps is not checked. I think it may lead to wrong results sometimes, I will come back to this bug soon.
I plan to carefully re-check the coeff stuff and related normalize stuff.

The explicit TD-DMRG/TDH hybrid method will be removed in the future.

As tdvp-based evolution schemes are very robust now and TD-DMRG/TDH could be embedded in tdvp-based schemes implicitly with some virtual bonds M=1, there is no reason to keep the explicit TD-DMRG/TDH algorithm anymore. I plan to remove it in the near future.
Some coding is needed:

  1. A new MPO scheme which puts the Hartree DoFs at the end of the chain.

improve periodic hmpo in scheme 4

  • It seems period function does not support scheme 4. Actually in scheme 4 where all electronic DOF is in the same site a much different approach should be used for periodic boundary condition MPO.
  • If scheme 4 is taken into consideration, it'll be natural to make period an option of Mpo. Another reason for this is that other calculations may need to run in periodic conditions either.
  • Adding some tests about the validity of the MPO should be nice.

Also a side note: it is not necessary to use super() for subclass methods every time. Do this only when the subclass has overwritten the ancestor's method and the overwritten method is desired.

Originally posted by @liwt31 in #55 (comment)

gpu not working for cv-dmrg

We made several commits at #66, after my commit enable cv for gpu, some more commits for bugfix was made, and somehow, resulted in the malfunction of gpu for cv, sorry for not checking the following code changes, later I will find why @jjren @liwt31

mismatch between the ouput ground state energy and mps

The optimize_mps returns the macro_iteration_result and res_mps. If we evaluate the energy by res_mps.expectation(mpo), the energy is not necessarily equal to min(macro_iteration_result). It is not even necessarily contained in macro_iteration_result. For instance, if the minimal energy is not obtained in the last sweep, but in the middle sweeps (energy does not decrease monotonically with the number of sweeps), then we obtainmin(macro_iteration_result)$\neq$res_mps.expectation(mpo)

Use Mollist2 as internal system information data structure

This is an extension to the discussion in #82 , in which I proposed to use MolList2 as the internal data structure to keep track of system information and remove the original MPO construction function. At that time, major concerns arise on the performance in large systems. During my usage of the module for about 3 months, I found no performance problem, because MPO construction is always so small a portion of the total time cost. After all, the original code is designed for Holstein Hamiltonian which is almost the simplest Hamiltonian we can think of. When constructing these simple Hamiltonian, the general MPO construction routine is generally efficient. One thing that worries me is that I feel (no benchmark, just feeling) the algorithm is a little bit slow when constructing a lot of simple MPOs such as in the case of calc_reduced_density_matrix, this can certainly be improved but has a lower priority.
Of course, any discussions on this issue are still welcome.

This would a very big update. Contents include:

  • Use MolList2 as internal system information data structure
  • Remove chain representation of MPO #90
  • Remove explicit TD-DMRG/TDH algorithm #61 . In the original issue, the discussion is postponed. And in #82 it is already proposed that people should move unimportant modes to the end of the MPS chain as an alternative. To fully incorporate the algorithm with the new Mollist2 backend, a moderate endeavor of coding is required, which may not be justified if the feature is going to be removed.
  • Remove the quasi-boson feature which is seldomly used and costs lots of time in the test suite #25 .
  • Also, a possible update in the interface of MolList2 as discussed in #97 . The details will be updated in a comment to this issue.

How to construct time-dependent MPOs with the general optimal method directly?

Sometimes we need to deal with time-dependent Hamiltonian(eg. the effective Hamiltonian in Hierarchy of Matrix Product States). I have tried two methods, but each of them has some drawbacks.

  1. Devide the operators into two groups, the time-independent group and the time-dependent group. The MPO of the former group is generated when the model is initiated, and the MPO of the latter group is generated each time during the evolution. The two MPOs are added directly. Since the time-dependent MPO is much simpler, the construction may be not time-consuming. But the direct adding makes the bond dimension of the total MPO much larger, so the result is not the optimal MPO.
  2. Generate the MPO of the total Hamiltonian from the operator list each time during the evolution. The resulting MPO is optimal, but it is time-consuming to generate the MPO from the total Hamiltonian frequently.
    MPO construction

So can we construct time-dependent numerical MPOs from optimal symbolic MPOs with parameters(time)?

Variational Compress Method

Rewrite the variational compress method in the old ephMPS in Renormalizer.
MPO \times MPS with a large bond dimension consumes a lot of memory. Variational compress method could help.

The 3rd-party libraries used in Renormalizer

There are several 3rd-party libraries used in Renormalizer.
I would like to list them all and figure out their roles in the whole package.
Please help to check and finish it. @liwt31

  1. /lib/davidson.py
    https://github.com/pyscf/pyscf/blob/master/pyscf/lib/linalg_helper.py
    davidson diagonalization

  2. lib/_ivp
    scipy.integrate
    solve initial value problem
    (I guess this file is modified for Cupy, right? If the scipy.integrate is upgraded, what should we do?)

  3. lib/krylov.py
    https://github.com/cmendl/pytenet/blob/master/pytenet/krylov.py
    Krylov space method to calculate e^{iH\tau} \Psi

  4. utils/qutip_utils.py
    It seems that qutip_utils.py calculates the matrix element of some basic operators.

Compress the test suite

Currently we have too many tests. A successful build takes 37 mins according to travis CI.

It would be ideal if we can cut or modify some of the tests. I think ~20 min build time is more reasonable.

Tests that take more than 10 s according to travis CI:

110.64s call     renormalizer/spectra/tests/test_spectra.py::test_zero_exact_emi
100.36s call     renormalizer/mps/tests/test_quasiboson.py::test_quasiboson_solver[value0]
88.82s call     renormalizer/spectra/tests/test_hybrid_spectra.py::test_hybrid_emi[1-mol_list1-ZeroExactEmi.npy-0.01]
88.52s call     renormalizer/spectra/tests/test_hybrid_spectra.py::test_hybrid_emi[2-mol_list3-ZeroExactEmi.npy-0.01]
71.81s call     renormalizer/mps/tdh/tests/test_tdh.py::test_TDH_ZT_emi
67.89s call     renormalizer/mps/tests/test_evolve.py::test_finite_t_spectra_emi_TDVP[EvolveMethod.tdvp_mctdh_new-85-4-None-0.01-2]
67.41s call     renormalizer/spectra/tests/test_hybrid_ft_spectra.py::test_ft_hybrid_dmrg_tdh[mol_list0-abs-hybrid_FT_abs_pure.npy]
64.29s call     renormalizer/spectra/tests/test_hybrid_spectra.py::test_hybrid_emi[2-mol_list2-hybrid_ZTemi_prop.npy-0.001]
63.15s call     renormalizer/spectra/tests/test_hybrid_spectra.py::test_Exact_Spectra_hybrid_TDDMRG_TDH
62.44s call     renormalizer/spectra/tests/test_hybrid_spectra.py::test_hybrid_emi[1-mol_list0-hybrid_ZTemi_prop.npy-0.001]
53.94s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-True-None-mol_list1-0.0853413581416-occ_std1-0.005]
53.36s call     renormalizer/spectra/tests/test_hybrid_ft_spectra.py::test_ft_hybrid_dmrg_tdh[mol_list2-emi-hybrid_FT_emi_pure.npy]
51.73s call     renormalizer/mps/tests/test_evolve.py::test_ZeroTcorr_TDVP[EvolveMethod.tdvp_ps-15.0-True-0.01]
50.24s call     renormalizer/mps/tests/test_mps_solver.py::test_multistate
44.91s call     renormalizer/transport/tests/test_autocorr.py::test_autocorr[None-0.01]
40.62s call     renormalizer/transport/tests/test_hybrid_dynamics.py::test_FT_dynamics_hybrid_TDDMRG_TDH[10-3]
39.47s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-False-None-mol_list1-0.0853413581416-occ_std1-0.005]
37.81s call     renormalizer/transport/tests/test_hybrid_dynamics.py::test_FT_dynamics_hybrid_TDDMRG_TDH[10-4]
36.81s call     renormalizer/transport/tests/test_autocorr.py::test_autocorr[50-0.01]
34.19s call     renormalizer/spectra/tests/test_hybrid_ft_spectra.py::test_ft_hybrid_dmrg_tdh[mol_list3-emi-hybrid_FT_emi_hybrid.npy]
33.86s call     renormalizer/mps/tests/test_evolve.py::test_ZeroTcorr_TDVP[EvolveMethod.tdvp_mctdh_new-2.0-None-0.01]
33.30s call     renormalizer/spectra/tests/test_hybrid_ft_spectra.py::test_ft_hybrid_dmrg_tdh[mol_list1-abs-hybrid_FT_abs_hybrid.npy]
31.81s call     renormalizer/mps/tests/test_evolve.py::test_ZeroTcorr_TDVP[EvolveMethod.tdvp_ps-15.0-False-0.01]
30.95s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-True-100-mol_list1-0.0853413581416-occ_std1-0.005]
27.39s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-True-None-mol_list0-0.0853441664951-occ_std0-0.005]
25.53s call     renormalizer/mps/tests/test_evolve.py::test_finite_t_spectra_emi_TDVP[EvolveMethod.tdvp_ps-30-30-True-0.01-1]
24.03s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.prop_and_compress-None-None-mol_list1-0.0853413581416-occ_std1-0.005]
21.84s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-False-100-mol_list1-0.0853413581416-occ_std1-0.005]
21.16s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-False-None-mol_list0-0.0853441664951-occ_std0-0.005]
20.67s call     renormalizer/transport/tests/test_hybrid_dynamics.py::test_FT_dynamics_hybrid_TDDMRG_TDH[5-3]
20.38s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs[1-svd-ph_info2-0.01]
20.07s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs_mposcheme3[1-svd-ph_info2-0.01]
19.34s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs[2-svd-ph_info3-0.01]
19.02s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs_mposcheme3[2-svd-ph_info3-0.01]
18.60s call     renormalizer/transport/tests/test_hybrid_dynamics.py::test_FT_dynamics_hybrid_TDDMRG_TDH[5-4]
18.54s call     renormalizer/mps/tests/test_evolve.py::test_finite_t_spectra_emi_TDVP[EvolveMethod.tdvp_ps-30-30-False-0.01-1]
17.67s call     renormalizer/transport/tests/test_fullmpdm.py::test_dynamics[0-4-20]
17.43s call     renormalizer/spectra/tests/test_spectra.py::test_finite_t_spectra_emi[2-svd-ph_info1-0.01]
17.02s call     renormalizer/transport/tests/test_hybrid_dynamics.py::test_zt[10-3]
16.30s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-True-100-mol_list0-0.0853441664951-occ_std0-0.005]
15.58s call     renormalizer/transport/tests/test_transport.py::test_adaptive_zero_t[0.1-EvolveMethod.tdvp_ps]
15.04s call     renormalizer/mps/tdh/tests/test_dynamics_TDH.py::test_FT_dynamics_TDH
14.33s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.prop_and_compress-None-None-mol_list0-0.0853441664951-occ_std0-0.005]
14.06s call     renormalizer/transport/tests/test_hybrid_dynamics.py::test_zt[10-4]
13.58s call     renormalizer/mps/tests/test_quasiboson.py::test_quasiboson_solver[value1]
12.85s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs[1-svd-ph_info0-0.01]
12.63s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.prop_and_compress-None-100-mol_list1-0.0853413581416-occ_std1-0.005]
12.38s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs_mposcheme3[1-svd-ph_info0-0.001]
12.33s call     renormalizer/spectra/tests/test_spectra.py::test_finite_t_spectra_abs[2-svd-ph_info1-0.01]
11.93s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs[2-svd-ph_info1-0.01]
11.81s call     renormalizer/mps/tests/test_mpdm.py::test_thermal_prop[EvolveMethod.tdvp_ps-False-100-mol_list0-0.0853441664951-occ_std0-0.005]
11.71s call     renormalizer/spectra/tests/test_spectra.py::test_zero_t_abs_mposcheme3[2-svd-ph_info1-0.001]
11.54s call     renormalizer/spectra/tests/test_hybrid_spectra.py::test_hybrid_abs[2-mol_list1-ZeroTabs_2svd.npy-0.01]
11.28s call     renormalizer/transport/tests/test_transport.py::test_evolve[5-0.8-0.00387-ph_info0-4-2-50]
10.75s call     renormalizer/spectra/tests/test_spectra.py::test_finite_t_spectra_emi[2-svd-ph_info0-0.01]
10.37s call     renormalizer/transport/tests/test_transport.py::test_bandlimit_zero_t[3-EvolveMethod.tdvp_ps-2-100-0.001]

Determine an official abbreviation for `renormalizer`

In certain cases, we will have to refer to the project name. For example:

GPU_KEY = "EPHMPS_GPU"

This is legacy code and an important reason why I haven't updated it is that renaming it to RENORMALIZER_GPU will make it more difficult to use in the command line.
Maybe an abbreviation for renormalizer can solve this. Some brainstorm results:

  • renmlzer
  • renmlz
  • rnmlz
  • reno
  • ren
  • renorm
  • lizer

and so on...

Refactor how physical observables are calculated in TdMpsJob

In the early days of the project, I decided to store all previously evolved mps in memory, and obtain physical observable from the mps, which is proved to be a design failure, leading to ugly things like clear_memory.

A more natural way is to allow users to choose which physical observables to calculate in the time evolution job and discard previously evolved mps after the observables are obtained.

`approx_propagator` in `MpDm` seems obsolete

In MpDm there is a class method approx_propagator which tries to construct e^-{iHt} explicitly.

@classmethod
def approx_propagator(cls, mpo, dt, thresh=0):
"""
e^-iHdt : approximate propagator MPO from Runge-Kutta methods
"""
mps = Mps()
mps.mol_list = mpo.mol_list
mps.dim = [1] * (mpo.site_num + 1)
mps.qn = [[0]] * (mpo.site_num + 1)
mps.qnidx = mpo.site_num - 1
mps.qntot = 0
mps.threshold = thresh
for impo in range(mpo.site_num):
ms = xp.ones((1, mpo[impo].shape[1], 1), dtype=backend.complex_dtype)
mps.append(ms)
approx_mpo_t0 = cls.from_mps(mps)
approx_mpo = approx_mpo_t0.evolve(mpo, dt)
return approx_mpo

Currently, the code is barely used, only in ThermalProp. But sadly the optional argument is not used either and there seems to be a bug that makes the argument take no effect.

def __init__(self, init_mpdm, h_mpo, exact=False, space="GS", evolve_config=None, approx_eiht=None, dump_dir=None,
job_name=None):
self.init_mpdm: MpDm = init_mpdm
self.h_mpo = h_mpo
self.exact = exact
assert space in ["GS", "EX"]
self.space = space
self.approx_eiht = approx_eiht
# calculated during propagation
self.approx_eihpt = None
self.energies = []
self._e_occupations_array = []
self._ph_occupations_array = []
super().__init__(evolve_config, dump_dir, job_name)

IMO the approach of constructing the propagator is inefficient. The argument is the same as multiplying matrices one by one rather than constructing large tensor $H$.

So, I'm thinking of removing the code, which I think will also lead to simplifications of the evolve method of Mps:

def evolve(self, mpo, evolve_dt, approx_eiht=None):

Remove the chain representation?

When constructing MPO based on MolList it is possible to choose star representation or chain representation. As far as I know, the chain representation is seldomly used and not well tested. Besides, the task of choosing representation would be advanced to writing the model if MolList2 is used and the inconsistency constitutes a barrier to combine MolList and MolList2.
It'll probably be a good idea to remove the chain representation, which IMO is a legacy of the old ephMPS.

modify ft cv emission part

  • finite temperature emission still need further modification, cooperating with different imaginary evolution configs
  • enable dumping density operator for further analysis.
  • add some test for emission

Do not use energy conservation as a criteria in imaginary time evolution

new_mps1 = compressed_sum(scaled_termlist[:-1])._dmrg_normalize()
new_mps2 = compressed_sum([new_mps1, scaled_termlist[-1]])._dmrg_normalize()
angle = new_mps1.angle(new_mps2)
energy1 = self.expectation(mpo)
energy2 = new_mps1.expectation(mpo)
rtol = config.adaptive_rtol # default to 1e-3
p = (rtol / (np.sqrt(2 * abs(1 - angle)) + 1e-30)) ** 0.2 * 0.8
logger.debug(f"angle: {angle}. e1: {energy1}. e2: {energy2}, p: {p}")
d_energy = config.d_energy
if abs(energy1 - energy2) < d_energy and 0.5 < p:
# converged
if abs(config.evolve_dt - evolve_dt) / abs(evolve_dt) < 1e-5:
# equal evolve_dt

In the imaginary time evolution, energy conservation should not be adopted as a criterion to adapt the time step size in both P&C and TDVP, I will fix this and modify the adaptive algorithm.
In my opinion, the wavefunction only is enough to determine the adaptive time step, because if the wavefunction has error O(\epsilon), the total energy has error O(\epsilon) too.

What kind of operators does this efficient hash algorithm support?

def expectations(self, mpos) -> np.ndarray:
if len(mpos) < 3:
return np.array([self.expectation(mpo) for mpo in mpos])
assert 2 < len(mpos)
# id can be used as efficient hash because of `Matrix` implementation
mpo_ids = np.array([[id(m) for m in mpo] for mpo in mpos])
common_mpo_ids = mpo_ids[0].copy()
mpo0_unique_idx = np.where(np.sum(mpo_ids == common_mpo_ids, axis=0) == 1)[0][0]
common_mpo_ids[mpo0_unique_idx] = mpo_ids[1][mpo0_unique_idx]

@liwt31

mpi4py vs. multiprocessing of DDMRG

  • currently DDMRG is parallelized using the multiprocessing module for its clean API and easy usage
  • mpi4py is more sophisticated and is considered to replace multiprocessing to gain more speed and also allows parallelization across clusters.

A draft for the logo

image

The image is mostly inspired by:
image
according to wikipedia it is licensed under the Creative Commons Attribution 4.0 International license.

The font for "renormalizer" is the "transformer font" from this website. It is said to be "100% free" and if I understood correctly there is no issue with the license.

If this logo is OK we can put it into our document and readme file.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.