mirror of
				https://github.com/OPM/ResInsight.git
				synced 2025-02-25 18:55:39 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/////////////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
//  Copyright (C) 2019-    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 "RigCaseCellResultCalculator.h"
 | 
						|
 | 
						|
#include "RiaApplication.h"
 | 
						|
#include "RiaLogging.h"
 | 
						|
 | 
						|
#include "RigCaseCellResultsData.h"
 | 
						|
#include "RigEclipseCaseData.h"
 | 
						|
#include "RigEclipseResultAddress.h"
 | 
						|
#include "RigGridManager.h"
 | 
						|
#include "RigMainGrid.h"
 | 
						|
#include "RigResultAccessorFactory.h"
 | 
						|
#include "RigResultModifier.h"
 | 
						|
#include "RigResultModifierFactory.h"
 | 
						|
 | 
						|
#include "RimEclipseCase.h"
 | 
						|
#include "RimProject.h"
 | 
						|
 | 
						|
#include "cvfAssert.h"
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
///
 | 
						|
//--------------------------------------------------------------------------------------------------
 | 
						|
bool RigCaseCellResultCalculator::computeDifference(RigEclipseCaseData*            sourceCase,
 | 
						|
                                                    RiaDefines::PorosityModelType  porosityModel,
 | 
						|
                                                    const RigEclipseResultAddress& address)
 | 
						|
{
 | 
						|
    CVF_ASSERT(address.isValid());
 | 
						|
    CVF_ASSERT(address.hasDifferenceCase() || address.isTimeLapse());
 | 
						|
 | 
						|
    // Assume at this stage that data for the case is available
 | 
						|
    // It is up to the caller to make sure the case is read from file
 | 
						|
 | 
						|
    RigEclipseCaseData* baseCase = sourceCase;
 | 
						|
 | 
						|
    if (address.hasDifferenceCase())
 | 
						|
    {
 | 
						|
        {
 | 
						|
            auto eclipseCases = RiaApplication::instance()->project()->eclipseCases();
 | 
						|
            for (RimEclipseCase* c : eclipseCases)
 | 
						|
            {
 | 
						|
                if (c && c->caseId() == address.m_differenceCaseId && c->eclipseCaseData())
 | 
						|
                {
 | 
						|
                	baseCase = c->eclipseCaseData();
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (!baseCase || !sourceCase)
 | 
						|
    {
 | 
						|
        RiaLogging::error("Missing input case for difference calculator");
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    RigMainGrid* sourceMainGrid = sourceCase->mainGrid();
 | 
						|
    RigMainGrid* baseMainGrid  = baseCase->mainGrid();
 | 
						|
 | 
						|
    if (!RigGridManager::isEqual(sourceMainGrid, baseMainGrid))
 | 
						|
    {
 | 
						|
        RiaLogging::error("Case difference : Grid cases do not match");
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    RigCaseCellResultsData* baseCaseResults   = baseCase->results(porosityModel);
 | 
						|
    RigCaseCellResultsData* sourceCaseResults = sourceCase->results(porosityModel);
 | 
						|
 | 
						|
    if (!baseCaseResults || !sourceCaseResults)
 | 
						|
    {
 | 
						|
        RiaLogging::error("Missing result data for difference calculator");
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    RigEclipseResultAddress nativeAddress(address);
 | 
						|
    nativeAddress.m_differenceCaseId      = RigEclipseResultAddress::NO_CASE_DIFF;
 | 
						|
    nativeAddress.m_timeLapseBaseFrameIdx = RigEclipseResultAddress::NO_TIME_LAPSE;
 | 
						|
    if (!sourceCaseResults->ensureKnownResultLoaded(nativeAddress))
 | 
						|
    {
 | 
						|
        RiaLogging::error("Failed to load destination diff result");
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!baseCaseResults->ensureKnownResultLoaded(nativeAddress))
 | 
						|
    {
 | 
						|
        RiaLogging::error("Failed to load difference result");
 | 
						|
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // Initialize difference result with infinity for correct number of time steps and values per time step
 | 
						|
    {
 | 
						|
        const std::vector<std::vector<double>>& srcFrames  = sourceCaseResults->cellScalarResults(nativeAddress);
 | 
						|
        std::vector<std::vector<double>>& diffResultFrames = sourceCaseResults->modifiableCellScalarResultTimesteps(address);
 | 
						|
        diffResultFrames.resize(srcFrames.size());
 | 
						|
        for (size_t fIdx = 0; fIdx < srcFrames.size(); ++fIdx)
 | 
						|
        {
 | 
						|
            const std::vector<double>& srcVals = srcFrames[fIdx];
 | 
						|
            std::vector<double>&       dstVals = diffResultFrames[fIdx];
 | 
						|
 | 
						|
            dstVals.resize(srcVals.size(), std::numeric_limits<double>::infinity());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    size_t baseFrameCount   = baseCaseResults->cellScalarResults(nativeAddress).size();
 | 
						|
    size_t sourceFrameCount = sourceCaseResults->cellScalarResults(nativeAddress).size();
 | 
						|
    size_t maxFrameCount    = std::min(baseFrameCount, sourceFrameCount);
 | 
						|
 | 
						|
    for (size_t gridIdx = 0; gridIdx < sourceMainGrid->gridCount(); ++gridIdx)
 | 
						|
    {
 | 
						|
        auto                     grid           = sourceMainGrid->gridByIndex(gridIdx);
 | 
						|
        const RigActiveCellInfo* activeCellInfo = sourceCaseResults->activeCellInfo();
 | 
						|
 | 
						|
        for (size_t fIdx = 0; fIdx < maxFrameCount; ++fIdx)
 | 
						|
        {
 | 
						|
            cvf::ref<RigResultAccessor> sourceResultAccessor =
 | 
						|
                RigResultAccessorFactory::createFromResultAddress(sourceCase, gridIdx, porosityModel, fIdx, nativeAddress);
 | 
						|
 | 
						|
            cvf::ref<RigResultModifier> resultModifier =
 | 
						|
                RigResultModifierFactory::createResultModifier(sourceCase, gridIdx, porosityModel, fIdx, address);
 | 
						|
 | 
						|
            size_t baseFrameIdx = fIdx;
 | 
						|
            if (address.isTimeLapse())
 | 
						|
            {
 | 
						|
                baseFrameIdx = address.m_timeLapseBaseFrameIdx;
 | 
						|
            }
 | 
						|
 | 
						|
            cvf::ref<RigResultAccessor> baseResultAccessor =
 | 
						|
                RigResultAccessorFactory::createFromResultAddress(baseCase, gridIdx, porosityModel, baseFrameIdx, nativeAddress);
 | 
						|
 | 
						|
            for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++)
 | 
						|
            {
 | 
						|
                size_t reservoirCellIndex = grid->reservoirCellIndex(localGridCellIdx);
 | 
						|
                if (activeCellInfo->isActive(reservoirCellIndex))
 | 
						|
                {
 | 
						|
                    double sourceVal = sourceResultAccessor->cellScalar(localGridCellIdx);
 | 
						|
                    double baseVal  = baseResultAccessor->cellScalar(localGridCellIdx);
 | 
						|
 | 
						|
                    double difference = sourceVal - baseVal;
 | 
						|
 | 
						|
                    resultModifier->setCellScalar(localGridCellIdx, difference);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 |