Skip to content

Conversation

@JonathonMisiewicz
Copy link
Contributor

@JonathonMisiewicz JonathonMisiewicz commented Sep 23, 2021

Description

In preparation for some PRs adding EDIIS and ADIIS to Psi, this PR moves the compute_orbital_gradient functions, which call DIIS, to the Python layer.

There are multiple things going on:

  • For pybinding, it was convenient to convert the enums in libdiis to strongly typed enums. This means the enums have their own scope, which changes how other functions had to call them. Every change in occ, dfocc, dct, fisapt, and libdiis is solely due to this. This occupies commit one.
  • Many other functions had to be pybound. In particular, it was necessary to convert diis_manager into a property. Old code would call HF.diis_manager(), but now they call HF.diis_manager_. We're not bothering to deprecate the old way of calling it. I'm not aware if there's a way to still support the old syntax. It might work if we change the property name to diis_manager? I haven't tested this.
  • It is not possible to pybind a variadic, so I had to pybind every set_error_vector_size and set_vector_size and add_entry type combination that Python might use. Sad, but necessary.

And with that done, all four of the compute_orbital_gradient functions could finally be moved to the Python layer. compute_orbital_gradient is kept as a virtual function, C++ side, to signal that Psi expects such a function to exist. My tests indicate that if the function is defined C++ side, it still works, so this won't break any SCF subclasses defined in plugins.

Todos

  • Lots of pybind-ing involving DIIS
  • Alert! HF.diis_manager() has changed to HF.diis_manager_
  • HF.compute_orbital_gradient moved to the Python layer. C-side compute_orbital_gradient is still supported, but not used by the core Psi.

Questions

  • Who is responsible for updating the Great DFOCC Branch with the libdiis API change?
  • How do we feel about the new functions I Pybind-ed over? Anything amiss?

Checklist

  • ctest -L scf passes

Status

  • Ready for review
  • Let's discuss the two questions before merging this in, please.

Copy link
Member

@loriab loriab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!


if save_fock:
if not self.initialized_diis_manager_:
storage_policy = getattr(core.DIISManager.StoragePolicy, "InCore" if self.scf_type() == "DIRECT" else "OnDisk")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
storage_policy = getattr(core.DIISManager.StoragePolicy, "InCore" if self.scf_type() == "DIRECT" else "OnDisk")
if self.scf_type() == "DIRECT":
storage_policy = core.DIISManager.StoragePolicy.InCore
else:
storage_policy = core.DIISManager.StoragePolicy.OnDisk

equivalent? I usually save getattr for when attribute only known in a variable. But that's my readability opinion. Your choice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, equivalent. The right thing to do for readability is probably to import from core.DIISManager import StoragePolicy, RemovalPolicy. Then I can have a terse ternary without using getattr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that works. only other consideration is if you'd ever want to track which paths were tested with codecov.


from psi4 import core

def _RHF_orbital_gradient(self, save_fock: bool, max_diis_vectors: int) -> float:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general info to readers: the Sphinx docs can now process type annotations, so they're not added in vain. the Sphinx docs now also hate the old Parameters\n verbose : int style in-docstring type annotation, so those're worth moving up into the signature.

@JonathonMisiewicz
Copy link
Contributor Author

JonathonMisiewicz commented Sep 24, 2021

On hold until #2296 gets approved, to see if we can reach a consensus on what pybind docstring format is now.

@JonathonMisiewicz
Copy link
Contributor Author

Force pushed to bring this branch up-to-date. Should be good to review again.

Copy link
Member

@jturney jturney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@JonathonMisiewicz JonathonMisiewicz added this to the Psi4 1.5 milestone Sep 29, 2021
Copy link
Contributor

@PeterKraus PeterKraus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have a couple very minor style suggestions. I suggest @JonathonMisiewicz can decide whether to action them or merge straight away.

return gradient.absmax()

core.RHF.compute_orbital_gradient = _RHF_orbital_gradient
core.UHF.compute_orbital_gradient = core.CUHF.compute_orbital_gradient = _UHF_orbital_gradient
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a terribly big fan of this triple-assignment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looked strange to me at first as well, but I've made my peace with it. Putting these assignments on the same line makes it obvious that these two are intended to be the same function. I was a little surprised that CUHF didn't need custom logic here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants