Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change raw pointer return in libmints to std::unique_ptr #2775

Merged
merged 11 commits into from
Jan 18, 2023

Conversation

hmacdope
Copy link
Contributor

@hmacdope hmacdope commented Nov 14, 2022

Fixes #2493

Description

For memory safety, the integrals in libmints should be returned as unique_ptrs rather than raw pointers

User API & Changelog headlines

Dev notes & details

  • All integrals in libmints now return a unique_ptr rather than a raw pointer
  • Call sites refactored to match

Questions

  • Are my refactors to the call sites correct? Many are just an immediate release of the unique_pointer, with the assumption that the memory management / pointer deletion occurs elsewhere
  • Should iterators eg CartesianIter also return unique_ptrs?

Checklist

Status

  • Ready for review
  • Ready for merge

Copy link
Contributor Author

@hmacdope hmacdope left a comment

Choose a reason for hiding this comment

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

Few questions @JonathonMisiewicz :)

psi4/src/psi4/libmints/mintshelper.cc Outdated Show resolved Hide resolved
psi4/src/psi4/libmints/mintshelper.cc Outdated Show resolved Hide resolved
psi4/src/psi4/libmints/orbitalspace.cc Outdated Show resolved Hide resolved
psi4/src/psi4/libmints/orbitalspace.cc Outdated Show resolved Hide resolved
@hmacdope hmacdope marked this pull request as ready for review November 14, 2022 11:49
@loriab
Copy link
Member

loriab commented Nov 14, 2022

tests/test_erisieve.py is unhappy with the changes. You can run it locally via <objdir># pytest -v ../tests/pytests/test_eriseive.py after executing the results of <objdir># stage/bin/psi4 --psiapi.

@hmacdope
Copy link
Contributor Author

tests/test_erisieve.py is unhappy with the changes. You can run it locally via <objdir># pytest -v ../tests/pytests/test_eriseive.py after executing the results of <objdir># stage/bin/psi4 --psiapi.

Thats strange, I couldn't reproduce locally ☹️

@hmacdope
Copy link
Contributor Author

@JonathonMisiewicz @loriab I'm also a bit confused as to why none of the callsites for the eri integrals needed to be changes and everything compiled no sweat. I feel I am probably missing something?

@loriab
Copy link
Member

loriab commented Nov 15, 2022

hmm, do which psi4 python and python -c "import psi4;print(psi4.__file__, psi4.__version__)" to see if anything looks suspicious (or post them here if you're unsure).

@hmacdope
Copy link
Contributor Author

python -c "import psi4;print(psi4.file, psi4.version)"

/Users/hugomacdermott/Desktop/dev/psi4_build/bin/psi4
/Users/hugomacdermott/miniconda3/envs/flow/bin/python
/Users/hugomacdermott/Desktop/dev/psi4_build/lib/psi4/__init__.py 1.7a1.dev109

But this should not affect the cmake compilation in my objdir?

@hmacdope
Copy link
Contributor Author

@loriab to add to this the CI seems to build fine. Some of the tests no dice.

@loriab
Copy link
Member

loriab commented Nov 15, 2022

If /Users/hugomacdermott/Desktop/dev/psi4_build/ is your CMAKE_INSTALL_PREFIX, then this is fine, but you can make development a little easier by skipping the install step. In your objdir/ is a stage/ dir with a complete install that gets updated with every make. It's this installation that gets run with ctest. I'd seek that, then run the results of objdir/stage/bin/psi4 --psiapi and check that the which & python -c commands returns paths in objdir/stage/. This way there's a quick turnaround between edit/make/test.

I don't see anything necessarily wrong with what you posted. The above is just a setup that can reduce confusion if you forget the install step.

@hmacdope
Copy link
Contributor Author

Ah yep thanks for the tips makes sense . It is my CMAKE_INSTALL_PREFIX.

I'm still confused though as to how it's even compiling

@JonathonMisiewicz
Copy link
Contributor

@JonathonMisiewicz @loriab I'm also a bit confused as to why none of the callsites for the eri integrals needed to be changes and everything compiled no sweat. I feel I am probably missing something?

A quick grep tells me that the raw pointers returned by eri were converted to shared_ptr almost immediately. That's the reason why, I'm sure.

@hmacdope
Copy link
Contributor Author

@JonathonMisiewicz @loriab I think I understand now, I thought you had to use an explicit std::move but that is only for an lvalue, you can do

std::shared_ptr<TwoBodyAOInt>(factory->erf_eri(omega_)

where erf_eri returns a std::unique_ptr because its a temporary rvalue

My bad sorry for the misunderstanding.

Regardless I will track down the failing test.

@hmacdope hmacdope changed the title WIP: change raw pointer return in libmints to std::unique_ptr change raw pointer return in libmints to std::unique_ptr Nov 21, 2022
@loriab loriab added this to the Psi4 1.8 milestone Nov 28, 2022
@hmacdope
Copy link
Contributor Author

hmacdope commented Dec 9, 2022

How do we want to move forward here @JonathonMisiewicz @loriab etc? :)

@JonathonMisiewicz
Copy link
Contributor

Apologies for the delay; you decided to get this PR moving again when Lori and I were both extremely busy with PsiCon and 1.8.

The one outstanding issue here seems to be the Pybind holder conversion. I'll look that over later today.

@JonathonMisiewicz
Copy link
Contributor

It looks like the segfault is a known Pybind issue. I think that the solution of changing the caster type from shared_ptr to unique_ptr is better coding practice. If nobody else objects, the Pybind conversion here seems as good as it's going to get.

Other thoughts? If nothing comes up soon, I'll give this another review.

@@ -144,7 +144,7 @@ void X2CInt::compute_integrals() {
if ((lambda_[0] != 0.0) or (lambda_[1] != 0) or (lambda_[2] != 0)) {
OperatorSymmetry msymm(1, molecule_, integral_, soFactory_);
std::vector<SharedMatrix> dipoles = msymm.create_matrices("Dipole");
OneBodySOInt *so_dipole = integral_->so_dipole();
std::unique_ptr<OneBodySOInt> so_dipole = integral_->so_dipole();
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't we use auto here?

@@ -525,7 +525,7 @@ void FISAPT::nuclear() {

auto Vfact = std::make_shared<IntegralFactory>(primary_);
std::shared_ptr<PotentialInt> Vint;
Vint = std::shared_ptr<PotentialInt>(static_cast<PotentialInt*>(Vfact->ao_potential()));
Vint = std::shared_ptr<PotentialInt>(static_cast<PotentialInt*>(Vfact->ao_potential().release()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Does Vint = Vfact->ao_potential() not suffice here (and many other places throughout this PR)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not without changing std::shared_ptr<PotentialInt> Vint; on L527, Im not libmints expert but does this have downstream effects or are we all good to cast to PotentialInt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lots of cases like this in this PR so probably good to decide what the strategy is.

Copy link
Contributor

Choose a reason for hiding this comment

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

To be more explicit: this line of code is both downcasting the underlying object and changing the type of the holding smart pointer to a shared pointer. I missed that first point in my original comment.

The underlying ao_potential method should be changed so that this downcasting isn't necessary, but that's beyond scope for this PR. This can stay as-is, begrudgingly, knowing that the removal of this ugliness is deferred to a follow-up PR. I'll do it if need be.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see. This is in the same vein as #2793 and related PR #2795. Perhaps should make a more general issue. Happy to help out fixing.

Copy link
Contributor

@JonathonMisiewicz JonathonMisiewicz left a comment

Choose a reason for hiding this comment

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

Now that the holidays are over (and I remembered about this PR, whoops), time to start getting this in.

Copy link
Contributor

@JonathonMisiewicz JonathonMisiewicz left a comment

Choose a reason for hiding this comment

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

Good enough for now. The integral factory methods need to stop upcasting their return values in a different PR, but otherwise, LGTM.

@JonathonMisiewicz
Copy link
Contributor

Is there a reason not to merge this now?

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 for the modernization.

@JonathonMisiewicz
Copy link
Contributor

JonathonMisiewicz commented Jan 18, 2023

Is there a reason not to merge this now?

To be clear, this is directed at @hmacdope, since you don't have "Ready to merge" checked.

@hmacdope
Copy link
Contributor Author

@JonathonMisiewicz oh sorry, yeah pits good to go

@JonathonMisiewicz JonathonMisiewicz merged commit 697fe5a into psi4:master Jan 18, 2023
@loriab loriab mentioned this pull request Jan 19, 2023
7 tasks
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.

libmints Raw to Unique Pointer
4 participants