-
Notifications
You must be signed in to change notification settings - Fork 67
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
Add support for directional relative permeabilities #714
Conversation
jenkins build this opm-material=532 opm-common=3113 please |
Adds support for directional relperms for the tpfa linearizer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I looked at seems good, I just have a few questions and minor requests.
@@ -588,6 +646,39 @@ private: | |||
friend BlackOilBrineIntensiveQuantities<TypeTag>; | |||
friend BlackOilMICPIntensiveQuantities<TypeTag>; | |||
|
|||
void updateRelperms(const Problem& problem, const MaterialLawParams& materialParams, unsigned globalSpaceIdx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When it is spread across two functions, it is not easy to see that mobility_ and dirMob_ gets updated here. What about making this a static function and passing mobility_ and dirMob_ to it, that way it is obvious at the call site that those variables get updated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! See update.
/*! | ||
* \brief Returns the direction of the face | ||
*/ | ||
FaceDir::DirEnum dirId() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my current work on boundary conditions, it would be very useful if dirId() returned the underlying int instead, as I need to distinguish between the XMin and XPlus cases. Could we make that change, and add a free function faceDirFromDirId() with the implementation below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, see update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have added the code identically to my own branch too, so it should be easy to rebase one once the other is merged.
@@ -597,6 +688,7 @@ private: | |||
Evaluation porosity_; | |||
Evaluation rockCompTransMultiplier_; | |||
std::array<Evaluation,numPhases> mobility_; | |||
std::shared_ptr<DirectionalMobility> dirMob_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this is a shared_ptr and not a unique_ptr to keep the class copyable. But I think that changes the semantics of the class in a nontrivial way, as we will then not get a fully independent copy anymore. I am not set against it, but have you looked at the places where IQs are copied and checked that this is ok?
If we want to preserve deep copy semantics with a smart pointer it is possible, the Thor library has (or at least used to have) a CopiedPtr template that implemented it: https://bromeon.ch/libraries/thor/tutorials/v1.1/smartptr.html
Not sure that is necessary though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! That was to make the IQs copyable. I am not sure if there is an easy way to find all the places where the copy constructor and assignment operator for the IQ are used. I checked some files and looked at the compiler error messages and found one place in fvbaseelmentcontext.hh where they are copied: see updateIntensitiveQuantities_() at line 562 and one place where the IQs are reassigned, see updateStencil() at line 140. There are probably other places?
In the updated PR, I changed the shared_ptr to unique_ptr and added a copy constructor and an assignment operator to the BlackOilIntensiveQuantities class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is not a good solution to add explicitly coded copy constructors and assignment operators. It adds to the maintenance overhead significantly. I am also not sure it is actually correct as implemented here in the copy constructor, it fails to copy most members, this just demonstrates the point that it is hard to maintain.
I think using a copyable smart pointer is the best solution, keeping the copy construction and assigment defaulted. I may have come across as skeptical of the shared_ptr, but I think it can be an acceptable solution, as long as we have considered the consequences. A smart pointer with copy semantics is also a fine solution I think, but requires us to create or adopt such a template class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It adds to the maintenance overhead significantly
@atgeirr Yes, I agree.
A smart pointer with copy semantics is also a fine solution I think, but requires us to create or adopt such a template class.
I'll give the "copyable pointer" a try first. In the added commit I try to implement a minimal functionality for a copyable pointer.
To make each copy of the IQ unique, we change dirMob_ to be a shared_ptr instead of a unique_ptr.
To aid readability, we make updateRelperms() a static function.
Use a copyable unique pointer instead of writing custom copy constructor and assignment operator.
return ptr_ ? true : false; | ||
} | ||
// get a reference to the stored value | ||
T& get() const {return *ptr_;} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be consistent with the unique_ptr interface, it should return the raw pointer instead (return ptr_.get()
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea
CopyablePtr() : ptr_(nullptr) {} | ||
CopyablePtr(const CopyablePtr& other) { | ||
if (other) { // other does not contain a nullptr | ||
ptr_ = std::make_unique<T>(other.get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With get() returning a pointer (see below), this should change to take *this
.
if (other) { // other does not contain a nullptr | ||
ptr_ = std::make_unique<T>(other.get()); | ||
} | ||
// else {ptr_ = nullptr;} // this is the default construction value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The else branch must be implemented to kill the current pointer. Copying from an empty smart pointer should leave the current object as a similarly empty one, just as in the assignment operator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought since we are constructing a new object there will be no current object? Then, the default constructor will apply to the unique_ptr which will initialize it with a nullptr. Anyway, for clarity I have updated the code to use the else branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct in that there is no current object, my mistake! Maybe I thought it was a move constructor or something, not sure. But the default constructor is not invoked automatically, so you should always ensure all members are initialized.
// of the unique_ptr each time we copy construct or assign to it from another BlackOilIntensiveQuantites. | ||
// (On the other hand, if a copy could share the ptr with the original, a shared_ptr could be used instead and the | ||
// wrapper would not be needed) | ||
template <class T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add one more warning to this class template comment: You should never use it polymorphically. (That would require a virtual clone()
method etc.) It will only ever copy the static class type of the pointed to class.
Also, it should be put in a separate file, and have some unit tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I have moved the class to opm-common, see OPM/opm-common#3113 and added some tests..
This is more in line with how std::unique_ptr works.
For clarity, explicitly default construct the unique_ptr in the copy constructor
Moved the CopyablePtr template class to opm-common, see file opm/utility/CopyablePtr.hpp in opm-common
Try to fix jenkins build error: no type named EclMaterialLawManager
Define a method materialLawManagerPtr() that returns a nullpointer to EclMaterialLawManager, but that can be overridden in derived classes e.g. EclProblem
This PR appears to break the post-commit build. Please fix or revert. |
Strange, it was green. Let me first double-check locally. Could there be an issue with the ordering and timing of when this and the PR in opm-material was merged? |
I see in the jenkins log:
But locally on my machine the test |
Configure all your module builds with the -DBUILD_TESTING:BOOL=True cmake option. |
I suppose, but I get the same result locally when I include |
Depends on OPM/opm-material#532 and OPM/opm-common#3113