Adds support for MSW completion data

Introduces structures and classes to represent and manage data from MSW completion tables (WELSEGS, COMPSEGS, WSEGVALV, WSEGAICD).
This commit is contained in:
Magne Sjaastad committed 2025-10-31 08:11:19 +01:00
1 parent f384b5ef38
commit 8b9d6aa42c
5 files changed
+338

No files matched your search

@@ -0,0 +1,8 @@
set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigMswTableRows.h
${CMAKE_CURRENT_LIST_DIR}/RigMswTableData.h
)
set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigMswTableData.cpp)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
@@ -0,0 +1,153 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RigMswTableData.h"
#include <algorithm>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigMswTableData::RigMswTableData( const std::string& wellName, RiaDefines::EclipseUnitSystem unitSystem )
: m_wellName( wellName )
, m_unitSystem( unitSystem )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigMswTableData::setWelsegsHeader( const WelsegsHeader& header )
{
m_welsegsHeader = header;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigMswTableData::addWelsegsRow( const WelsegsRow& row )
{
m_welsegsData.push_back( row );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigMswTableData::addCompsegsRow( const CompsegsRow& row )
{
m_compsegsData.push_back( row );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigMswTableData::addWsegvalvRow( const WsegvalvRow& row )
{
m_wsegvalvData.push_back( row );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigMswTableData::addWsegaicdRow( const WsegaicdRow& row )
{
m_wsegaicdData.push_back( row );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigMswTableData::hasLgrData() const
{
return std::any_of( m_compsegsData.begin(), m_compsegsData.end(), []( const CompsegsRow& row ) { return row.isLgrGrid(); } );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigMswTableData::isEmpty() const
{
return m_welsegsData.empty() && m_compsegsData.empty() && m_wsegvalvData.empty() && m_wsegaicdData.empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<CompsegsRow> RigMswTableData::mainGridCompsegsData() const
{
std::vector<CompsegsRow> mainGridRows;
std::copy_if( m_compsegsData.begin(),
m_compsegsData.end(),
std::back_inserter( mainGridRows ),
[]( const CompsegsRow& row ) { return row.isMainGrid(); } );
return mainGridRows;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<CompsegsRow> RigMswTableData::lgrCompsegsData() const
{
std::vector<CompsegsRow> lgrRows;
std::copy_if( m_compsegsData.begin(),
m_compsegsData.end(),
std::back_inserter( lgrRows ),
[]( const CompsegsRow& row ) { return row.isLgrGrid(); } );
return lgrRows;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigMswTableData::isValid() const
{
return validationErrors().empty();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RigMswTableData::validationErrors() const
{
std::vector<QString> errors;
if ( m_wellName.empty() )
{
errors.push_back( "Well name is empty" );
}
if ( m_welsegsData.empty() )
{
errors.push_back( "No WELSEGS data" );
}
// Check for duplicate segment numbers in WELSEGS
std::vector<int> segmentNumbers;
for ( const auto& row : m_welsegsData )
{
segmentNumbers.push_back( row.segmentNumber );
}
std::sort( segmentNumbers.begin(), segmentNumbers.end() );
auto it = std::adjacent_find( segmentNumbers.begin(), segmentNumbers.end() );
if ( it != segmentNumbers.end() )
{
errors.push_back( QString( "Duplicate segment number: %1" ).arg( *it ) );
}
return errors;
}
@@ -0,0 +1,77 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaDefines.h"
#include "RigMswTableRows.h"
#include <vector>
//==================================================================================================
/// Container class for MSW table data for a single well
//==================================================================================================
class RigMswTableData
{
public:
RigMswTableData( const std::string& wellName, RiaDefines::EclipseUnitSystem unitSystem );
// Data access
const WelsegsHeader& welsegsHeader() const { return m_welsegsHeader; }
const std::vector<WelsegsRow>& welsegsData() const { return m_welsegsData; }
const std::vector<CompsegsRow>& compsegsData() const { return m_compsegsData; }
const std::vector<WsegvalvRow>& wsegvalvData() const { return m_wsegvalvData; }
const std::vector<WsegaicdRow>& wsegaicdData() const { return m_wsegaicdData; }
// Data modification
void setWelsegsHeader( const WelsegsHeader& header );
void addWelsegsRow( const WelsegsRow& row );
void addCompsegsRow( const CompsegsRow& row );
void addWsegvalvRow( const WsegvalvRow& row );
void addWsegaicdRow( const WsegaicdRow& row );
// Metadata
std::string wellName() const { return m_wellName; }
RiaDefines::EclipseUnitSystem unitSystem() const { return m_unitSystem; }
// Data analysis
bool hasLgrData() const;
bool isEmpty() const;
bool hasWelsegsData() const { return !m_welsegsData.empty(); }
bool hasCompsegsData() const { return !m_compsegsData.empty(); }
bool hasWsegvalvData() const { return !m_wsegvalvData.empty(); }
bool hasWsegaicdData() const { return !m_wsegaicdData.empty(); }
// Filtering for LGR data
std::vector<CompsegsRow> mainGridCompsegsData() const;
std::vector<CompsegsRow> lgrCompsegsData() const;
// Data validation
bool isValid() const;
std::vector<QString> validationErrors() const;
private:
std::string m_wellName;
RiaDefines::EclipseUnitSystem m_unitSystem;
WelsegsHeader m_welsegsHeader;
std::vector<WelsegsRow> m_welsegsData;
std::vector<CompsegsRow> m_compsegsData;
std::vector<WsegvalvRow> m_wsegvalvData;
std::vector<WsegaicdRow> m_wsegaicdData;
};
@@ -0,0 +1,99 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <cstddef>
#include <optional>
#include <string>
//==================================================================================================
/// Header structure for WELSEGS table (well-level information)
//==================================================================================================
struct WelsegsHeader
{
std::string wellName;
double topMD;
double topTVD;
std::optional<double> volume;
std::string lengthAndDepthText;
std::string pressureDropText;
};
//==================================================================================================
/// Row structure for WELSEGS table segment data
//==================================================================================================
struct WelsegsRow
{
int segmentNumber;
int outletSegmentNumber;
int branchNumber;
double length;
std::optional<double> depth;
std::optional<double> diameter;
std::optional<double> roughness;
std::optional<double> volume;
std::string description;
};
//==================================================================================================
/// Row structure for COMPSEGS table data
//==================================================================================================
struct CompsegsRow
{
size_t cellI;
size_t cellJ;
size_t cellK;
int branchNumber;
double startLength;
double endLength;
std::optional<int> direction;
std::optional<double> endRange;
std::optional<double> connectionDepth;
std::string gridName; // Empty for main grid, populated for LGR data
bool isMainGrid() const { return gridName.empty(); }
bool isLgrGrid() const { return !gridName.empty(); }
};
//==================================================================================================
/// Row structure for WSEGVALV table data
//==================================================================================================
struct WsegvalvRow
{
std::string wellName;
int segmentNumber;
double flowCoefficient;
std::optional<double> area;
};
//==================================================================================================
/// Row structure for WSEGAICD table data
//==================================================================================================
struct WsegaicdRow
{
std::string wellName;
int segmentNumber;
double flowCoefficient;
std::optional<double> area;
std::optional<double> oilViscosityParameter;
std::optional<double> waterViscosityParameter;
std::optional<double> gasViscosityParameter;
std::string deviceType;
};