mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
Data keywords (PORO, EQLNUM, etc.) inside BOX/ENDBOX contain values for the sub-box only. When BOX coordinates are transformed to sector coordinates, the data size must match the transformed box dimensions. Crop boxed data keywords to the intersection of the BOX region with the sector, preserving the BOX/ENDBOX structure in the exported deck. If the box does not intersect the sector, the data keyword is removed.
235 lines
14 KiB
C++
235 lines
14 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2025- Equinor ASA
|
|
//
|
|
// ResInsight is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
#include "cafVecIjk.h"
|
|
#include "cvfArray.h"
|
|
#include "cvfVector3.h"
|
|
|
|
#include <QString>
|
|
|
|
#include <expected>
|
|
#include <functional>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
class RimEclipseView;
|
|
class RimEclipseCase;
|
|
class RigModelPaddingSettings;
|
|
class RigSimulationInputSettings;
|
|
class RifOpmFlowDeckFile;
|
|
class RigSimWellData;
|
|
template <typename Vec>
|
|
class RigBoundingBoxIjk;
|
|
class RigGridExportAdapter;
|
|
class RigMainGrid;
|
|
|
|
namespace Opm
|
|
{
|
|
class DeckRecord;
|
|
class DeckKeyword;
|
|
} // namespace Opm
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// Tool for exporting simulation input files (sector models)
|
|
///
|
|
//==================================================================================================
|
|
class RigSimulationInputTool
|
|
{
|
|
public:
|
|
// Data structures for NNC export
|
|
|
|
/// Raw NNC connection with global cell indices
|
|
struct NNCConnection
|
|
{
|
|
size_t c1GlobIdx; // Global cell index for cell 1
|
|
size_t c2GlobIdx; // Global cell index for cell 2
|
|
double transmissibility; // Transmissibility value
|
|
};
|
|
|
|
/// Transformed NNC connection with sector-relative 0-based IJK coordinates
|
|
struct TransformedNNCConnection
|
|
{
|
|
caf::VecIjk0 cell1 = caf::VecIjk0::ZERO; // 0-based sector IJK for cell 1
|
|
caf::VecIjk0 cell2 = caf::VecIjk0::ZERO; // 0-based sector IJK for cell 2
|
|
double transmissibility = 0.0; // Transmissibility value
|
|
};
|
|
|
|
static std::expected<void, QString>
|
|
exportSimulationInput( RimEclipseCase& eclipseCase, const RigSimulationInputSettings& settings, cvf::UByteArray* visibility );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processEqualsRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processMultiplyRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processBoxRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processCopyRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processAddRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processAquconRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processAquanconRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processAqunumRecord( const Opm::DeckRecord& record, const caf::VecIjk0& min, const caf::VecIjk0& max, const cvf::Vec3st& refinement );
|
|
|
|
static std::vector<int> createRefinedVisibility( const RigGridExportAdapter& gridAdapter );
|
|
|
|
static void expandBoxContextInDeckFile( RifOpmFlowDeckFile& deckFile );
|
|
static void cropDataKeywordsInsideBoxContext( RifOpmFlowDeckFile& deckFile,
|
|
const caf::VecIjk0& sectorMin,
|
|
const caf::VecIjk0& sectorMax,
|
|
const cvf::Vec3st& refinement );
|
|
|
|
// Public EDITNNC methods for testing
|
|
static std::vector<NNCConnection> extractDeckEditNncConnections( RifOpmFlowDeckFile& deckFile, const RigMainGrid& mainGrid );
|
|
static std::vector<NNCConnection> filterInternalSectorConnections( const std::vector<NNCConnection>& allConnections,
|
|
const RigMainGrid& mainGrid,
|
|
const caf::VecIjk0& min,
|
|
const caf::VecIjk0& max );
|
|
static std::expected<TransformedNNCConnection, QString> transformNNCToSectorCoordinates( const NNCConnection& connection,
|
|
const RigMainGrid& mainGrid,
|
|
const caf::VecIjk0& min,
|
|
const cvf::Vec3st& refinement );
|
|
static std::vector<TransformedNNCConnection> refineEditNncConnection( const NNCConnection& connection,
|
|
const RigMainGrid& mainGrid,
|
|
const caf::VecIjk0& min,
|
|
const cvf::Vec3st& refinement );
|
|
|
|
private:
|
|
static std::expected<void, QString> updateCornerPointGridInDeckFile( RimEclipseCase* eclipseCase,
|
|
const RigSimulationInputSettings& settings,
|
|
RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString> replaceKeywordValuesInDeckFile( RimEclipseCase* eclipseCase,
|
|
const RigSimulationInputSettings& settings,
|
|
RifOpmFlowDeckFile& deckFile,
|
|
const std::set<std::string>& alreadyCropped = {} );
|
|
|
|
static std::set<std::string>
|
|
cropDataKeywordsInDeckFile( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
updateWelldimsKeyword( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString> addBorderBoundaryConditions( RimEclipseCase* eclipseCase,
|
|
const RigSimulationInputSettings& settings,
|
|
cvf::ref<cvf::UByteArray> visibility,
|
|
RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceEqualsKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceMultiplyKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceBoxKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceCopyKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceAddKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceAquconKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceAquanconKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
replaceAqunumKeywordIndices( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString>
|
|
addFaultsToDeckFile( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString> filterAndUpdateWellKeywords( std::set<std::string>& validWellNames,
|
|
const RigSimulationInputSettings& settings,
|
|
RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString> updateWellListKeywords( std::set<std::string>& validWellNames,
|
|
const RigSimulationInputSettings& settings,
|
|
RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::set<std::string> wellNamesToInclude( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings );
|
|
|
|
static std::expected<void, QString>
|
|
exportEditNncKeyword( RimEclipseCase* eclipseCase, const RigSimulationInputSettings& settings, RifOpmFlowDeckFile& deckFile );
|
|
|
|
static std::expected<void, QString> applyModelPadding( RifOpmFlowDeckFile& deckFile, const RigModelPaddingSettings& paddingSettings );
|
|
|
|
// Utility: Transform global IJK to sector-relative coordinates with refinement
|
|
static caf::VecIjk0 transformToSectorCoordinates( const caf::VecIjk0& globalIjk, const caf::VecIjk0& min, const cvf::Vec3st& refinement );
|
|
|
|
static std::expected<void, QString> addOperNumRegionAndOperater( RifOpmFlowDeckFile& deckFile,
|
|
const RigGridExportAdapter& gridAdapter,
|
|
const std::vector<int>& operNumResult,
|
|
int operNumRegion,
|
|
double porvMultiplier );
|
|
|
|
static std::vector<RigSimWellData*> findIntersectingWells( RimEclipseCase* eclipseCase, const caf::VecIjk0& min, const caf::VecIjk0& max );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processWelspecsRecord( const Opm::DeckRecord& record, const std::string& wellName, const RigSimulationInputSettings& settings );
|
|
|
|
static std::expected<Opm::DeckRecord, QString>
|
|
processCompdatRecord( const Opm::DeckRecord& record, const std::string& wellName, const RigSimulationInputSettings& settings );
|
|
|
|
static std::expected<Opm::DeckRecord, QString> processCompsegsRecord( const Opm::DeckRecord& record,
|
|
const std::string& wellName,
|
|
bool isWellNameRecord,
|
|
const RigSimulationInputSettings& settings );
|
|
|
|
// Generic helper for processing keywords with box indices
|
|
using RecordProcessorFunc =
|
|
std::function<std::expected<Opm::DeckRecord, QString>( const Opm::DeckRecord&, const caf::VecIjk0&, const caf::VecIjk0&, const cvf::Vec3st& )>;
|
|
|
|
static std::expected<void, QString> replaceKeywordWithBoxIndices( const std::string& keywordName,
|
|
RimEclipseCase* eclipseCase,
|
|
const RigSimulationInputSettings& settings,
|
|
RifOpmFlowDeckFile& deckFile,
|
|
RecordProcessorFunc processorFunc );
|
|
|
|
// Helper function to transform bounding box from global to sector coordinates
|
|
// Returns bounding box with 0-based sector-relative coordinates
|
|
static std::expected<RigBoundingBoxIjk<caf::VecIjk0>, QString>
|
|
transformBoxToSectorCoordinates( const RigBoundingBoxIjk<caf::VecIjk0>& inputBox,
|
|
const caf::VecIjk0& sectorMin,
|
|
const caf::VecIjk0& sectorMax,
|
|
const cvf::Vec3st& refinement,
|
|
const QString& keywordName,
|
|
const QString& recordIdentifier );
|
|
|
|
// Helper function to extract IJK coordinates from a deck record
|
|
// Returns a VecIjk1 (1-based) constructed from values at the specified item indices
|
|
static caf::VecIjk1 extractIjk( const Opm::DeckRecord& record, size_t indexI, size_t indexJ, size_t indexK );
|
|
};
|