Skip to content

Conversation

@davpoolechem
Copy link
Contributor

@davpoolechem davpoolechem commented Mar 7, 2024

Description

This is something I have been working on as part of the upcoming Psi4-GauXC interface; but it seems to be of interest for other use cases, so I will be adding it here as a separate PR.

What this change does, is it adds two new member functions to the Psi4::Matrix class, eigen_map() and eigen_maps() . Both of these functions serve the same purpose - take the Psi4 matrix in question and return a representation of said matrix through Eigen's Map objects. The Eigen::Map class acts the same way as a normal Eigen::Matrix object, but uses an external array as its data buffer rather than an internal data buffer. The eigen_map() and eigen_maps() functions, then, return Eigen matrix-like objects that directly link with the Psi4 matrix data buffer of the Psi4 matrix for which the function was called. This provides an efficient fashion by which to utilize Psi4 matrices in contexts which require Eigen constructs, with no data deepcopying or Eigen-to-Psi4 back-conversions required.

There is a key difference between the two functions. eigen_map() assumes that the matrix has a single irrep, and returns a single Eigen::Map object. eigen_maps() , on the other hand, is used for matrices with multiple irreps, and returns a std::vector of Eigen::Map objects, each Map in the vector corresponding to one irrep of the Psi4 matrix.

User API & Changelog headlines

  • Adds two new functions, eigen_map() and eigen_maps(), usable in Psi4 plugins and downstream programs, that return a formulation of the calling Psi::Matrix object, that is usable in contexts where Eigen::Matrix objects are required/desired.

Dev notes & details

  • Adds two new member functions to Psi4::Matrix, eigen_map() and eigen_maps(), that return Eigen::Map representations of the Psi4 matrix object.

Questions

  • N/A

Notes

  • I did look into forward declaring the necessary Eigen classes, but forward declaring Eigen::Map turns out to be a bit ugly, as it is a class template that, to forward declare, ends up requiring forward declarations for other Eigen classes and enums (such as Stride and AlignmentType) that aren't specifically necessary for the Psi4 use case. Therefore, I have skipped forward declarations here.
  • I can confirm the correctness of the eigen_map() function, as I have implemented these PR changes into my Psi-GauXC interface, wherein eigen_map() replaces the original formulation I used for the equivalent result. eigen_maps(), however, is currently untested as there is no current use case for it yet, and should thus be considered experimental.

Checklist

Status

  • Ready for review
  • Ready for merge

@TiborGY
Copy link
Contributor

TiborGY commented Mar 13, 2024

User API & Changelog headlines

* [x]  N/A

The entire psi::Matrix class is marked as PSI_API, so I think adding any public member functions amounts to a change in API.

@davpoolechem
Copy link
Contributor Author

User API & Changelog headlines

* [x]  N/A

The entire psi::Matrix class is marked as PSI_API, so I think adding any public member functions amounts to a change in API.

The reason I didn't mark anything here as an API change is because neither of the new eigen_map functions are added to the list of exported Psi4::Matrix functions in export_mints.cc, which means that they cannot be utilized in the PsiAPI or Psithon input modes. Which is fine, because you'd probably prefer the Psi4::Matrix as a NumPy array in those contexts anyway.

The PSI_API flag makes the symbols for these functions visible in the Psi4 shared object library, but I'm not sure if that alone constitutes a User API change. I suppose it could count for plugin developers, as it is a new functionality within Psi4 that they can utilize in their plugins.

eigen_maps.emplace_back(get_pointer(h), rowdim(h), coldim(h));
}

return std::move(eigen_maps);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this necessary?

Copy link
Contributor Author

@davpoolechem davpoolechem Mar 22, 2024

Choose a reason for hiding this comment

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

It's probably not "necessary", strictly speaking, but I did this on the understanding that doing a std::move on the output vector would be more efficient due to avoiding unnecessary object copying/duplication. Happy to change if this is deemed unnecessary, however.

Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't return value optimization cover this?

Copy link
Contributor Author

@davpoolechem davpoolechem Mar 22, 2024

Choose a reason for hiding this comment

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

Yeah, when I double-checked my assumption online based on your inquiry, it does seem that std::move can hinder RVO. So with that in mind, I'll get rid of the move.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done and done!

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, thanks!

I agree that this is an API change on the plugin side, and thanks for pointing that out @TiborGY . It's less disruptive than some b/c it's an addition. And we've never achieved API stability on the c++ side; plugins builds just have to pin to a particular psi4 bld.

@loriab loriab added the libmints For things that are wrong with libmints (but not wavefunction). label Mar 22, 2024
@loriab loriab added this to the Psi4 1.10 milestone Mar 22, 2024
@davpoolechem
Copy link
Contributor Author

All right, added a note about the relevant API change as introduced by this PR!

@loriab loriab added this pull request to the merge queue Mar 22, 2024
Merged via the queue into psi4:master with commit 3c2be01 Mar 22, 2024
Comment on lines +39 to +40
#include <eigen3/Eigen/Core>

Copy link
Member

Choose a reason for hiding this comment

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

Isn't this a new requirement? I don't think Eigen3 has been used in Psi4 previously...

Copy link
Member

Choose a reason for hiding this comment

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

Right, I did mean to mention this. Correct that Psi4 doesn't use Eigen3 itself. But Eigen3 and boost header-only libs are needed to compile against L2 header-only, so it isn't a net new requirement.

@loriab loriab mentioned this pull request Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libmints For things that are wrong with libmints (but not wavefunction).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants