using pinched grid for numerical aquifers.#517
Conversation
f386555 to
0cfca3b
Compare
|
serial results look fine while parallel results are wrong. |
|
the parallel results looks fine now. fixing all the tests now. |
83748dd to
6efd612
Compare
|
In this PR, we process the numerical aquifers connection information in the middle of the grid processing, which does not look natural, but I do not think it is an easy task to refactor to do the PINCH, MINPV in the parser. I am marking this PR to be ready for review. |
opm/grid/cpgrid/CpGridData.hpp
Outdated
| /// \param remove_ij_boundary if true, will remove (i, j) boundaries. Used internally. | ||
| void processEclipseFormat(const grdecl& input_data, const std::array<std::set<std::pair<int, int>>, 2>& nnc, double z_tolerance, bool remove_ij_boundary, bool turn_normals = false, | ||
| const std::unordered_map<size_t, double>& aquifer_cell_volumes = std::unordered_map<size_t, double>()); | ||
| void processEclipseFormat(const grdecl& input_data, Opm::EclipseState& ecl_state, const Opm::Deck& deck, |
There was a problem hiding this comment.
Your really need to document this properly, as the change seems a bit dangerous. We seem to call this function with an empty ecl_state, which is fine as long as there are no numerical aquifers.
The danger is that in the future fellow developer might assume that the ecl_state is always valid and use it for other things. In that case they will have a hard time debugging.
There was a problem hiding this comment.
This looks very dangerous to me - the empty EclipseState is purely an artifact of the serialization - it is deeply invalid and should not be used for anything!
There was a problem hiding this comment.
I will add the document here. If we do not use EclipseState here, we will need the EclipseGrid, FieldPropsManager, AquiferConfig and inputNNC of the EclipseState. I really do not want to add so many arguments and passing them around. One of the big difficulties when developing this part is that we have five different functions with the same name processEclipseFormat, with different arguments, and doing different but related things, and call one other. Maybe it is good idea to rename the functions to get a little bit more descriptive (maybe I should have done it before developing this PR). Anyway, it is not related to this PR directly.
We seem to call this function with an empty ecl_state,
I think you mean the place that uses empty ecl_state to fix the interface.
There was a problem hiding this comment.
The empty ecl_state happens in the following code in CpGrid.cpp to fix the interfaces.
void CpGrid::processEclipseFormat(const grdecl& input_data, double z_tolerance,
bool remove_ij_boundary, bool turn_normals)
{
// TODO: just fix the interface, not sure it will be problematic
Opm::EclipseState ecl_state;
Opm::Deck deck;
using NNCMap = std::set<std::pair<int, int>>;
using NNCMaps = std::array<NNCMap, 2>;
NNCMaps nnc;
current_view_data_->processEclipseFormat(input_data, ecl_state, deck, nnc, z_tolerance, remove_ij_boundary, turn_normals);Do you think to use pointers here better than using the references? Then we can just pass in nullptr for the above situation. Please comment.
There was a problem hiding this comment.
Yes I think using a pointer or optional is better here - as I said - things will go fast to pieces if you use a default constructed EclipseState
There was a problem hiding this comment.
Okay. I will use pointers here. I think optional to reference is not there yet, right? Correct me if I am wrong here.
There was a problem hiding this comment.
Wouldn't std::optional make a copy of EclipseState? That might be expensive...
You would need to use a std::optional with a std::reference_wrapper inside to prevent the copy. Not sure whether that really works.
There was a problem hiding this comment.
You would need to use a std::optional with a std::reference_wrapper inside to prevent the copy. Not sure whether that really works.
That works - I have tried it in another context; but maybe slightly over engineered? I would go with a pointer, but this is not my turf.
There was a problem hiding this comment.
This change really backfired in the downstream modules. in opm-upscaling module, it only looks at the eclipse_grid. With the same grid deck, you can generate a EclipseGrid and also possible for a EclipseState with an EclipseGrid. But these two grid are different, because since there is no pore volumes, all the grid cells will be marked inactive.
opm/grid/cpgrid/CpGrid.cpp
Outdated
| using NNCMap = std::set<std::pair<int, int>>; | ||
| using NNCMaps = std::array<NNCMap, 2>; | ||
| NNCMaps nnc; | ||
| current_view_data_->processEclipseFormat(g, nullptr, nullptr, nnc, 0.0, false, false); |
There was a problem hiding this comment.
not sure why nnc can not use {} as the original code, will try more.
There was a problem hiding this comment.
not sure why
nnccan not use{}as the original code, will try more.
Just a quick follow-up to this in case it's not already clear. The function takes an NNCMaps& rather than a const NNCMaps& so you can't pass a temporary.
eb5fc8a to
0300e5d
Compare
opm/grid/CpGrid.hpp
Outdated
| const Opm::NNC& = Opm::NNC(), | ||
| const std::unordered_map<size_t, double>& aquifer_cell_volumes = std::unordered_map<size_t, double>()); | ||
| // TODO: add description of the arguments | ||
| void processEclipseFormat(Opm::EclipseState* ecl_state, |
There was a problem hiding this comment.
One thing unfortunate due to the change here is that, originally the main input is EclipseGrid, but now the main input EclipseGrid becomes something hidden in the EclipseState.
Maybe we still can keep EclipseGrid as the main input, but also has EclipseState there for extra information. But we can not guarantee the EclipseGrid is the grid from EclipseState.
There was a problem hiding this comment.
I will recovered to be the main argument is the EclipseGrid. EclipseState will be secondary argument to provide other information. When there is only EclipseState provided, we use the EclipseGrid belonging to EclipseState.
| } | ||
| const auto& ecl_grid = ecl_state->getInputGrid(); | ||
| const auto& fp = ecl_state->fieldProps(); | ||
| aquifer.mutableNumericalAquifers().addAquiferConnections(*deck, ecl_grid, new_actnum); |
There was a problem hiding this comment.
@joakim-hove , it is here the mutableNumericalAquifers() will be modified.
for EclipseState and Deck.
0300e5d to
7ec48db
Compare
|
rebasing turned out to be a little tedious. So merging is used here to fix the conflicts. |
|
This is the major parts related to this effort to get this piece of numerical aquifers in. Besides some code related to numerical aquifers directly, the main part is interface changes related to functions The jenkins was triggered from upsctream PR OPM/opm-common#2389 and is green now. |
bska
left a comment
There was a problem hiding this comment.
Looks good to me. I just had a couple of minor questions. Once those are addressed, I'm prepared to merge this along with its upstream OPM/opm-common#2389.
opm/grid/cpgrid/CpGrid.cpp
Outdated
| using NNCMap = std::set<std::pair<int, int>>; | ||
| using NNCMaps = std::array<NNCMap, 2>; | ||
| NNCMaps nnc; | ||
| current_view_data_->processEclipseFormat(g, nullptr, nullptr, nnc, 0.0, false, false); |
There was a problem hiding this comment.
not sure why
nnccan not use{}as the original code, will try more.
Just a quick follow-up to this in case it's not already clear. The function takes an NNCMaps& rather than a const NNCMaps& so you can't pass a temporary.
opm/grid/cpgrid/CpGrid.cpp
Outdated
| NNCMaps nnc; | ||
| current_view_data_->processEclipseFormat(input_data, nullptr, nullptr, nnc, z_tolerance, remove_ij_boundary, turn_normals); |
There was a problem hiding this comment.
Why is it appropriate to just drop the nnc information here?
There was a problem hiding this comment.
Not totally sure that I understand your question correctly here.
For this situation, nnc will always be empty. The only reason it can be modified within this function call is numerical aquifers, but we pass in nullptr for EclipseState*, so no numerical aquifers. nnc created here is purely for interface. It does not look pretty.
Suggestion is very welcomed here.
| void CpGridData::processEclipseFormat(const grdecl& input_data, const NNCMaps& nnc, double z_tolerance, bool remove_ij_boundary, bool turn_normals, | ||
| const std::unordered_map<size_t, double>& aquifer_cell_volumes) | ||
| void CpGridData::processEclipseFormat(const grdecl& input_data, Opm::EclipseState* ecl_state, const Opm::Deck* deck, | ||
| NNCMaps& nnc, double z_tolerance, bool remove_ij_boundary, bool turn_normals) |
There was a problem hiding this comment.
I didn't notice this before. Strictly speaking, this particular function is not protected by HAVE_ECL_INPUT so it was originally supposed to be callable without types from opm-common. I'd be happy to remove that restriction, but maybe we should discuss this topic a little more before we merge the PR.
There was a problem hiding this comment.
Sure. I am not that familiar with grid related stuff.
In my own opinion, the grid processing (getting the final ACTNUM, we should not drop any information before determining the final ACTNUM, so a cell is free to change from inactive to active.) should be done in the early stage of the parsing, so all the numerical aquifers stuff can stay in opm-common.
The current way is intruding because we do the processing (can remove more cells) after parsing, while parsing needs processed grid and parsing information also intervene the grid processing.
…d_numerical_aquifer
|
Thanks for adding documentation. My main point for requesting it, was that developers can see which are optional or which do only have to have a limited state in certain circumstances. Seems like that is still not clear from the text. Or maybe this did change? I would like to get the following info from the documentation:
Or has that changed meanwhile. |
|
I am approving now as this could be done in a separate PR (which often means it will slip). |
blattms
left a comment
There was a problem hiding this comment.
Apart from doc improvements this looks fine.
Yes. Null pointers are allowed, which makes it okay to only have the grid passed in. When you do not have
This is hard to tell. For example, if a deck only have the GRID description without providing |
joakim-hove
left a comment
There was a problem hiding this comment.
This PR uses the raw Deck datastructure - outside of opm-common, we must find a way to avoid that. I'm trying to come up with a suggestion.
|
This series of PR's brings in a completely new thing - namely that pinched out cells are activated by the Aquifer code. This is complex code - breaking with an assumption (that cells can only be deactivated) which has been correct for a long time. This should in my opinion not be merged without proper testing - preferably both unit testing and integration test. |
| const size_t global_nc = input_data.dims[0] * input_data.dims[1] * input_data.dims[2]; | ||
| std::vector<int> new_actnum(global_nc, 0); | ||
| for (int i = 0; i < output.number_of_cells; ++i) { | ||
| new_actnum[output.local_cell_index[i]] = 1; |
There was a problem hiding this comment.
That this line of code actually "turns on" a cell is so special it deserves a comment.
There was a problem hiding this comment.
Okay. This is not the line turning on a aquifer cell. This line just generates the actnum based on output.
There was a problem hiding this comment.
Here is the place that forcefully keeps aquifer cells active.
opm-grid/opm/grid/cpgpreprocess/preprocess.c
Line 354 in a28f0bd
My only suggestion is to have a temporary vector in the numerical aquiferclass with all the connections coming from the |
…d_numerical_aquifer
b2f9f96 to
a8e70c8
Compare
Done, waiting for Jenkins to pass. At the same time, there is one function |
A little surprising - I think it should be removed. |
a8e70c8 to
402718d
Compare
No description provided.