Files
ResInsight/ApplicationLibCode/ReservoirDataModel/RigReservoirBuilderMock.cpp
T

405 lines
15 KiB
C++
Raw Normal View History

2012-05-18 09:45:23 +02:00
/////////////////////////////////////////////////////////////////////////////////
//
2014-09-23 15:04:57 +02:00
// Copyright (C) 2011- Statoil ASA
// Copyright (C) 2013- Ceetron Solutions AS
// Copyright (C) 2011-2012 Ceetron AS
//
2012-05-18 09:45:23 +02:00
// 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.
//
2012-05-18 09:45:23 +02:00
// 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>
2012-05-18 09:45:23 +02:00
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigReservoirBuilderMock.h"
#include "RigActiveCellInfo.h"
#include "RigCell.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigNNCData.h"
#include "Well/RigSimWellData.h"
#include "Well/RigWellResultFrame.h"
#include "Well/RigWellResultPoint.h"
2012-05-18 09:45:23 +02:00
#include "cafAssert.h"
2024-10-28 13:09:18 +01:00
#include <QRegularExpression>
2024-09-30 11:21:17 +02:00
2012-06-26 16:10:41 +02:00
/* rand example: guess the number */
#include <cstdio>
#include <cstdlib>
#include <ctime>
2012-06-26 16:10:41 +02:00
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
RigReservoirBuilderMock::RigReservoirBuilderMock()
{
m_resultCount = 0;
m_timeStepCount = 0;
m_enableWellData = true;
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::setCellCounts( const cvf::Vec3st& cellCounts )
2012-05-18 09:45:23 +02:00
{
m_reservoirBuilder.setIJKCount( cellCounts );
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::setResultInfo( size_t resultCount, size_t timeStepCount )
2012-05-18 09:45:23 +02:00
{
m_resultCount = resultCount;
2012-05-18 09:45:23 +02:00
m_timeStepCount = timeStepCount;
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::populateReservoir( RigEclipseCaseData* eclipseCase )
2012-05-18 09:45:23 +02:00
{
m_reservoirBuilder.createGridsAndCells( eclipseCase );
2012-05-18 09:45:23 +02:00
if ( m_enableWellData )
2013-10-28 10:31:46 +01:00
{
addWellData( eclipseCase, eclipseCase->mainGrid() );
2013-10-28 10:31:46 +01:00
}
2013-02-25 14:07:59 +01:00
addFaults( eclipseCase );
2013-12-06 19:38:42 +01:00
2013-05-21 21:03:05 +02:00
// Add grid coarsening for main grid
// if ( cellDimension().x() > 4 && cellDimension().y() > 5 && cellDimension().z() > 6 )
// {
// eclipseCase->mainGrid()->addCoarseningBox( 1, 2, 1, 3, 1, 4 );
// eclipseCase->mainGrid()->addCoarseningBox( 3, 4, 4, 5, 5, 6 );
// }
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::addLocalGridRefinement( const cvf::Vec3st& mainGridStart,
const cvf::Vec3st& mainGridEnd,
const cvf::Vec3st& refinementFactors )
2012-05-18 09:45:23 +02:00
{
m_reservoirBuilder.addLocalGridRefinement( mainGridStart, mainGridEnd, refinementFactors );
2012-05-18 09:45:23 +02:00
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::setWorldCoordinates( cvf::Vec3d minWorldCoordinate, cvf::Vec3d maxWorldCoordinate )
2012-05-18 09:45:23 +02:00
{
m_reservoirBuilder.setWorldCoordinates( minWorldCoordinate, maxWorldCoordinate );
2012-05-18 09:45:23 +02:00
}
2012-06-26 16:10:41 +02:00
//--------------------------------------------------------------------------------------------------
///
2012-06-26 16:10:41 +02:00
//--------------------------------------------------------------------------------------------------
2023-02-26 10:48:40 +01:00
bool RigReservoirBuilderMock::inputProperty( RigEclipseCaseData* eclipseCase, const QString& propertyName, std::vector<double>* values )
2012-06-26 16:10:41 +02:00
{
size_t k;
/* initialize random seed: */
srand( time( nullptr ) );
2012-06-26 16:10:41 +02:00
/* generate secret number: */
int iSecret = rand() % 20 + 1;
2024-10-23 20:43:08 +02:00
for ( k = 0; k < eclipseCase->mainGrid()->totalCellCount(); k++ )
2012-06-26 16:10:41 +02:00
{
values->push_back( k * iSecret );
2012-06-26 16:10:41 +02:00
}
return true;
}
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
2020-02-12 11:43:15 +01:00
bool RigReservoirBuilderMock::staticResult( RigEclipseCaseData* eclipseCase, const QString& result, std::vector<double>* values )
2012-05-18 09:45:23 +02:00
{
2024-10-23 20:43:08 +02:00
values->resize( eclipseCase->mainGrid()->totalCellCount() );
2012-05-18 09:45:23 +02:00
2014-04-24 09:52:46 +02:00
#pragma omp parallel for
2024-10-23 20:43:08 +02:00
for ( long long k = 0; k < static_cast<long long>( eclipseCase->mainGrid()->totalCellCount() ); k++ )
2012-05-18 09:45:23 +02:00
{
2024-10-23 20:43:08 +02:00
values->at( k ) = ( k * 2 ) % eclipseCase->mainGrid()->totalCellCount();
2012-05-18 09:45:23 +02:00
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
2023-02-26 10:48:40 +01:00
bool RigReservoirBuilderMock::dynamicResult( RigEclipseCaseData* eclipseCase, const QString& result, size_t stepIndex, std::vector<double>* values )
2012-05-18 09:45:23 +02:00
{
int resultIndex = 1;
2024-10-28 13:09:18 +01:00
QRegularExpression rx( "[0-9]{1,2}" ); // Find number 0-99
QRegularExpressionMatch match = rx.match( result );
if ( match.hasMatch() )
2012-05-18 09:45:23 +02:00
{
2024-10-28 13:09:18 +01:00
resultIndex = match.captured( 0 ).toInt() + 1;
2012-05-18 09:45:23 +02:00
}
double scaleValue = 1.0 + resultIndex * 0.1;
2012-05-18 09:45:23 +02:00
double offsetValue = 100 * resultIndex;
2024-10-23 20:43:08 +02:00
values->resize( eclipseCase->mainGrid()->totalCellCount() );
2013-11-08 10:34:05 +01:00
#pragma omp parallel for
2024-10-23 20:43:08 +02:00
for ( long long k = 0; k < static_cast<long long>( eclipseCase->mainGrid()->totalCellCount() ); k++ )
2012-05-18 09:45:23 +02:00
{
2024-10-23 20:43:08 +02:00
double val = offsetValue + scaleValue * ( ( stepIndex * 1000 + k ) % eclipseCase->mainGrid()->totalCellCount() );
values->at( k ) = val;
2012-05-18 09:45:23 +02:00
}
2012-08-31 19:12:47 +02:00
// Set result size to zero for some timesteps
if ( ( stepIndex + 1 ) % 3 == 0 )
2012-08-31 19:12:47 +02:00
{
values->clear();
}
2012-05-18 09:45:23 +02:00
return true;
}
//--------------------------------------------------------------------------------------------------
///
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::addWellData( RigEclipseCaseData* eclipseCase, RigGridBase* grid )
2012-05-18 09:45:23 +02:00
{
CAF_ASSERT( eclipseCase );
CAF_ASSERT( grid );
2012-05-18 09:45:23 +02:00
2024-01-21 21:13:24 +01:00
auto cellCountJ = grid->cellCountJ();
auto cellCountK = grid->cellCountK();
2012-05-18 09:45:23 +02:00
cvf::Collection<RigSimWellData> wells;
2012-05-18 09:45:23 +02:00
int wellIdx;
for ( wellIdx = 0; wellIdx < 1; wellIdx++ )
2012-05-18 09:45:23 +02:00
{
cvf::ref<RigSimWellData> wellCellsTimeHistory = new RigSimWellData;
wellCellsTimeHistory->m_wellName = QString( "Well %1" ).arg( wellIdx );
2012-05-18 09:45:23 +02:00
wellCellsTimeHistory->m_wellCellsTimeSteps.resize( m_timeStepCount );
2012-05-18 09:45:23 +02:00
size_t timeIdx;
for ( timeIdx = 0; timeIdx < m_timeStepCount; timeIdx++ )
2012-05-18 09:45:23 +02:00
{
RigWellResultFrame& wellCells = wellCellsTimeHistory->m_wellCellsTimeSteps[timeIdx];
2023-04-14 11:00:45 +02:00
wellCells.setProductionType( RiaDefines::WellProductionType::PRODUCER );
wellCells.setIsOpen( true );
2012-05-18 09:45:23 +02:00
2023-04-14 11:00:45 +02:00
auto wellHead = wellCells.wellHead();
wellHead.setGridIndex( 0 );
wellHead.setGridCellIndex( grid->cellIndexFromIJK( 1, 0, 0 ) );
wellCells.setWellHead( wellHead );
2012-05-18 09:45:23 +02:00
// Connections
// int connectionCount = std::min(dim.x(), std::min(dim.y(), dim.z())) - 2;
2024-01-21 21:13:24 +01:00
size_t connectionCount = cellCountK - 2;
if ( connectionCount > 0 )
2012-05-18 09:45:23 +02:00
{
// Only main grid supported by now. Must be taken care of when LGRs are supported
2023-04-14 11:00:45 +02:00
auto newWellResultBranches = wellCells.wellResultBranches();
newWellResultBranches.resize( 1 );
RigWellResultBranch& wellSegment = newWellResultBranches[0];
2012-05-18 09:45:23 +02:00
size_t connIdx;
for ( connIdx = 0; connIdx < connectionCount; connIdx++ )
2012-05-18 09:45:23 +02:00
{
2023-04-13 07:05:53 +02:00
if ( connIdx == (size_t)( connectionCount / 4 ) ) continue;
2012-05-18 09:45:23 +02:00
RigWellResultPoint data;
2023-02-28 16:06:37 +01:00
data.setGridIndex( 0 );
2012-05-18 09:45:23 +02:00
2024-01-21 21:13:24 +01:00
if ( connIdx < cellCountJ - 2 )
2023-02-28 16:06:37 +01:00
data.setGridCellIndex( grid->cellIndexFromIJK( 1, 1 + connIdx, 1 + connIdx ) );
2012-05-18 09:45:23 +02:00
else
2024-01-21 21:13:24 +01:00
data.setGridCellIndex( grid->cellIndexFromIJK( 1, cellCountJ - 2, 1 + connIdx ) );
2012-05-18 09:45:23 +02:00
if ( connIdx < connectionCount / 2 )
2012-05-18 09:45:23 +02:00
{
2023-02-28 16:06:37 +01:00
data.setIsOpen( true );
2012-05-18 09:45:23 +02:00
}
else
{
2023-02-28 16:06:37 +01:00
data.setIsOpen( false );
2012-05-18 09:45:23 +02:00
}
2023-04-14 11:00:45 +02:00
if ( wellSegment.branchResultPoints().empty() || wellSegment.branchResultPoints().back().cellIndex() != data.cellIndex() )
2012-05-18 09:45:23 +02:00
{
2023-04-14 11:00:45 +02:00
wellSegment.addBranchResultPoint( data );
2012-05-18 09:45:23 +02:00
if ( connIdx == connectionCount / 2 )
2012-05-18 09:45:23 +02:00
{
RigWellResultPoint deadEndData = data;
2023-02-28 16:06:37 +01:00
deadEndData.setGridCellIndex( data.cellIndex() + 1 );
deadEndData.setIsOpen( true );
2012-05-18 09:45:23 +02:00
RigWellResultPoint deadEndData1 = data;
2023-02-28 16:06:37 +01:00
deadEndData1.setGridCellIndex( data.cellIndex() + 2 );
deadEndData1.setIsOpen( false );
2012-05-18 09:45:23 +02:00
2023-04-14 11:00:45 +02:00
wellSegment.addBranchResultPoint( deadEndData );
wellSegment.addBranchResultPoint( deadEndData1 );
2012-05-18 09:45:23 +02:00
2023-04-14 11:00:45 +02:00
wellSegment.addBranchResultPoint( deadEndData );
2012-05-18 09:45:23 +02:00
2023-02-28 16:06:37 +01:00
data.setIsOpen( true );
2023-04-14 11:00:45 +02:00
wellSegment.addBranchResultPoint( data );
2012-05-18 09:45:23 +02:00
}
}
2024-01-21 21:13:24 +01:00
if ( connIdx < cellCountJ - 2 )
2012-05-18 09:45:23 +02:00
{
2023-02-28 16:06:37 +01:00
data.setGridCellIndex( grid->cellIndexFromIJK( 1, 1 + connIdx, 2 + connIdx ) );
2012-05-18 09:45:23 +02:00
2023-04-14 11:00:45 +02:00
if ( wellSegment.branchResultPoints().empty() ||
wellSegment.branchResultPoints().back().cellIndex() != data.cellIndex() )
2012-05-18 09:45:23 +02:00
{
2023-04-14 11:00:45 +02:00
wellSegment.addBranchResultPoint( data );
2012-05-18 09:45:23 +02:00
}
}
}
2023-04-14 11:00:45 +02:00
wellCells.setWellResultBranches( newWellResultBranches );
2012-05-18 09:45:23 +02:00
}
}
// Create a mapping from result timestep indices to well timestep indices.
// Use one-to-one mapping for easy use
std::vector<size_t> map;
for ( timeIdx = 0; timeIdx < m_timeStepCount; timeIdx++ )
2012-05-18 09:45:23 +02:00
{
map.push_back( timeIdx );
2012-05-18 09:45:23 +02:00
}
wellCellsTimeHistory->m_resultTimeStepIndexToWellTimeStepIndex = map;
wells.push_back( wellCellsTimeHistory.p() );
2012-05-18 09:45:23 +02:00
}
eclipseCase->setSimWellData( wells );
2012-05-18 09:45:23 +02:00
}
2013-12-06 19:38:42 +01:00
//--------------------------------------------------------------------------------------------------
///
2013-12-06 19:38:42 +01:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::addFaults( RigEclipseCaseData* eclipseCase )
2013-12-06 19:38:42 +01:00
{
if ( !eclipseCase ) return;
2013-12-06 19:38:42 +01:00
RigMainGrid* grid = eclipseCase->mainGrid();
if ( !grid ) return;
2013-12-06 19:38:42 +01:00
cvf::Collection<RigFault> faults;
auto cellDimension = m_reservoirBuilder.ijkCount();
2013-12-06 19:38:42 +01:00
{
cvf::ref<RigFault> fault = new RigFault;
fault->setName( "Fault A" );
2013-12-06 19:38:42 +01:00
cvf::Vec3st min = cvf::Vec3st::ZERO;
cvf::Vec3st max( 0, 0, cellDimension.z() - 2 );
if ( cellDimension.x() > 5 )
2013-12-06 19:38:42 +01:00
{
min.x() = cellDimension.x() / 2;
max.x() = min.x() + 2;
2013-12-06 19:38:42 +01:00
}
if ( cellDimension.y() > 5 )
2013-12-06 19:38:42 +01:00
{
min.y() = cellDimension.y() / 2;
max.y() = cellDimension.y() / 2;
2013-12-06 19:38:42 +01:00
}
cvf::CellRange cellRange( min, max );
2013-12-06 19:38:42 +01:00
fault->addCellRangeForFace( cvf::StructGridInterface::POS_I, cellRange );
faults.push_back( fault.p() );
2013-12-06 19:38:42 +01:00
}
grid->setFaults( faults );
// NNCs
std::vector<RigConnection> nncConnections;
{
size_t i1 = 2;
size_t j1 = 2;
size_t k1 = 3;
size_t i2 = 2;
size_t j2 = 3;
size_t k2 = 4;
addNnc( grid, i1, j1, k1, i2, j2, k2, nncConnections );
}
{
size_t i1 = 2;
size_t j1 = 2;
size_t k1 = 3;
size_t i2 = 2;
size_t j2 = 1;
size_t k2 = 4;
addNnc( grid, i1, j1, k1, i2, j2, k2, nncConnections );
}
2014-08-26 12:07:08 +02:00
grid->nncData()->setEclipseConnections( nncConnections );
2023-02-26 10:48:40 +01:00
std::vector<double>& tranVals = grid->nncData()->makeStaticConnectionScalarResult( RiaDefines::propertyNameCombTrans() );
for ( size_t cIdx = 0; cIdx < tranVals.size(); ++cIdx )
2014-08-26 12:07:08 +02:00
{
tranVals[cIdx] = 0.2;
}
2013-12-06 19:38:42 +01:00
}
2014-04-14 10:24:15 +02:00
//--------------------------------------------------------------------------------------------------
///
2014-04-14 10:24:15 +02:00
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::enableWellData( bool enableWellData )
2013-10-28 10:31:46 +01:00
{
m_enableWellData = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigReservoirBuilderMock::addNnc( RigMainGrid* grid,
size_t i1,
size_t j1,
size_t k1,
size_t i2,
size_t j2,
size_t k2,
std::vector<RigConnection>& nncConnections )
{
if ( i1 >= grid->cellCountI() || j1 >= grid->cellCountJ() || k1 >= grid->cellCountK() ) return;
if ( i2 >= grid->cellCountI() || j2 >= grid->cellCountJ() || k2 >= grid->cellCountK() ) return;
size_t c1GlobalIndex = grid->cellIndexFromIJK( i1, j1, k1 );
size_t c2GlobalIndex = grid->cellIndexFromIJK( i2, j2, k2 );
2020-05-14 19:11:45 +02:00
RigConnection conn( c1GlobalIndex, c2GlobalIndex );
nncConnections.push_back( conn );
}