From 1b6592efd47c1625b57a84b82dfcf334d75269be Mon Sep 17 00:00:00 2001 From: Antonella Ritorto Date: Fri, 28 Nov 2025 14:57:01 +0100 Subject: [PATCH 1/2] Create output grid with COORD and ZCORN lgrs. --- opm/simulators/flow/EclGenericWriter_impl.hpp | 80 +++++++++++++++---- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/opm/simulators/flow/EclGenericWriter_impl.hpp b/opm/simulators/flow/EclGenericWriter_impl.hpp index d6d1151534a..86423176485 100644 --- a/opm/simulators/flow/EclGenericWriter_impl.hpp +++ b/opm/simulators/flow/EclGenericWriter_impl.hpp @@ -25,6 +25,8 @@ #include + +#include #include #include #include @@ -236,20 +238,64 @@ EclGenericWriter(const Schedule& schedule, , equilGrid_ (equilGrid) { if (this->collectOnIORank_.isIORank()) { - this->eclIO_ = std::make_unique - (this->eclState_, - UgGridHelpers::createEclipseGrid(*equilGrid, eclState_.getInputGrid()), - this->schedule_, summaryConfig, "", enableEsmry); - } - // create output thread if enabled and rank is I/O rank - // async output is enabled by default if pthread are enabled - int numWorkerThreads = 0; - if (enableAsyncOutput && collectOnIORank_.isIORank()) { - numWorkerThreads = 1; - } + if constexpr (std::is_same_v) { + // For CpGrid with LGRs, we generate an EclipseGrid for output using grid_ + // rather than equilGrid_. When equilGrid_ is created as a shallow copy of + // grid_, some internal data members are not propagated. As a result, + // equilGrid_ lacks the necessary LGR information, and ResInsight cannot + // visualize the local grids. + // + // TODO: Resolve this by improving the CpGrid copy constructor or by introducing + // an alternative mechanism to ensure all relevant grid data is fully transferred. + if ( (this->grid_.comm().size() == 1) && (this->eclState_.getLgrs().size()>0) && (this->grid_.maxLevel()>0) ) { + + // Create a new EclpseGrid for output using dims and zcorn and coords from level zero + const auto [l0CartesianIdxToCellIdx, l0IJK] = Opm::lgrIJK(grid_, "GLOBAL"); + const auto [l0COORD, l0ZCORN] = Opm::lgrCOORDandZCORN(grid_, 0, l0CartesianIdxToCellIdx, l0IJK); + Opm::EclipseGrid eclipse_grid_output(grid_.logicalCartesianSize(), l0COORD, l0ZCORN); + + // Set the LGRCollection + eclipse_grid_output.init_lgr_cells(eclState_.getLgrs()); + + // Loop over all levels + for (const auto& [lgr_name, lgr_level] : grid_.getLgrNameToLevel()) + { + const auto [lgrCartesianIdxToCellIdx, lgrIJK] = Opm::lgrIJK(grid_, lgr_name); + const auto [lgrCOORD, lgrZCORN] = Opm::lgrCOORDandZCORN(grid_, lgr_level, lgrCartesianIdxToCellIdx, lgrIJK); + + eclipse_grid_output.set_lgr_refinement(lgr_name, lgrCOORD, lgrZCORN); + } + eclipse_grid_output.init_children_host_cells(); + + this->eclIO_ = std::make_unique + (this->eclState_, + eclipse_grid_output, + this->schedule_, summaryConfig, "", enableEsmry); - this->taskletRunner_.reset(new TaskletRunner(numWorkerThreads)); + } + else { + this->eclIO_ = std::make_unique + (this->eclState_, + UgGridHelpers::createEclipseGrid(*equilGrid, eclState_.getInputGrid()), + this->schedule_, summaryConfig, "", enableEsmry); + } + } else { + this->eclIO_ = std::make_unique + (this->eclState_, + UgGridHelpers::createEclipseGrid(*equilGrid, eclState_.getInputGrid()), + this->schedule_, summaryConfig, "", enableEsmry); + } + + // create output thread if enabled and rank is I/O rank + // async output is enabled by default if pthread are enabled + int numWorkerThreads = 0; + if (enableAsyncOutput && collectOnIORank_.isIORank()) { + numWorkerThreads = 1; + } + + this->taskletRunner_.reset(new TaskletRunner(numWorkerThreads)); + } } template @@ -615,14 +661,16 @@ doWriteOutput(const int reportStepNum, } } - std::vector restartValues{}; - // only serial, only CpGrid (for now) + std::vector restartValues{}; // Level grids RestartValues (only serial and CpGrid for now) if ( !isParallel && !needsReordering && (this->eclState_.getLgrs().size()>0) && (this->grid_.maxLevel()>0) ) { // Level cells that appear on the leaf grid view get the data::Solution values from there. - // Other cells (i.e., parent cells that vanished due to refinement) get rubbish values for now. + // Other cells (i.e., parent cells that vanished due to refinement) get average of children values for now. // Only data::Solution is restricted to the level grids. Well, GroupAndNetwork, Aquifer are // not modified in this method. - Opm::Lgr::extractRestartValueLevelGrids(this->grid_, restartValue, restartValues); + Opm::Lgr::extractRestartValueLevelGrids(this->grid_, + restartValue, + this->eclState_.fieldProps().get_double("PORV"), + restartValues); } else { restartValues.reserve(1); // minimum size From e456304c24f168692506939df61e4eaa47ad9fab Mon Sep 17 00:00:00 2001 From: Antonella Ritorto Date: Tue, 9 Dec 2025 09:18:56 +0100 Subject: [PATCH 2/2] Reduce duplication with optional output_grid --- opm/simulators/flow/EclGenericWriter_impl.hpp | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/opm/simulators/flow/EclGenericWriter_impl.hpp b/opm/simulators/flow/EclGenericWriter_impl.hpp index 86423176485..8b5cf17c2e3 100644 --- a/opm/simulators/flow/EclGenericWriter_impl.hpp +++ b/opm/simulators/flow/EclGenericWriter_impl.hpp @@ -239,6 +239,8 @@ EclGenericWriter(const Schedule& schedule, { if (this->collectOnIORank_.isIORank()) { + std::optional output_grid; + if constexpr (std::is_same_v) { // For CpGrid with LGRs, we generate an EclipseGrid for output using grid_ // rather than equilGrid_. When equilGrid_ is created as a shallow copy of @@ -268,24 +270,21 @@ EclGenericWriter(const Schedule& schedule, } eclipse_grid_output.init_children_host_cells(); - this->eclIO_ = std::make_unique - (this->eclState_, - eclipse_grid_output, - this->schedule_, summaryConfig, "", enableEsmry); - - } - else { - this->eclIO_ = std::make_unique - (this->eclState_, - UgGridHelpers::createEclipseGrid(*equilGrid, eclState_.getInputGrid()), - this->schedule_, summaryConfig, "", enableEsmry); + output_grid = std::move(eclipse_grid_output); } - } else { - this->eclIO_ = std::make_unique - (this->eclState_, - UgGridHelpers::createEclipseGrid(*equilGrid, eclState_.getInputGrid()), - this->schedule_, summaryConfig, "", enableEsmry); } + // CpGrid without LGR or different grid type + if (!output_grid) { + output_grid = UgGridHelpers::createEclipseGrid(*equilGrid, eclState_.getInputGrid()); + } + + this->eclIO_ = std::make_unique(this->eclState_, + *output_grid, + this->schedule_, + summaryConfig, + "", + enableEsmry); + // create output thread if enabled and rank is I/O rank // async output is enabled by default if pthread are enabled @@ -669,7 +668,6 @@ doWriteOutput(const int reportStepNum, // not modified in this method. Opm::Lgr::extractRestartValueLevelGrids(this->grid_, restartValue, - this->eclState_.fieldProps().get_double("PORV"), restartValues); } else {