2019-02-12 05:48:18 -06:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// 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());
|
2019-02-15 06:03:05 -06:00
|
|
|
CVF_ASSERT(address.hasDifferenceCase() || address.isTimeLapse());
|
2019-02-12 05:48:18 -06:00
|
|
|
|
|
|
|
// 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
|
|
|
|
|
2019-02-15 06:03:05 -06:00
|
|
|
RigEclipseCaseData* baseCase = sourceCase;
|
2019-02-12 05:48:18 -06:00
|
|
|
|
2019-02-15 06:03:05 -06:00
|
|
|
if (address.hasDifferenceCase())
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
|
|
|
{
|
2019-02-15 06:03:05 -06:00
|
|
|
auto eclipseCases = RiaApplication::instance()->project()->eclipseCases();
|
|
|
|
for (RimEclipseCase* c : eclipseCases)
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
2019-02-15 06:03:05 -06:00
|
|
|
if (c && c->caseId() == address.m_differenceCaseId && c->eclipseCaseData())
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
2019-03-25 01:36:33 -05:00
|
|
|
baseCase = c->eclipseCaseData();
|
2019-02-12 05:48:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
if (!baseCase || !sourceCase)
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
|
|
|
RiaLogging::error("Missing input case for difference calculator");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RigMainGrid* sourceMainGrid = sourceCase->mainGrid();
|
2019-03-25 01:36:33 -05:00
|
|
|
RigMainGrid* baseMainGrid = baseCase->mainGrid();
|
2019-02-12 05:48:18 -06:00
|
|
|
|
2019-03-25 01:36:33 -05:00
|
|
|
if (!RigGridManager::isMainGridDimensionsEqual(sourceMainGrid, baseMainGrid))
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
|
|
|
RiaLogging::error("Case difference : Grid cases do not match");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
RigCaseCellResultsData* baseCaseResults = baseCase->results(porosityModel);
|
2019-02-12 05:48:18 -06:00
|
|
|
RigCaseCellResultsData* sourceCaseResults = sourceCase->results(porosityModel);
|
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
if (!baseCaseResults || !sourceCaseResults)
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
|
|
|
RiaLogging::error("Missing result data for difference calculator");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RigEclipseResultAddress nativeAddress(address);
|
2019-04-03 04:46:26 -05:00
|
|
|
nativeAddress.m_differenceCaseId = RigEclipseResultAddress::noCaseDiffValue();
|
|
|
|
nativeAddress.m_timeLapseBaseFrameIdx = RigEclipseResultAddress::noTimeLapseValue();
|
2019-02-12 05:48:18 -06:00
|
|
|
if (!sourceCaseResults->ensureKnownResultLoaded(nativeAddress))
|
|
|
|
{
|
|
|
|
RiaLogging::error("Failed to load destination diff result");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
if (!baseCaseResults->ensureKnownResultLoaded(nativeAddress))
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
size_t baseFrameCount = baseCaseResults->cellScalarResults(nativeAddress).size();
|
2019-02-12 05:48:18 -06:00
|
|
|
size_t sourceFrameCount = sourceCaseResults->cellScalarResults(nativeAddress).size();
|
2019-02-15 05:43:25 -06:00
|
|
|
size_t maxFrameCount = std::min(baseFrameCount, sourceFrameCount);
|
2019-03-25 01:36:33 -05:00
|
|
|
size_t maxGridCount = std::min(baseMainGrid->gridCount(), sourceMainGrid->gridCount());
|
2019-02-12 05:48:18 -06:00
|
|
|
|
2019-03-25 01:36:33 -05:00
|
|
|
for (size_t gridIdx = 0; gridIdx < maxGridCount; ++gridIdx)
|
2019-02-12 05:48:18 -06:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
size_t baseFrameIdx = fIdx;
|
|
|
|
if (address.isTimeLapse())
|
|
|
|
{
|
|
|
|
baseFrameIdx = address.m_timeLapseBaseFrameIdx;
|
|
|
|
}
|
|
|
|
|
|
|
|
cvf::ref<RigResultAccessor> baseResultAccessor =
|
|
|
|
RigResultAccessorFactory::createFromResultAddress(baseCase, gridIdx, porosityModel, baseFrameIdx, nativeAddress);
|
|
|
|
|
2019-02-12 05:48:18 -06:00
|
|
|
for (size_t localGridCellIdx = 0; localGridCellIdx < grid->cellCount(); localGridCellIdx++)
|
|
|
|
{
|
|
|
|
size_t reservoirCellIndex = grid->reservoirCellIndex(localGridCellIdx);
|
|
|
|
if (activeCellInfo->isActive(reservoirCellIndex))
|
|
|
|
{
|
|
|
|
double sourceVal = sourceResultAccessor->cellScalar(localGridCellIdx);
|
2019-03-25 01:36:33 -05:00
|
|
|
double baseVal = baseResultAccessor->cellScalar(localGridCellIdx);
|
2019-02-12 05:48:18 -06:00
|
|
|
|
2019-02-15 05:43:25 -06:00
|
|
|
double difference = sourceVal - baseVal;
|
2019-02-12 05:48:18 -06:00
|
|
|
|
|
|
|
resultModifier->setCellScalar(localGridCellIdx, difference);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|