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

MultiFab::deepCopy() #3848

Merged
merged 5 commits into from
Mar 28, 2024
Merged

Conversation

ax3l
Copy link
Member

@ax3l ax3l commented Mar 25, 2024

Summary

Create a deep copy of this MultiFab, using the same Arena and factory.

Additional background

See AMReX-Codes/pyamrex#282

Checklist

The proposed changes:

  • fix a bug or incorrect behavior in AMReX
  • add new capabilities to AMReX
  • changes answers in the test suite to more than roundoff level
  • are likely to significantly affect the results of downstream AMReX users
  • include documentation in the code and/or rst files, if appropriate

@ax3l ax3l requested a review from WeiqunZhang March 25, 2024 21:22
@ax3l ax3l changed the title MultiFab::Copy() MultiFab::copy() Mar 25, 2024
Create a copy of this MultiFab, using the same Arena.
@WeiqunZhang
Copy link
Member

We should use a different name, because MultiFab::copy will hide FabArray::copy and therefore is a breaking change. Also we already have MultiFab::Copy. So it can be quite confusing. (We even deprecated FabArray::copy to avoid confusion.

@ax3l
Copy link
Member Author

ax3l commented Mar 26, 2024

We should use a different name, because MultiFab::copy will hide FabArray::copy and therefore is a breaking change.

I am not sure it does - they have different arguments in their signatures...?

Also we already have MultiFab::Copy. So it can be quite confusing. (We even deprecated FabArray::copy to avoid confusion.

I added the lowercase variant similar to the uppercase (Add - static) and lowercase (add - method) naming so far. Primarily, I added it because in Python containers like NumPy nd arrays, .copy() is the canonical way to do a by-value copy. AMReX-Codes/pyamrex#282

Should we add this extra copy() method overload to FabArray instead?

Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
@WeiqunZhang
Copy link
Member

That's how C++ works. https://isocpp.org/wiki/faq/strange-inheritance#hiding-rule (We could work around it by using FabArray<FArrayBox>::copy. But function overloading can be confusing to users.)

@ax3l
Copy link
Member Author

ax3l commented Mar 26, 2024

Haha, ah yes I sometimes forget that fun detail :D
We have do that in ImpactX elements, too.

Python has no overloading at all... unless we are in pybind11 😆

We could work around it by using FabArray::copy. But function overloading can be confusing to users.

Sounds safe to me, since we do not have default parameters on the existing copies...?

@WeiqunZhang
Copy link
Member

What makes me uneasy is its implication. We have so far repeatedly resisted the urge of making it too easy to create a deep copied object. The copy ctor is deleted. We have a ctor for creating an alias MultiFab, which takes a parameter amrex::MakeType, but only make_alias is allowed. The new copy function is just like a copy ctor. One might be attempted to write the following correct but inefficient code.

MultiFab a = b.copy();
a = 0;

So let's have some time to think about this. Maybe we should make the function name more obvious like createDeepCopy. Maybe we could update the ctor to allow amrex::MultiFab a(amrex::make_deep_copy, b);.

@ax3l
Copy link
Member Author

ax3l commented Mar 27, 2024

Yes, I very much sympathize where this comes from. Here, I think there is a reasonable difference: in C++, the copy constructor and copy assignment are syntactically very reasonable to delete for large containers such as MultiFab, because they can be implicitly be called and lead to surprising resource costs.

This is essentially the same reason why Python does by-ref for everything by default - no implicit copies of containers ever.

Contrary to copy constructors and copy assignment operators, adding a .copy() method is explicit and a clear resource allocation when it is needed.

One might be attempted to write the following correct but inefficient code.

Maybe I miss a point. Yes, we should definitely expose make_alike the same way so we create an exact shallow copy without the values being copied (i.e., for your example doing immediately an a = 0;)

MultiFab a = b.copy();
a *= -1;
MultiFab a = b.make_alike();  // or b.copy(/* deep= */ false)
a = 0;

Let's chat about this more. I think that is a reasonable syntax and explicit once a copy is actually needed. It also uses canonical naming for deep copies, so we definitely would want this downstream in pyAMReX.

My feeling is that making it equally explicit and not more verbose/complicated to create deep copies is desirable.

@ax3l
Copy link
Member Author

ax3l commented Mar 27, 2024

To avoid confusion with FabArray<FAB>::copy (which could be called copyFrom() and are deprecated for the use of ParallelCopy instead) we name this: deepCopy().

In pyAMReX, because FabArray<FAB>::copy is deprecated, we will not expose it to Python and keep naming this .copy() as is canonical in Python.

@ax3l ax3l changed the title MultiFab::copy() MultiFab::deepCopy() Mar 27, 2024
@WeiqunZhang WeiqunZhang enabled auto-merge (squash) March 28, 2024 01:42
@WeiqunZhang WeiqunZhang merged commit 7437aa1 into AMReX-Codes:development Mar 28, 2024
68 of 69 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants