mirror of
				https://github.com/OPM/ResInsight.git
				synced 2025-02-25 18:55:39 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			402 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/////////////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
//  Copyright (C) 2011-2012 Statoil ASA, Ceetron AS
 | 
						|
// 
 | 
						|
//  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 "RigSimWellData.h"
 | 
						|
 | 
						|
#include <map>
 | 
						|
 | 
						|
#include <QDebug>
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
RigSimWellData::RigSimWellData()
 | 
						|
    : m_isMultiSegmentWell(false)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
const RigWellResultFrame& RigSimWellData::wellResultFrame(size_t resultTimeStepIndex) const
 | 
						|
{
 | 
						|
    CVF_ASSERT(resultTimeStepIndex < m_resultTimeStepIndexToWellTimeStepIndex.size());
 | 
						|
 | 
						|
    size_t wellTimeStepIndex = m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex];
 | 
						|
    CVF_ASSERT(wellTimeStepIndex < m_wellCellsTimeSteps.size());
 | 
						|
 | 
						|
    return m_wellCellsTimeSteps[wellTimeStepIndex];
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
void RigSimWellData::computeMappingFromResultTimeIndicesToWellTimeIndices(const std::vector<QDateTime>& simulationTimeSteps)
 | 
						|
{
 | 
						|
    m_resultTimeStepIndexToWellTimeStepIndex.clear();
 | 
						|
    if (m_wellCellsTimeSteps.size() == 0) return;
 | 
						|
 | 
						|
    m_resultTimeStepIndexToWellTimeStepIndex.resize(simulationTimeSteps.size(), cvf::UNDEFINED_SIZE_T);
 | 
						|
 | 
						|
    if (false)
 | 
						|
    {
 | 
						|
        qDebug() << "Well TimeStamps";
 | 
						|
        for (size_t i = 0; i < m_wellCellsTimeSteps.size(); i++)
 | 
						|
        {
 | 
						|
            qDebug() << m_wellCellsTimeSteps[i].m_timestamp.toString();
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        qDebug() << "Result TimeStamps";
 | 
						|
        for (size_t i = 0; i < simulationTimeSteps.size(); i++)
 | 
						|
        {
 | 
						|
            qDebug() << simulationTimeSteps[i].toString();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    size_t wellTimeStepIndex = 0;
 | 
						|
    for (size_t resultTimeStepIndex = 0; resultTimeStepIndex < simulationTimeSteps.size(); resultTimeStepIndex++)
 | 
						|
    {
 | 
						|
        while ( wellTimeStepIndex < m_wellCellsTimeSteps.size() &&
 | 
						|
                m_wellCellsTimeSteps[wellTimeStepIndex].m_timestamp < simulationTimeSteps[resultTimeStepIndex])
 | 
						|
        {
 | 
						|
            wellTimeStepIndex++;
 | 
						|
        }
 | 
						|
 | 
						|
        if (   wellTimeStepIndex < m_wellCellsTimeSteps.size() 
 | 
						|
            && m_wellCellsTimeSteps[wellTimeStepIndex].m_timestamp == simulationTimeSteps[resultTimeStepIndex])
 | 
						|
        {
 | 
						|
            m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex] = wellTimeStepIndex;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex] = cvf::UNDEFINED_SIZE_T;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
bool RigSimWellData::hasWellResult(size_t resultTimeStepIndex) const
 | 
						|
{
 | 
						|
    if (resultTimeStepIndex >= m_resultTimeStepIndexToWellTimeStepIndex.size())
 | 
						|
    {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    size_t wellTimeStepIndex = m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex];
 | 
						|
 | 
						|
    return wellTimeStepIndex != cvf::UNDEFINED_SIZE_T;
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
bool RigSimWellData::hasAnyValidCells(size_t resultTimeStepIndex) const
 | 
						|
{
 | 
						|
    if (resultTimeStepIndex >= m_resultTimeStepIndexToWellTimeStepIndex.size())
 | 
						|
    {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    size_t wellTimeStepIndex = m_resultTimeStepIndexToWellTimeStepIndex[resultTimeStepIndex];
 | 
						|
 | 
						|
    if( wellTimeStepIndex == cvf::UNDEFINED_SIZE_T) return false;
 | 
						|
    
 | 
						|
    if (wellResultFrame(resultTimeStepIndex).m_wellHead.isCell()) return true;
 | 
						|
 | 
						|
    const std::vector<RigWellResultBranch> &resBranches = wellResultFrame(resultTimeStepIndex).m_wellResultBranches;
 | 
						|
 | 
						|
    for ( size_t i = 0 ; i < resBranches.size(); ++i )
 | 
						|
    {
 | 
						|
        for (size_t cIdx = 0; cIdx < resBranches[i].m_branchResultPoints.size(); ++cIdx )
 | 
						|
        {
 | 
						|
            if (resBranches[i].m_branchResultPoints[cIdx].isCell()) return true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
 | 
						|
bool operator== (const RigWellResultPoint& p1, const RigWellResultPoint& p2)
 | 
						|
{
 | 
						|
    return 
 | 
						|
        p1.m_gridIndex == p2.m_gridIndex 
 | 
						|
        && p1.m_gridCellIndex == p2.m_gridCellIndex
 | 
						|
        && p1.m_ertBranchId == p2.m_ertBranchId
 | 
						|
        && p1.m_ertSegmentId == p2.m_ertSegmentId;
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
void RigSimWellData::computeStaticWellCellPath() const
 | 
						|
{
 | 
						|
    if (m_wellCellsTimeSteps.size() == 0) return;
 | 
						|
 | 
						|
    // Mapping of Branch ERT ID to ResultPoint list
 | 
						|
    std::map < int, std::list< RigWellResultPoint > > staticWellBranches;
 | 
						|
 | 
						|
    // Add ResultCell data from the first timestep to the final result.
 | 
						|
 | 
						|
    for (size_t bIdx = 0; bIdx < m_wellCellsTimeSteps[0].m_wellResultBranches.size(); ++bIdx)
 | 
						|
    {
 | 
						|
        int branchErtId = m_wellCellsTimeSteps[0].m_wellResultBranches[bIdx].m_ertBranchId;
 | 
						|
        const std::vector<RigWellResultPoint>& frameCells = m_wellCellsTimeSteps[0].m_wellResultBranches[bIdx].m_branchResultPoints;
 | 
						|
       
 | 
						|
        std::list< RigWellResultPoint >& branch =  staticWellBranches[branchErtId];
 | 
						|
 | 
						|
        for(size_t cIdx = 0; cIdx < frameCells.size(); ++cIdx)
 | 
						|
        {
 | 
						|
            branch.push_back(frameCells[cIdx]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    for (size_t tIdx = 1; tIdx < m_wellCellsTimeSteps.size(); ++tIdx)
 | 
						|
    {
 | 
						|
        // Merge well branches separately
 | 
						|
 | 
						|
        for (size_t bIdx = 0; bIdx < m_wellCellsTimeSteps[tIdx].m_wellResultBranches.size(); ++bIdx)
 | 
						|
        {
 | 
						|
            int branchId = m_wellCellsTimeSteps[tIdx].m_wellResultBranches[bIdx].m_ertBranchId;
 | 
						|
            const std::vector<RigWellResultPoint>& resBranch = m_wellCellsTimeSteps[tIdx].m_wellResultBranches[bIdx].m_branchResultPoints;
 | 
						|
 | 
						|
            std::list< RigWellResultPoint >& stBranch =  staticWellBranches[branchId];
 | 
						|
            std::list< RigWellResultPoint >::iterator sEndIt;
 | 
						|
            size_t  rStartIdx = -1;
 | 
						|
            size_t  rEndIdx = -1;
 | 
						|
 | 
						|
            // First detect if we have cells on the start of the result frame, that is not in the static frame
 | 
						|
            {
 | 
						|
                sEndIt = stBranch.begin();
 | 
						|
                bool found = false;
 | 
						|
                if (!stBranch.empty())
 | 
						|
                {
 | 
						|
                    for (rEndIdx = 0; !found && rEndIdx < resBranch.size(); ++rEndIdx)
 | 
						|
                    {
 | 
						|
                        if ((*sEndIt) == (resBranch[rEndIdx])) { found = true; break; }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                if (found)
 | 
						|
                {
 | 
						|
                    if (rEndIdx > 0)
 | 
						|
                    {
 | 
						|
                        // Found cells in start, merge them in
 | 
						|
                        for (size_t cIdx = 0; cIdx < rEndIdx; ++cIdx)
 | 
						|
                        {
 | 
						|
                            stBranch.insert(sEndIt, resBranch[cIdx]);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else 
 | 
						|
                {
 | 
						|
                    // The result probably starts later in the well
 | 
						|
                    rEndIdx = 0;
 | 
						|
                }
 | 
						|
 | 
						|
                rStartIdx = rEndIdx;
 | 
						|
            }
 | 
						|
 | 
						|
            // Now find all result cells in ranges between pairs in the static path
 | 
						|
            // If the result has items that "compete" with those in the static path, 
 | 
						|
            // those items are inserted after the ones in the static path. This 
 | 
						|
            // is not neccesarily correct. They could be in front, and also merged in 
 | 
						|
            // strange ways. A geometric test could make this more robust, but we will 
 | 
						|
            // not solve before we see that it actually ends up as a problem
 | 
						|
 | 
						|
            if (sEndIt !=  stBranch.end()) ++sEndIt;
 | 
						|
            for ( ; sEndIt != stBranch.end() ; ++sEndIt)
 | 
						|
            {
 | 
						|
                bool found = false;
 | 
						|
                for (rEndIdx += 1; !found && rEndIdx < resBranch.size(); ++rEndIdx)
 | 
						|
                {
 | 
						|
                    if ((*sEndIt) == (resBranch[rEndIdx])) { found = true; break; }
 | 
						|
                }
 | 
						|
 | 
						|
                if (found)
 | 
						|
                 {
 | 
						|
                    if (rEndIdx - rStartIdx > 1)
 | 
						|
                    {
 | 
						|
                        // Found cell range in result that we do not have in the static result, merge them in
 | 
						|
                        for (size_t cIdx = rStartIdx + 1; cIdx < rEndIdx; ++cIdx)
 | 
						|
                        {
 | 
						|
                            stBranch.insert(sEndIt, resBranch[cIdx]);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    // The static path probably has some extra cells
 | 
						|
                    rEndIdx = rStartIdx;
 | 
						|
                }
 | 
						|
 | 
						|
                rStartIdx = rEndIdx;
 | 
						|
            }
 | 
						|
 | 
						|
            // Then add cells from the end of the resultpath not present in the static path
 | 
						|
            for (size_t cIdx = rEndIdx + 1; cIdx < resBranch.size(); ++cIdx)
 | 
						|
            {
 | 
						|
                stBranch.push_back(resBranch[cIdx]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // Populate the static well info 
 | 
						|
 | 
						|
    std::map < int, std::list< RigWellResultPoint > >::iterator bIt;
 | 
						|
 | 
						|
    m_staticWellCells.m_wellResultBranches.clear();
 | 
						|
    m_staticWellCells.m_wellHead = m_wellCellsTimeSteps[0].m_wellHead;
 | 
						|
 | 
						|
    for (bIt = staticWellBranches.begin(); bIt != staticWellBranches.end(); ++bIt)
 | 
						|
    {
 | 
						|
        // Copy from first time step
 | 
						|
        RigWellResultBranch rigBranch; 
 | 
						|
        rigBranch.m_ertBranchId = bIt->first;
 | 
						|
 | 
						|
        std::list< RigWellResultPoint >& branch =  bIt->second;
 | 
						|
        std::list< RigWellResultPoint >::iterator cIt;
 | 
						|
        for (cIt = branch.begin(); cIt != branch.end(); ++cIt)
 | 
						|
        {
 | 
						|
            rigBranch.m_branchResultPoints.push_back(*cIt);
 | 
						|
        }
 | 
						|
 | 
						|
        m_staticWellCells.m_wellResultBranches.push_back(rigBranch);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
void RigSimWellData::setMultiSegmentWell(bool isMultiSegmentWell)
 | 
						|
{
 | 
						|
    m_isMultiSegmentWell = isMultiSegmentWell;
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
bool RigSimWellData::isMultiSegmentWell() const
 | 
						|
{
 | 
						|
    return m_isMultiSegmentWell;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
RigWellResultFrame::WellProductionType RigSimWellData::wellProductionType(size_t resultTimeStepIndex) const
 | 
						|
{
 | 
						|
    if (hasWellResult(resultTimeStepIndex))
 | 
						|
    {
 | 
						|
        const RigWellResultFrame& wResFrame = wellResultFrame(resultTimeStepIndex);
 | 
						|
        return wResFrame.m_productionType;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        return RigWellResultFrame::UNDEFINED_PRODUCTION_TYPE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
const RigWellResultFrame& RigSimWellData::staticWellCells() const
 | 
						|
{
 | 
						|
    // Make sure we have computed the static representation of the well
 | 
						|
    if (m_staticWellCells.m_wellResultBranches.size() == 0)
 | 
						|
    {
 | 
						|
        computeStaticWellCellPath();
 | 
						|
    }
 | 
						|
 | 
						|
    return m_staticWellCells;
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
bool RigSimWellData::isOpen(size_t resultTimeStepIndex) const
 | 
						|
{
 | 
						|
    if (hasWellResult(resultTimeStepIndex))
 | 
						|
    {
 | 
						|
        const RigWellResultFrame& wResFrame = wellResultFrame(resultTimeStepIndex);
 | 
						|
        return wResFrame.m_isOpen;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
const RigWellResultPoint* RigWellResultFrame::findResultCell(size_t gridIndex, size_t gridCellIndex) const
 | 
						|
{
 | 
						|
    CVF_ASSERT(gridIndex != cvf::UNDEFINED_SIZE_T && gridCellIndex != cvf::UNDEFINED_SIZE_T);
 | 
						|
 | 
						|
    for (size_t wb = 0; wb < m_wellResultBranches.size(); ++wb)
 | 
						|
    {
 | 
						|
        for (size_t wc = 0; wc < m_wellResultBranches[wb].m_branchResultPoints.size(); ++wc)
 | 
						|
        {
 | 
						|
            if (   m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridCellIndex == gridCellIndex  
 | 
						|
                && m_wellResultBranches[wb].m_branchResultPoints[wc].m_gridIndex == gridIndex  )
 | 
						|
            {
 | 
						|
                return &(m_wellResultBranches[wb].m_branchResultPoints[wc]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // If we could not find the cell among the real connections, we try the wellhead.
 | 
						|
    // The wellhead does however not have a real connection state, and is thereby always rendered as closed
 | 
						|
    // If we have a real connection in the wellhead, we should not end here. See Github issue #712
 | 
						|
 | 
						|
    if (m_wellHead.m_gridCellIndex == gridCellIndex && m_wellHead.m_gridIndex == gridIndex )
 | 
						|
    {
 | 
						|
        return &m_wellHead;
 | 
						|
    }
 | 
						|
 | 
						|
    return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
/// 
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
RigWellResultPoint RigWellResultFrame::wellHeadOrStartCell() const
 | 
						|
{
 | 
						|
    if (m_wellHead.isCell()) return m_wellHead;
 | 
						|
 | 
						|
    for ( const RigWellResultBranch& resBranch : m_wellResultBranches )
 | 
						|
    {
 | 
						|
        for ( const RigWellResultPoint& wrp: resBranch.m_branchResultPoints )
 | 
						|
        {
 | 
						|
            if ( wrp.isCell() ) return wrp;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return m_wellHead; // Nothing else to do
 | 
						|
}
 |