Skip to content

using pinched grid for numerical aquifers.#517

Merged
joakim-hove merged 9 commits intoOPM:masterfrom
GitPaean:using_pinched_grid_numerical_aquifer
Apr 21, 2021
Merged

using pinched grid for numerical aquifers.#517
joakim-hove merged 9 commits intoOPM:masterfrom
GitPaean:using_pinched_grid_numerical_aquifer

Conversation

@GitPaean
Copy link
Member

No description provided.

@GitPaean GitPaean force-pushed the using_pinched_grid_numerical_aquifer branch from f386555 to 0cfca3b Compare March 26, 2021 23:02
@GitPaean
Copy link
Member Author

serial results look fine while parallel results are wrong.

@GitPaean
Copy link
Member Author

GitPaean commented Apr 7, 2021

the parallel results looks fine now. fixing all the tests now.

@GitPaean GitPaean force-pushed the using_pinched_grid_numerical_aquifer branch 3 times, most recently from 83748dd to 6efd612 Compare April 7, 2021 21:51
@GitPaean GitPaean marked this pull request as ready for review April 7, 2021 22:14
@GitPaean
Copy link
Member Author

GitPaean commented Apr 7, 2021

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.

/// \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,
Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Member

Choose a reason for hiding this comment

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

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!

Copy link
Member Author

@GitPaean GitPaean Apr 8, 2021

Choose a reason for hiding this comment

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

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.

Copy link
Member Author

@GitPaean GitPaean Apr 8, 2021

Choose a reason for hiding this comment

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

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.

Copy link
Member

Choose a reason for hiding this comment

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

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay. I will use pointers here. I think optional to reference is not there yet, right? Correct me if I am wrong here.

Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Member Author

@GitPaean GitPaean Apr 15, 2021

Choose a reason for hiding this comment

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

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.

@GitPaean GitPaean closed this Apr 8, 2021
@GitPaean GitPaean reopened this Apr 8, 2021
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);
Copy link
Member Author

Choose a reason for hiding this comment

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

not sure why nnc can not use {} as the original code, will try more.

Copy link
Member

Choose a reason for hiding this comment

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

not sure why nnc can 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.

@GitPaean GitPaean force-pushed the using_pinched_grid_numerical_aquifer branch from eb5fc8a to 0300e5d Compare April 9, 2021 22:19
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,
Copy link
Member Author

Choose a reason for hiding this comment

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

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

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);
Copy link
Member Author

Choose a reason for hiding this comment

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

@joakim-hove , it is here the mutableNumericalAquifers() will be modified.

@GitPaean GitPaean force-pushed the using_pinched_grid_numerical_aquifer branch from 0300e5d to 7ec48db Compare April 12, 2021 10:36
@GitPaean
Copy link
Member Author

rebasing turned out to be a little tedious. So merging is used here to fix the conflicts.

@GitPaean GitPaean requested review from blattms and bska April 16, 2021 07:54
@GitPaean
Copy link
Member Author

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 processEclipseFormat. Please review and suggest.

The jenkins was triggered from upsctream PR OPM/opm-common#2389 and is green now.

@GitPaean GitPaean added this to the Release 2021.04 milestone Apr 16, 2021
@GitPaean GitPaean changed the title WIP in using pinched grid for numerical aquifers. using pinched grid for numerical aquifers. Apr 16, 2021
@bska bska mentioned this pull request Apr 16, 2021
Copy link
Member

@bska bska left a comment

Choose a reason for hiding this comment

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

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.

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);
Copy link
Member

Choose a reason for hiding this comment

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

not sure why nnc can 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.

Comment on lines +547 to +548
NNCMaps nnc;
current_view_data_->processEclipseFormat(input_data, nullptr, nullptr, nnc, z_tolerance, remove_ij_boundary, turn_normals);
Copy link
Member

Choose a reason for hiding this comment

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

Why is it appropriate to just drop the nnc information here?

Copy link
Member Author

Choose a reason for hiding this comment

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

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.

Comment on lines -251 to +254
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)
Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

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.

@blattms
Copy link
Member

blattms commented Apr 19, 2021

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:

  1. If and when I am allowed to pass nullpointers
  2. If and when I allowed to pass incomplete objects (e.g. EclState not reflecting the whole model)

Or has that changed meanwhile.
Would be cool if that was be easy to find. Otherwise I concur with @bska's opinion (not even sure whether I have the required knowledge to do so).

@blattms
Copy link
Member

blattms commented Apr 19, 2021

I am approving now as this could be done in a separate PR (which often means it will slip).

Copy link
Member

@blattms blattms left a comment

Choose a reason for hiding this comment

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

Apart from doc improvements this looks fine.

@GitPaean
Copy link
Member Author

GitPaean commented Apr 19, 2021

If and when I am allowed to pass nullpointers

Yes. Null pointers are allowed, which makes it okay to only have the grid passed in. When you do not have ElcipseState or Deck available, you can pass in null pointers. This is referring to the function void CpGridData::processEclipseFormat in processEclipseFormat.cpp.

If and when I allowed to pass incomplete objects (e.g. EclState not reflecting the whole model)

This is hard to tell. For example, if a deck only have the GRID description without providing PORO or PORV information, all the grid cells will be marked inactive. Then it will probably not work very well. But I am not sure it is a problem of the EclipseState or here.

Copy link
Member

@joakim-hove joakim-hove left a comment

Choose a reason for hiding this comment

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

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.

@GitPaean GitPaean removed this from the Release 2021.04 milestone Apr 19, 2021
@joakim-hove
Copy link
Member

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;
Copy link
Member

Choose a reason for hiding this comment

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

That this line of code actually "turns on" a cell is so special it deserves a comment.

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay. This is not the line turning on a aquifer cell. This line just generates the actnum based on output.

Copy link
Member Author

Choose a reason for hiding this comment

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

Here is the place that forcefully keeps aquifer cells active.

/* we keep aquifer cells active always even the cells have zero thickness or volume */

@joakim-hove
Copy link
Member

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.

My only suggestion is to have a temporary vector in the numerical aquiferclass with all the connections coming from the AQUCON keyword, and then a method e.g. NumericalAquifer::post_process_connections( new_actnum );

@GitPaean GitPaean force-pushed the using_pinched_grid_numerical_aquifer branch 2 times, most recently from b2f9f96 to a8e70c8 Compare April 20, 2021 07:31
@GitPaean GitPaean closed this Apr 20, 2021
@GitPaean GitPaean reopened this Apr 20, 2021
@GitPaean
Copy link
Member Author

My only suggestion is to have a temporary vector in the numerical aquiferclass with all the connections coming from the AQUCON keyword, and then a method e.g. NumericalAquifer::post_process_connections( new_actnum );

Done, waiting for Jenkins to pass. At the same time, there is one function processEclipseFormat using const Deck& as input argument already in CpGridData.hpp.

@joakim-hove
Copy link
Member

At the same time, there is one function processEclipseFormat using const Deck& as input argument already in CpGridData.hpp.

A little surprising - I think it should be removed.

@GitPaean GitPaean force-pushed the using_pinched_grid_numerical_aquifer branch from a8e70c8 to 402718d Compare April 21, 2021 07:37
@GitPaean GitPaean closed this Apr 21, 2021
@GitPaean GitPaean reopened this Apr 21, 2021
@joakim-hove joakim-hove merged commit e0d4da6 into OPM:master Apr 21, 2021
@GitPaean GitPaean deleted the using_pinched_grid_numerical_aquifer branch April 22, 2021 07:24
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.

4 participants