TWFFastDerivWrapper: add support for MultiDet wfs - #5398
Conversation
|
Thanks for laying out a roadmap. Would be excellent to have this of course. Please do an absolute minimum implementation first, to get something working. Likely Ray has already thought this through , so check with him if you have not already. In case they are needed, add accessor functions to get excitation data. Do not break encapsulation. Forgive the reminder, but please start writing units tests early. i.e. Now. This will make reviewing and merging easier and faster. For this kind of code it is possible to achieve excellent coverage. Do not rely in integration tests. Happy to discuss further if you want. |
|
@prckent thanks for the feedback; I have been in touch with Ray about this
I'm trying to come up with a clean way to do this. For the multidet case, we will need to do something similar with at least the I'm also trying to decide how to have the singledet and multidet code paths live nicely together. |
|
update on status: I've been assuming that the I compute terms like these for each DiracDeterminant in computeMDDerivatives_ExcDets, and then I do the necessary contraction over the full list of SlaterDets in computeMDDerivatives_total, which returns If I'm reading the code correctly, then in the single-det code path, I think this is mostly on the right track, but I'd welcome any feedback if any of what I've described seems incorrect. @rcclay said that there should be some reference values already present in test_ion_derivs.cpp, so my next step is to work on checking the new functions against those values. My first attempt was not successful, but I'm not at all confident that I'm calculating/comparing the right thing. I added a call to the TWFFastDerivWrapper multidet function here (branched from this PR source because I don't want to make too much of a mess with the branch history if it takes a while to figure this out) with that change, the output I see from the test is which doesn't seem to match any of the reference values in this test. The wf_grad values are close enough that I suspect that these are at least representing sort of the same thing, either with some discrepancy in exactly what quantity is being compared, or some small-ish term that isn't being accounted for in the new code. Another thing I'm aware of is that I could try to make a multi-det test that more closely mirrors this single-det one. (I'm not sure if I could accomplish the same thing by building a separate Hamiltonian that only includes a single term; I'd need to look at everything in more detail to figure out whether excluding the other terms would cause issues, and that would probably take more time than just adding the matrix evaluation as the single-det test does) |
|
@kgasperich I think the path forward here is to first spot check one of the finite difference reference values just to make sure it's OK. I'm sure it is, but if there's a chance it's wrong, that concern needs to be killed now. Step 2 will be to focus entirely on making sure that wfgrad comes out right. That's the simplest/most transparent quantity, and also dodges issues related to the fact that only some of the hamiltonian quantities have ion derivatives computed in this framework. I think your plan of making a more fine grained unit test a la single det code will probably save some debugging time in the long run. Also gives you clean and independent checks of the kinetic and nonlocal force contributions. |
|
@rcclay thanks!
Is there an existing test or example somewhere that performs this? (I assume there's something somewhere in
ok, this sounds good; I will work on this part for now and update as it progresses! |
|
I fixed two small bugs, and the new code seems to be giving the correct values now. I still get a slight discrepancy compared to numerical derivatives I computed using WFtester (I used a two-point central difference with delta of +/- 0.0001 for all dims). After these fixes, I started refactoring the new multidet code for the ionic derivatives (there is/was a lot of redundant computation). I'm working on that in another branch, and once I fix that issue I'll merge it back into this branch |
|
I see that a bunch of the complex tests are failing because Catch::Approx doesn't play nicely with complex types. I can remove those and then use |
|
The test should build now for I removed the part of the test that verifies that If there's a good reason to keep |
|
Just in case it's not clear from the comments, for the multidet derivatives we need terms like I initially made one function ( The The other two types of terms still need to be computed once for each ion dim, so those are handled by |
|
RE: Catch. We have our own ComplexApprox if that helps. |
rcclay
left a comment
There was a problem hiding this comment.
I think this looks fine. Logic is sound, design is contained to TWFFastDerivWrapper and is consistent with what is already there, and so has minimal impact to rest of code for a big improvement in capability. I indicated some examples of incomplete documentation that should be addressed--documentation of innards of computeMDDerivatives_dmu should be more verbose. Also there are a few comments in the code along the lines of "FIX ME" and "TODO" which should be revisited.
| // IndexType ndet = multidiracdet_i->getNumDets(); | ||
| IndexType ndet = multidiracdet_i.getNumDets(); | ||
|
|
||
| /// FIXME: set these correctly; decide how to index into nocc if not contiguous within nOcc |
There was a problem hiding this comment.
It's more of a possible performance improvement than a correctness issue.
Everything works now assuming that the orbital dimension of any matrix is either
- all of the
Nparticleorbs (i.e. occupied in the reference det) in order - all of the virtual orbs (i.e.
OrbitalSetSize - Nparticle) in order - the concatenation of [1] and [2] (i.e. all orbs in order)
For improved performance, there is the simple case where we have e.g. 10 virtuals, but we only ever excite into the first two of these. In this case, it's a simple basis truncation that could be handled very early in the construction of SPOSets, wavefunctions, etc. or even as a simple processing of input files; this would not make any difference in the current code.
There might also be a case where we have 10 virtuals, but we only ever excite into the second and sixth one. This corresponds to maybe a slightly less trivial pre-processing like the one described above where the relevant virtuals comprise a contiguous set from the start of the full set of virtuals.
With an extra level of redirection, we could handle things like this within the TWFFastDerivWrapper, and this would reduce the amount of useless work we'd do over unused orbitals.
We could do the same thing (in some places) with the occupied orbitals that we're exciting out of.
For occupied orbs, there are some intermediate quantities where we contract over the full set of ground-state orbitals, so we would need at least some matrices to be represented in that full space, but there are other quantities where we only need to consider the ones that appear as holes in the excited dets.
In the table method code for computing det ratios, this is simple, because the final quantity we need in the space of hole/particle indices is just Minv.M, so each element is a single gemv, and we can just do the ones we need rather than doing a full gemm.
For the quantities here, we could do something similar and only compute the matrix elements we need, but on my first implementation attempt that seemed like it would get a bit too messy.
Since then, I've found some more compact ways to represent some of the quantities we need (this can be seen in the difference between computeMDDerivatives_ExcDets and computeMDDerivatives_dmu). It seems more feasible now, but I haven't yet worked out exactly what it would save us in terms of scaling, and I'm not sure what the cost of the extra level of redirection would be.
Under the broader umbrella of performance considerations, there are also some things that we could avoid fully recomputing after each particle move (definitely the Minv and Minv.Mvirt, and possibly some others?). Also, I mostly implemented the _dmu and _Obs functions in a way that is easy to follow, but this isn't necessarily the most efficient; eventually it will be worth taking a closer look at this to see if we're leaving any easy performance gains on the table.
| // X3 = Minv_B [occ, occ+virt] | ||
| // X4 = Minv_dB [occ, occ+virt] | ||
|
|
||
| // O is all occ orbs; o is occ orbs that appear as holes in exc. list; e is all elecs; v is virt orbs that appear as particles in exc. list |
There was a problem hiding this comment.
For the sake of posterity, can you document this a little better? Latex expression, or reference to equation. This is correct, but it took a while to unpack. Looks like the documentation near lines 670 could be appropriated.
There was a problem hiding this comment.
yes, I'll go through the comments again and try to make them clearer.
|
@rcclay I'd like to remove |
|
@kgasperich Sure. Slash away. Actually, it just hit me. While we are here, can you hack something together to see if the multideterminant+Jastrow code path also works? Some reference values should already be floating around, albeit commented out. It should by construction, but if it doesn't, we need to block off that code path if it's not fixed in this PR. |
Good catch; I had forgotten to check that. I've added two new tests for md+jastrow: one is with the cn.msd-wfj.xml that was already present, and the other is with a new cn.msd-1det-wfj.xml that uses the same MOs and jastrow as the cn.wfj.xml (so we can check against the reference values that are already known), but it has a multidet block (with a single det) so that it will be treated as a multidet wavefunction in the wrapper (I wanted to make sure that it would gracefully handle a single-det wavefunction since some of the stuff involves only computing quantities for excited dets, and then adding on the ground state det separately) I also removed the old unused |
|
After making those changes, I think I actually prefer the single MSD ( |
|
Test this please |
|
Test this please |
Proposed changes
The plan is to extend the functionality of the TWFFastDerivWrapper to be able to handle MultiDeterminant wavefunctions (based on https://doi.org/10.1063/1.4948778).
This will probably just be a simple reference implementation at first, with some refactoring/optimization to come later if needed.
TODO:
(could make some container/struct to hold pointers to the required data, but maybe simpler to just have a pointer to the MultiDiracDeterminant?)ndets_per_excitation_level_detDatauniquePairswe might be able to use the specific pairs, but for first ref implementation I will probably just use the full cartesian product ofholes x particles(not sure if this is available elsewhere, but we can generate it from the pairs)DetSignsonly needed when we're contracting/summing over dets; we can pass it all the way through and include it in the terms for each excited det, but can also keep at the level of the alpha/beta CI coefs and use it when we do theval = data_alpha[a]*signs_alpha[a] * CI_coeffs_ab[a,b] * data_beta[b]*signs_beta[b]std::vector<const MultiSlaterDetTableMethod*> slaterdets_to wrapper; access through there (also make sure SPOSets from MultiDiracDets in MultiSlaterDet are added to the wrapper)TWFFastDerivWrapper::addMultiSlaterDet; access MultiDiracDets through there; add necessary SPOSets at same timedecide how to handle MultiSlaterDet info (can pass alpha/beta MultiDiracDet individually, but will need to be able to associate the MultiSlaterDet with the MultiDiracDets; maybe better to just add the MultiSlaterDet directly and then add the constituent MultiDiracDets through the MultiSlaterDet)computeMDDerivativein progress: need to add some small matrix ops, verify dims of some inputsconsider adding something similar to SmallMatrixDetCalculator for small matrix inversionin progress: still need to contract alpha/beta det info with CI coefsevaluateIonDerivsFastin same file)What type(s) of changes does this code introduce?
Delete the items that do not apply
Does this introduce a breaking change?
What systems has this change been tested on?
Checklist
Update the following with a yes where the items apply. If you're unsure about any of them, don't hesitate to ask. This is
simply a reminder of what we are going to look for before merging your code.