mirror of
https://github.com/OPM/ResInsight.git
synced 2024-12-28 18:01:08 -06:00
#2388 fractures. Support for asymmetric stim plan
This commit is contained in:
parent
1370cfe3e5
commit
7ddfaeb234
@ -28,17 +28,23 @@
|
||||
|
||||
#include <cmath> // Needed for HUGE_VAL on Linux
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal functions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool hasNegativeValues(std::vector<double> xs);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigStimPlanFractureDefinition> RifStimPlanXmlReader::readStimPlanXMLFile(const QString& stimPlanFileName,
|
||||
double conductivityScalingFactor,
|
||||
MirrorMode mirrorMode,
|
||||
QString * errorMessage)
|
||||
{
|
||||
RiaLogging::info(QString("Starting to open StimPlan XML file: '%1'").arg(stimPlanFileName));
|
||||
|
||||
cvf::ref<RigStimPlanFractureDefinition> stimPlanFileData = new RigStimPlanFractureDefinition;
|
||||
size_t startingNegXsValues = 0;
|
||||
{
|
||||
QFile dataFile(stimPlanFileName);
|
||||
if (!dataFile.open(QFile::ReadOnly))
|
||||
@ -50,7 +56,7 @@ cvf::ref<RigStimPlanFractureDefinition> RifStimPlanXmlReader::readStimPlanXMLFil
|
||||
QXmlStreamReader xmlStream;
|
||||
xmlStream.setDevice(&dataFile);
|
||||
xmlStream.readNext();
|
||||
startingNegXsValues = readStimplanGridAndTimesteps(xmlStream, stimPlanFileData.p());
|
||||
readStimplanGridAndTimesteps(xmlStream, stimPlanFileData.p(), mirrorMode);
|
||||
|
||||
RiaEclipseUnitTools::UnitSystemType unitSystem = stimPlanFileData->unitSet();
|
||||
|
||||
@ -69,9 +75,9 @@ cvf::ref<RigStimPlanFractureDefinition> RifStimPlanXmlReader::readStimPlanXMLFil
|
||||
}
|
||||
|
||||
|
||||
size_t numberOfDepthValues = stimPlanFileData->depthCount();
|
||||
RiaLogging::debug(QString("Grid size X: %1, Y: %2").arg(QString::number(stimPlanFileData->gridXCount()),
|
||||
QString::number(numberOfDepthValues)));
|
||||
size_t numberOfYValues = stimPlanFileData->yCount();
|
||||
RiaLogging::debug(QString("Grid size X: %1, Y: %2").arg(QString::number(stimPlanFileData->xCount()),
|
||||
QString::number(numberOfYValues)));
|
||||
|
||||
size_t numberOfTimeSteps = stimPlanFileData->timeSteps().size();
|
||||
RiaLogging::debug(QString("Number of time-steps: %1").arg(numberOfTimeSteps));
|
||||
@ -109,8 +115,9 @@ cvf::ref<RigStimPlanFractureDefinition> RifStimPlanXmlReader::readStimPlanXMLFil
|
||||
{
|
||||
double timeStepValue = getAttributeValueDouble(xmlStream2, "value");
|
||||
|
||||
std::vector<std::vector<double>> propertyValuesAtTimestep = getAllDepthDataAtTimeStep(xmlStream2, startingNegXsValues);
|
||||
|
||||
std::vector<std::vector<double>> propertyValuesAtTimestep =
|
||||
stimPlanFileData->generateDataLayoutFromFileDataLayout(getAllDepthDataAtTimeStep(xmlStream2));
|
||||
|
||||
bool valuesOK = stimPlanFileData->numberOfParameterValuesOK(propertyValuesAtTimestep);
|
||||
if (!valuesOK)
|
||||
{
|
||||
@ -153,17 +160,16 @@ cvf::ref<RigStimPlanFractureDefinition> RifStimPlanXmlReader::readStimPlanXMLFil
|
||||
RiaLogging::info(QString("Successfully read XML file: '%1'").arg(stimPlanFileName));
|
||||
}
|
||||
|
||||
|
||||
return stimPlanFileData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RifStimPlanXmlReader::readStimplanGridAndTimesteps(QXmlStreamReader &xmlStream, RigStimPlanFractureDefinition* stimPlanFileData)
|
||||
void RifStimPlanXmlReader::readStimplanGridAndTimesteps(QXmlStreamReader &xmlStream,
|
||||
RigStimPlanFractureDefinition* stimPlanFileData,
|
||||
MirrorMode mirrorMode)
|
||||
{
|
||||
|
||||
size_t startNegValuesXs = 0;
|
||||
size_t startNegValuesYs = 0;
|
||||
QString gridunit = "unknown";
|
||||
|
||||
@ -180,9 +186,9 @@ size_t RifStimPlanXmlReader::readStimplanGridAndTimesteps(QXmlStreamReader &xmlS
|
||||
{
|
||||
gridunit = getAttributeValueString(xmlStream, "uom");
|
||||
|
||||
if (gridunit == "m") stimPlanFileData->setUnitSet(RiaEclipseUnitTools::UNITS_METRIC);
|
||||
else if (gridunit == "ft") stimPlanFileData->setUnitSet(RiaEclipseUnitTools::UNITS_FIELD);
|
||||
else stimPlanFileData->setUnitSet(RiaEclipseUnitTools::UNITS_UNKNOWN);
|
||||
if (gridunit == "m") stimPlanFileData->m_unitSet = RiaEclipseUnitTools::UNITS_METRIC;
|
||||
else if (gridunit == "ft") stimPlanFileData->m_unitSet = RiaEclipseUnitTools::UNITS_FIELD;
|
||||
else stimPlanFileData->m_unitSet = RiaEclipseUnitTools::UNITS_UNKNOWN;
|
||||
|
||||
double tvdToTopPerfFt = getAttributeValueDouble(xmlStream, "TVDToTopPerfFt");
|
||||
double tvdToBottomPerfFt = getAttributeValueDouble(xmlStream, "TVDToBottomPerfFt");
|
||||
@ -193,18 +199,26 @@ size_t RifStimPlanXmlReader::readStimplanGridAndTimesteps(QXmlStreamReader &xmlS
|
||||
|
||||
if (xmlStream.name() == "xs")
|
||||
{
|
||||
size_t dummy;
|
||||
std::vector<double> gridValues;
|
||||
getGriddingValues(xmlStream, gridValues, startNegValuesXs);
|
||||
stimPlanFileData->setGridXs(gridValues);
|
||||
getGriddingValues(xmlStream, gridValues, dummy);
|
||||
stimPlanFileData->m_fileXs = gridValues;
|
||||
|
||||
stimPlanFileData->generateXsFromFileXs(mirrorMode == MIRROR_AUTO ? !hasNegativeValues(gridValues) : (bool)mirrorMode);
|
||||
}
|
||||
|
||||
else if (xmlStream.name() == "ys")
|
||||
{
|
||||
std::vector<double> gridValues;
|
||||
getGriddingValues(xmlStream, gridValues, startNegValuesYs);
|
||||
stimPlanFileData->setGridYs(gridValues);
|
||||
|
||||
stimPlanFileData->reorderYgridToDepths();
|
||||
// Reorder and change sign
|
||||
std::vector<double> ys;
|
||||
for (double y : gridValues)
|
||||
{
|
||||
ys.insert(ys.begin(), -y);
|
||||
}
|
||||
stimPlanFileData->m_Ys = ys;
|
||||
}
|
||||
|
||||
else if (xmlStream.name() == "time")
|
||||
@ -219,13 +233,12 @@ size_t RifStimPlanXmlReader::readStimplanGridAndTimesteps(QXmlStreamReader &xmlS
|
||||
{
|
||||
RiaLogging::error(QString("Negative depth values detected in XML file"));
|
||||
}
|
||||
return startNegValuesXs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::vector<double>> RifStimPlanXmlReader::getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream, size_t startingNegValuesXs)
|
||||
std::vector<std::vector<double>> RifStimPlanXmlReader::getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream)
|
||||
{
|
||||
std::vector<std::vector<double>> propertyValuesAtTimestep;
|
||||
|
||||
@ -245,14 +258,10 @@ std::vector<std::vector<double>> RifStimPlanXmlReader::getAllDepthDataAtTimeSte
|
||||
QString depthDataStr = xmlStream.text().toString();
|
||||
for (int i = 0; i < depthDataStr.split(' ').size(); i++)
|
||||
{
|
||||
if (i < static_cast<int>(startingNegValuesXs)) continue;
|
||||
else
|
||||
QString value = depthDataStr.split(' ')[i];
|
||||
if ( value != "")
|
||||
{
|
||||
QString value = depthDataStr.split(' ')[i];
|
||||
if ( value != "")
|
||||
{
|
||||
propertyValuesAtDepth.push_back(value.toDouble());
|
||||
}
|
||||
propertyValuesAtDepth.push_back(value.toDouble());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,11 +283,8 @@ void RifStimPlanXmlReader::getGriddingValues(QXmlStreamReader &xmlStream, std::v
|
||||
if (value.size() > 0)
|
||||
{
|
||||
double gridValue = value.toDouble();
|
||||
if (gridValue > -1e-5) //tolerance of 1e-5
|
||||
{
|
||||
gridValues.push_back(gridValue);
|
||||
}
|
||||
else startNegValues++;
|
||||
gridValues.push_back(gridValue);
|
||||
if(gridValue < -RigStimPlanFractureDefinition::THRESHOLD_VALUE) startNegValues++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,6 +321,10 @@ QString RifStimPlanXmlReader::getAttributeValueString(QXmlStreamReader &xmlStrea
|
||||
return parameterValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal function
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool hasNegativeValues(std::vector<double> xs)
|
||||
{
|
||||
return xs[0] < -RigStimPlanFractureDefinition::THRESHOLD_VALUE;
|
||||
}
|
||||
|
@ -33,16 +33,23 @@ class QXmlStreamReader;
|
||||
class RifStimPlanXmlReader
|
||||
{
|
||||
public:
|
||||
static cvf::ref<RigStimPlanFractureDefinition> readStimPlanXMLFile(const QString& stimPlanFileName, double conductivityScalingFactor, QString * errorMessage);
|
||||
enum MirrorMode { MIRROR_OFF = 0, MIRROR_ON = 1, MIRROR_AUTO = 2};
|
||||
|
||||
static cvf::ref<RigStimPlanFractureDefinition> readStimPlanXMLFile(const QString& stimPlanFileName,
|
||||
double conductivityScalingFactor,
|
||||
MirrorMode mirrorMode,
|
||||
QString * errorMessage);
|
||||
|
||||
private:
|
||||
static size_t readStimplanGridAndTimesteps(QXmlStreamReader &xmlStream, RigStimPlanFractureDefinition* stimPlanFileData);
|
||||
static void readStimplanGridAndTimesteps(QXmlStreamReader &xmlStream,
|
||||
RigStimPlanFractureDefinition* stimPlanFileData,
|
||||
MirrorMode mirrorMode);
|
||||
|
||||
static double getAttributeValueDouble(QXmlStreamReader &xmlStream, QString parameterName);
|
||||
static QString getAttributeValueString(QXmlStreamReader &xmlStream, QString parameterName);
|
||||
static void getGriddingValues(QXmlStreamReader &xmlStream, std::vector<double>& gridValues, size_t& startNegValues);
|
||||
|
||||
static std::vector<std::vector<double>> getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream, size_t startingNegValuesXs);
|
||||
static std::vector<std::vector<double>> getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream);
|
||||
|
||||
};
|
||||
|
||||
|
@ -229,23 +229,6 @@ void RivWellFracturePartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* mod
|
||||
appendFracturePerforationLengthParts(eclView, model);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RivWellFracturePartMgr::mirrorDataAtSingleDepth(std::vector<double> depthData)
|
||||
{
|
||||
std::vector<double> mirroredValuesAtGivenDepth;
|
||||
mirroredValuesAtGivenDepth.push_back(depthData[0]);
|
||||
for (size_t i = 1; i < (depthData.size()); i++) //starting at 1 since we don't want center value twice
|
||||
{
|
||||
double valueAtGivenX = depthData[i];
|
||||
mirroredValuesAtGivenDepth.insert(mirroredValuesAtGivenDepth.begin(), valueAtGivenX);
|
||||
mirroredValuesAtGivenDepth.push_back(valueAtGivenX);
|
||||
}
|
||||
|
||||
return mirroredValuesAtGivenDepth;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -443,7 +426,7 @@ cvf::ref<cvf::Part> RivWellFracturePartMgr::createStimPlanColorInterpolatedSurfa
|
||||
doubleCoord = displayCoordTransform->transformToDisplayCoord(doubleCoord);
|
||||
nodeCoord = cvf::Vec3f(doubleCoord);
|
||||
}
|
||||
|
||||
|
||||
RimLegendConfig* legendConfig = nullptr;
|
||||
if (activeView.fractureColors() && activeView.fractureColors()->isChecked())
|
||||
{
|
||||
@ -459,10 +442,9 @@ cvf::ref<cvf::Part> RivWellFracturePartMgr::createStimPlanColorInterpolatedSurfa
|
||||
{
|
||||
size_t idx = 0;
|
||||
const std::vector<std::vector<double> > dataToPlot = stimPlanFracTemplate->resultValues(activeView.fractureColors->uiResultName(), activeView.fractureColors->unit(), stimPlanFracTemplate->activeTimeStepIndex());
|
||||
for (const std::vector<double>& unmirroredDataAtDepth : dataToPlot)
|
||||
for (const std::vector<double>& dataAtY : dataToPlot)
|
||||
{
|
||||
const std::vector<double> mirroredValuesAtDepth = mirrorDataAtSingleDepth(unmirroredDataAtDepth);
|
||||
for (double val : mirroredValuesAtDepth)
|
||||
for (double val : dataAtY)
|
||||
{
|
||||
perNodeResultValues[idx++] = val;
|
||||
}
|
||||
|
@ -57,8 +57,6 @@ public:
|
||||
|
||||
void appendGeometryPartsToModel(cvf::ModelBasicList* model, const RimEclipseView& eclView);
|
||||
|
||||
static std::vector<double> mirrorDataAtSingleDepth(std::vector<double> depthData);
|
||||
|
||||
const QString resultInfoText(const RimEclipseView& activeView, cvf::Vec3d domainIntersectionPoint) const;
|
||||
|
||||
const RigFractureCell* getFractureCellAtDomainCoord(cvf::Vec3d domainCoord) const;
|
||||
|
@ -260,7 +260,10 @@ void RimStimPlanFractureTemplate::loadDataAndUpdate()
|
||||
|
||||
if (m_readError) return;
|
||||
|
||||
m_stimPlanFractureDefinitionData = RifStimPlanXmlReader::readStimPlanXMLFile( m_stimPlanFileName(), m_conductivityScalingFactor(), &errorMessage);
|
||||
m_stimPlanFractureDefinitionData = RifStimPlanXmlReader::readStimPlanXMLFile( m_stimPlanFileName(),
|
||||
m_conductivityScalingFactor(),
|
||||
RifStimPlanXmlReader::MIRROR_AUTO,
|
||||
&errorMessage);
|
||||
if (errorMessage.size() > 0) RiaLogging::error(errorMessage);
|
||||
|
||||
if (m_stimPlanFractureDefinitionData.notNull())
|
||||
@ -670,7 +673,7 @@ void RimStimPlanFractureTemplate::defineEditorAttribute(const caf::PdmFieldHandl
|
||||
|
||||
if (field == &m_wellPathDepthAtFracture)
|
||||
{
|
||||
if ( !m_stimPlanFractureDefinitionData.isNull() && (m_stimPlanFractureDefinitionData->depthCount() > 0) )
|
||||
if ( !m_stimPlanFractureDefinitionData.isNull() && (m_stimPlanFractureDefinitionData->yCount() > 0) )
|
||||
{
|
||||
caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast<caf::PdmUiDoubleSliderEditorAttribute*>(attribute);
|
||||
if ( myAttr )
|
||||
|
@ -30,14 +30,16 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal functions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t findMirrorXIndex(std::vector<double> xs);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigStimPlanResultFrames::RigStimPlanResultFrames()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const double RigStimPlanFractureDefinition::THRESHOLD_VALUE = 1e-5;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@ -116,23 +118,60 @@ void RigStimPlanFractureDefinition::setTvdToBottomPerf(double bottomPerfTvd, Ria
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RigStimPlanFractureDefinition::getNegAndPosXcoords() const
|
||||
void RigStimPlanFractureDefinition::generateXsFromFileXs(bool xMirrorMode)
|
||||
{
|
||||
std::vector<double> allXcoords;
|
||||
for ( const double& xCoord : m_gridXs )
|
||||
{
|
||||
if ( xCoord > 1e-5 )
|
||||
{
|
||||
double negXcoord = -xCoord;
|
||||
allXcoords.insert(allXcoords.begin(), negXcoord);
|
||||
}
|
||||
}
|
||||
for ( const double& xCoord : m_gridXs )
|
||||
{
|
||||
allXcoords.push_back(xCoord);
|
||||
}
|
||||
m_xMirrorMode = xMirrorMode;
|
||||
m_Xs.clear();
|
||||
|
||||
return allXcoords;
|
||||
if (m_xMirrorMode)
|
||||
{
|
||||
size_t mirrorIndex = findMirrorXIndex(m_fileXs);
|
||||
std::list<double> xs;
|
||||
|
||||
// Mirror positive X values
|
||||
xs.push_back(m_fileXs[mirrorIndex]);
|
||||
for (size_t i = mirrorIndex + 1; i < m_fileXs.size(); i++)
|
||||
{
|
||||
xs.push_front(-m_fileXs[i]);
|
||||
xs.push_back(m_fileXs[i]);
|
||||
}
|
||||
m_Xs = std::vector<double>(xs.begin(), xs.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Xs = m_fileXs;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::vector<double>> RigStimPlanFractureDefinition::generateDataLayoutFromFileDataLayout(std::vector<std::vector<double>> fileXYData)
|
||||
{
|
||||
if (m_xMirrorMode)
|
||||
{
|
||||
std::vector<std::vector<double>> xyData;
|
||||
size_t mirrorIndex = findMirrorXIndex(m_fileXs);
|
||||
|
||||
for (const auto& yData : fileXYData)
|
||||
{
|
||||
std::list<double> xValues;
|
||||
|
||||
// Mirror positive X values
|
||||
xValues.push_back(yData[mirrorIndex]);
|
||||
for (size_t x = mirrorIndex + 1; x < yData.size(); x++)
|
||||
{
|
||||
xValues.push_front(yData[x]);
|
||||
xValues.push_back(yData[x]);
|
||||
}
|
||||
xyData.push_back(std::vector<double>(xValues.begin(), xValues.end()));
|
||||
}
|
||||
return xyData;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fileXYData;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -140,13 +179,12 @@ std::vector<double> RigStimPlanFractureDefinition::getNegAndPosXcoords() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigStimPlanFractureDefinition::numberOfParameterValuesOK(std::vector<std::vector<double>> propertyValuesAtTimestep)
|
||||
{
|
||||
size_t depths = this->depths.size();
|
||||
size_t gridXvalues = this->m_gridXs.size();
|
||||
size_t xCount = m_Xs.size();
|
||||
|
||||
if ( propertyValuesAtTimestep.size() != depths ) return false;
|
||||
if ( propertyValuesAtTimestep.size() != yCount()) return false;
|
||||
for ( std::vector<double> valuesAtDepthVector : propertyValuesAtTimestep )
|
||||
{
|
||||
if ( valuesAtDepthVector.size() != gridXvalues ) return false;
|
||||
if ( valuesAtDepthVector.size() != xCount ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -155,17 +193,16 @@ bool RigStimPlanFractureDefinition::numberOfParameterValuesOK(std::vector<std::v
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RigStimPlanFractureDefinition::adjustedDepthCoordsAroundWellPathPosition(double wellPathDepthAtFracture) const
|
||||
std::vector<double> RigStimPlanFractureDefinition::adjustedYCoordsAroundWellPathPosition(double wellPathIntersectionAtFractureDepth) const
|
||||
{
|
||||
std::vector<double> depthRelativeToWellPath;
|
||||
std::vector<double> yRelativeToWellPath;
|
||||
|
||||
for ( const double& depth : this->depths )
|
||||
for ( const double& y : m_Ys )
|
||||
{
|
||||
double adjustedDepth = depth - wellPathDepthAtFracture;
|
||||
adjustedDepth = -adjustedDepth;
|
||||
depthRelativeToWellPath.push_back(adjustedDepth);
|
||||
double adjustedDepth = y + wellPathIntersectionAtFractureDepth;
|
||||
yRelativeToWellPath.push_back(adjustedDepth);
|
||||
}
|
||||
return depthRelativeToWellPath;
|
||||
return yRelativeToWellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -183,32 +220,13 @@ std::vector<std::pair<QString, QString> > RigStimPlanFractureDefinition::getStim
|
||||
return propertyNamesUnits;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::vector<double>> RigStimPlanFractureDefinition::getMirroredDataAtTimeIndex(const QString& resultName,
|
||||
const QString& unitName,
|
||||
size_t timeStepIndex) const
|
||||
{
|
||||
std::vector<std::vector<double>> notMirrordedData = this->getDataAtTimeIndex(resultName, unitName, timeStepIndex);
|
||||
std::vector<std::vector<double>> mirroredData;
|
||||
|
||||
for ( std::vector<double> depthData : notMirrordedData )
|
||||
{
|
||||
std::vector<double> mirrordDepthData = RivWellFracturePartMgr::mirrorDataAtSingleDepth(depthData);
|
||||
mirroredData.push_back(mirrordDepthData);
|
||||
}
|
||||
|
||||
return mirroredData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::ref<RigFractureGrid> RigStimPlanFractureDefinition::createFractureGrid(const QString& resultName,
|
||||
int m_activeTimeStepIndex,
|
||||
int activeTimeStepIndex,
|
||||
RiaEclipseUnitTools::UnitSystemType fractureTemplateUnit,
|
||||
double m_wellPathDepthAtFracture)
|
||||
double wellPathIntersectionAtFractureDepth)
|
||||
{
|
||||
std::vector<RigFractureCell> stimPlanCells;
|
||||
std::pair<size_t, size_t> wellCenterStimPlanCellIJ = std::make_pair(0, 0);
|
||||
@ -217,17 +235,17 @@ cvf::ref<RigFractureGrid> RigStimPlanFractureDefinition::createFractureGrid(cons
|
||||
|
||||
QString condUnit = RiaDefines::unitStringConductivity(fractureTemplateUnit);
|
||||
|
||||
std::vector<std::vector<double>> conductivityValuesAtTimeStep = this->getMirroredDataAtTimeIndex(resultName,
|
||||
condUnit,
|
||||
m_activeTimeStepIndex);
|
||||
std::vector<std::vector<double>> conductivityValuesAtTimeStep = this->getDataAtTimeIndex(resultName,
|
||||
condUnit,
|
||||
activeTimeStepIndex);
|
||||
|
||||
std::vector<double> depthCoordsAtNodes = this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture);
|
||||
std::vector<double> xCoordsAtNodes = this->getNegAndPosXcoords();
|
||||
std::vector<double> yCoordsAtNodes = this->adjustedYCoordsAroundWellPathPosition(wellPathIntersectionAtFractureDepth);
|
||||
std::vector<double> xCoordsAtNodes = this->m_Xs;
|
||||
|
||||
std::vector<double> xCoords;
|
||||
for ( int i = 0; i < static_cast<int>(xCoordsAtNodes.size()) - 1; i++ ) xCoords.push_back((xCoordsAtNodes[i] + xCoordsAtNodes[i + 1]) / 2);
|
||||
std::vector<double> depthCoords;
|
||||
for ( int i = 0; i < static_cast<int>(depthCoordsAtNodes.size()) - 1; i++ ) depthCoords.push_back((depthCoordsAtNodes[i] + depthCoordsAtNodes[i + 1]) / 2);
|
||||
for ( int i = 0; i < static_cast<int>(yCoordsAtNodes.size()) - 1; i++ ) depthCoords.push_back((yCoordsAtNodes[i] + yCoordsAtNodes[i + 1]) / 2);
|
||||
|
||||
for ( int i = 0; i < static_cast<int>(xCoords.size()) - 1; i++ )
|
||||
{
|
||||
@ -276,8 +294,8 @@ cvf::ref<RigFractureGrid> RigStimPlanFractureDefinition::createFractureGrid(cons
|
||||
cvf::ref<RigFractureGrid> m_fractureGrid = new RigFractureGrid;
|
||||
m_fractureGrid->setFractureCells(stimPlanCells);
|
||||
m_fractureGrid->setWellCenterFractureCellIJ(wellCenterStimPlanCellIJ);
|
||||
m_fractureGrid->setICellCount(this->getNegAndPosXcoords().size() - 2);
|
||||
m_fractureGrid->setJCellCount(this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture).size() - 2);
|
||||
m_fractureGrid->setICellCount(this->m_Xs.size() - 2);
|
||||
m_fractureGrid->setJCellCount(this->adjustedYCoordsAroundWellPathPosition(wellPathIntersectionAtFractureDepth).size() - 2);
|
||||
|
||||
return m_fractureGrid;
|
||||
}
|
||||
@ -290,13 +308,13 @@ std::vector<double> RigStimPlanFractureDefinition::fractureGridResults(const QSt
|
||||
size_t timeStepIndex) const
|
||||
{
|
||||
std::vector<double> fractureGridResults;
|
||||
std::vector<std::vector<double>> resultValuesAtTimeStep = this->getMirroredDataAtTimeIndex(resultName,
|
||||
unitName,
|
||||
timeStepIndex);
|
||||
const std::vector<std::vector<double>>& resultValuesAtTimeStep = this->getDataAtTimeIndex(resultName,
|
||||
unitName,
|
||||
timeStepIndex);
|
||||
|
||||
for ( int i = 0; i < static_cast<int>(mirroredGridXCount()) - 2; i++ )
|
||||
for ( int i = 0; i < static_cast<int>(xCount()) - 2; i++ )
|
||||
{
|
||||
for ( int j = 0; j < static_cast<int>(depthCount()) - 2; j++ )
|
||||
for ( int j = 0; j < static_cast<int>(yCount()) - 2; j++ )
|
||||
{
|
||||
if ( j+1 < static_cast<int>(resultValuesAtTimeStep.size()) && i+1 < static_cast<int>(resultValuesAtTimeStep[j + 1].size()) )
|
||||
{
|
||||
@ -315,16 +333,16 @@ std::vector<double> RigStimPlanFractureDefinition::fractureGridResults(const QSt
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigStimPlanFractureDefinition::createFractureTriangleGeometry(double m_wellPathDepthAtFracture,
|
||||
void RigStimPlanFractureDefinition::createFractureTriangleGeometry(double wellPathIntersectionAtFractureDepth,
|
||||
RiaEclipseUnitTools::UnitSystem neededUnit,
|
||||
const QString& fractureUserName,
|
||||
std::vector<cvf::Vec3f>* vertices,
|
||||
std::vector<cvf::uint>* triangleIndices)
|
||||
{
|
||||
std::vector<double> xCoords = this->getNegAndPosXcoords();
|
||||
std::vector<double> xCoords = this->m_Xs;
|
||||
cvf::uint lenXcoords = static_cast<cvf::uint>(xCoords.size());
|
||||
|
||||
std::vector<double> adjustedDepths = this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture);
|
||||
std::vector<double> adjustedYs = this->adjustedYCoordsAroundWellPathPosition(wellPathIntersectionAtFractureDepth);
|
||||
|
||||
if ( neededUnit == m_unitSet )
|
||||
{
|
||||
@ -334,13 +352,13 @@ void RigStimPlanFractureDefinition::createFractureTriangleGeometry(double m_well
|
||||
else if ( m_unitSet == RiaEclipseUnitTools::UNITS_METRIC && neededUnit == RiaEclipseUnitTools::UNITS_FIELD )
|
||||
{
|
||||
RiaLogging::info(QString("Converting StimPlan geometry from metric to field for fracture template %1").arg(fractureUserName));
|
||||
for ( double& value : adjustedDepths ) value = RiaEclipseUnitTools::meterToFeet(value);
|
||||
for ( double& value : adjustedYs ) value = RiaEclipseUnitTools::meterToFeet(value);
|
||||
for ( double& value : xCoords ) value = RiaEclipseUnitTools::meterToFeet(value);
|
||||
}
|
||||
else if ( m_unitSet == RiaEclipseUnitTools::UNITS_FIELD && neededUnit == RiaEclipseUnitTools::UNITS_METRIC )
|
||||
{
|
||||
RiaLogging::info(QString("Converting StimPlan geometry from field to metric for fracture template %1").arg(fractureUserName));
|
||||
for ( double& value : adjustedDepths ) value = RiaEclipseUnitTools::feetToMeter(value);
|
||||
for ( double& value : adjustedYs ) value = RiaEclipseUnitTools::feetToMeter(value);
|
||||
for ( double& value : xCoords ) value = RiaEclipseUnitTools::feetToMeter(value);
|
||||
}
|
||||
else
|
||||
@ -350,16 +368,16 @@ void RigStimPlanFractureDefinition::createFractureTriangleGeometry(double m_well
|
||||
return;
|
||||
}
|
||||
|
||||
for ( cvf::uint k = 0; k < adjustedDepths.size(); k++ )
|
||||
for ( cvf::uint k = 0; k < adjustedYs.size(); k++ )
|
||||
{
|
||||
for ( cvf::uint i = 0; i < lenXcoords; i++ )
|
||||
{
|
||||
cvf::Vec3f node = cvf::Vec3f(xCoords[i], adjustedDepths[k], 0);
|
||||
cvf::Vec3f node = cvf::Vec3f(xCoords[i], adjustedYs[k], 0);
|
||||
vertices->push_back(node);
|
||||
|
||||
if ( i < lenXcoords - 1 && k < adjustedDepths.size() - 1 )
|
||||
if ( i < lenXcoords - 1 && k < adjustedYs.size() - 1 )
|
||||
{
|
||||
if ( xCoords[i] < 1e-5 )
|
||||
if ( xCoords[i] < THRESHOLD_VALUE )
|
||||
{
|
||||
//Upper triangle
|
||||
triangleIndices->push_back(i + k*lenXcoords);
|
||||
@ -423,16 +441,16 @@ void sortPolygon(std::vector<cvf::Vec3f> &polygon)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<cvf::Vec3f> RigStimPlanFractureDefinition::createFractureBorderPolygon(const QString& resultName,
|
||||
const QString& resultUnit,
|
||||
int m_activeTimeStepIndex,
|
||||
double m_wellPathDepthAtFracture,
|
||||
int activeTimeStepIndex,
|
||||
double wellPathIntersectionAtFractureDepth,
|
||||
RiaEclipseUnitTools::UnitSystem neededUnit,
|
||||
const QString& fractureUserName)
|
||||
{
|
||||
std::vector<cvf::Vec3f> polygon;
|
||||
|
||||
std::vector<std::vector<double>> dataAtTimeStep = this->getDataAtTimeIndex(resultName, resultUnit, m_activeTimeStepIndex);
|
||||
std::vector<std::vector<double>> dataAtTimeStep = this->getDataAtTimeIndex(resultName, resultUnit, activeTimeStepIndex);
|
||||
|
||||
std::vector<double> adjustedDepths = this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture);
|
||||
std::vector<double> adjustedYs = this->adjustedYCoordsAroundWellPathPosition(wellPathIntersectionAtFractureDepth);
|
||||
|
||||
for ( int k = 0; k < static_cast<int>(dataAtTimeStep.size()); k++ )
|
||||
{
|
||||
@ -442,18 +460,18 @@ std::vector<cvf::Vec3f> RigStimPlanFractureDefinition::createFractureBorderPolyg
|
||||
{
|
||||
if ( (i > 0) && ((dataAtTimeStep[k])[(i - 1)] > 1e-7) ) //side neighbour cell different from 0
|
||||
{
|
||||
polygon.push_back(cvf::Vec3f(static_cast<float>(this->m_gridXs[i]),
|
||||
static_cast<float>(adjustedDepths[k]), 0.0f));
|
||||
polygon.push_back(cvf::Vec3f(static_cast<float>(this->m_Xs[i]),
|
||||
static_cast<float>(adjustedYs[k]), 0.0f));
|
||||
}
|
||||
else if ( (k < static_cast<int>(dataAtTimeStep.size()) - 1) && ((dataAtTimeStep[k + 1])[(i)] > 1e-7) )//cell below different from 0
|
||||
{
|
||||
polygon.push_back(cvf::Vec3f(static_cast<float>(this->m_gridXs[i]),
|
||||
static_cast<float>(adjustedDepths[k]), 0.0f));
|
||||
polygon.push_back(cvf::Vec3f(static_cast<float>(this->m_Xs[i]),
|
||||
static_cast<float>(adjustedYs[k]), 0.0f));
|
||||
}
|
||||
else if ( (k > 0) && ((dataAtTimeStep[k - 1])[(i)] > 1e-7) )//cell above different from 0
|
||||
{
|
||||
polygon.push_back(cvf::Vec3f(static_cast<float>(this->m_gridXs[i]),
|
||||
static_cast<float>(adjustedDepths[k]), 0.0f));
|
||||
polygon.push_back(cvf::Vec3f(static_cast<float>(this->m_Xs[i]),
|
||||
static_cast<float>(adjustedYs[k]), 0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -518,28 +536,15 @@ std::vector<cvf::Vec3f> RigStimPlanFractureDefinition::createFractureBorderPolyg
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RigStimPlanFractureDefinition::timeStepExisist(double timeStepValueToCheck)
|
||||
bool RigStimPlanFractureDefinition::timeStepExists(double timeStepValueToCheck)
|
||||
{
|
||||
for (double timeStep : m_timeSteps)
|
||||
{
|
||||
if (fabs(timeStepValueToCheck - timeStep) < 1e-5) return true;
|
||||
if (fabs(timeStepValueToCheck - timeStep) < THRESHOLD_VALUE) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RigStimPlanFractureDefinition::reorderYgridToDepths()
|
||||
{
|
||||
std::vector<double> depthsInIncreasingOrder;
|
||||
for (double gridYvalue : m_gridYs)
|
||||
{
|
||||
depthsInIncreasingOrder.insert(depthsInIncreasingOrder.begin(), gridYvalue);
|
||||
}
|
||||
depths = depthsInIncreasingOrder;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -667,3 +672,21 @@ QStringList RigStimPlanFractureDefinition::conductivityResultNames() const
|
||||
return resultNames;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t findMirrorXIndex(std::vector<double> xs)
|
||||
{
|
||||
size_t mirrorIndex = cvf::UNDEFINED_SIZE_T;
|
||||
|
||||
for (size_t i = 0; i < xs.size(); i++)
|
||||
{
|
||||
if (xs[i] > -RigStimPlanFractureDefinition::THRESHOLD_VALUE)
|
||||
{
|
||||
mirrorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mirrorIndex;
|
||||
}
|
||||
|
@ -33,55 +33,58 @@ class PosNegAccumulator;
|
||||
class RigStimPlanResultFrames
|
||||
{
|
||||
public:
|
||||
RigStimPlanResultFrames();
|
||||
RigStimPlanResultFrames() {}
|
||||
|
||||
QString resultName;
|
||||
QString unit;
|
||||
|
||||
// Vector for each time step, for each depth and for each x-value
|
||||
// Vector for each time step, for each y and for each x-value
|
||||
std::vector< std::vector< std::vector<double> > > parameterValues;
|
||||
|
||||
};
|
||||
|
||||
class RigStimPlanFractureDefinition: public cvf::Object
|
||||
{
|
||||
friend class RifStimPlanXmlReader;
|
||||
|
||||
public:
|
||||
static const double THRESHOLD_VALUE;
|
||||
|
||||
RigStimPlanFractureDefinition();
|
||||
~RigStimPlanFractureDefinition();
|
||||
|
||||
RiaEclipseUnitTools::UnitSystem unitSet() const { return m_unitSet; }
|
||||
void setUnitSet(RiaEclipseUnitTools::UnitSystem unitset) { m_unitSet = unitset;}
|
||||
size_t xCount() const { return m_Xs.size(); }
|
||||
size_t yCount() const { return m_Ys.size(); }
|
||||
double minY() const { return m_Ys[0]; }
|
||||
double maxY() const { return m_Ys.back(); }
|
||||
|
||||
size_t gridXCount() const { return m_gridXs.size();}
|
||||
void setGridXs(const std::vector<double>& gridXs) { m_gridXs = gridXs; }
|
||||
|
||||
|
||||
//TODO: Consider removing gridYs or depths,
|
||||
//In example file these are the same, but can there be examples where not all gridY values are included in depths?
|
||||
|
||||
void setGridYs(const std::vector<double>& gridYs) { m_gridYs = gridYs; }
|
||||
|
||||
double minDepth() const { return depths[0]; }
|
||||
double maxDepth() const { return depths.back(); }
|
||||
size_t depthCount() const { return depths.size(); }
|
||||
double minDepth() const { return -minY(); }
|
||||
double maxDepth() const { return -maxY(); }
|
||||
|
||||
double topPerfTvd() const { return m_topPerfTvd; }
|
||||
double bottomPerfTvd() const { return m_bottomPerfTvd; }
|
||||
void setTvdToTopPerf(double topPerfTvd, RiaDefines::DepthUnitType unit);
|
||||
void setTvdToBottomPerf(double bottomPerfTvd, RiaDefines::DepthUnitType unit);
|
||||
|
||||
// Grid Geometry
|
||||
void enableXMirrorMode(bool enable) { m_xMirrorMode = enable; }
|
||||
bool xMirrorModeEnabled() const { return m_xMirrorMode; }
|
||||
|
||||
private:
|
||||
void generateXsFromFileXs(bool xMirrorMode);
|
||||
std::vector<std::vector<double>> generateDataLayoutFromFileDataLayout(std::vector<std::vector<double>> rawXYData);
|
||||
|
||||
|
||||
std::vector<double> adjustedYCoordsAroundWellPathPosition(double wellPathIntersectionAtFractureDepth) const;
|
||||
public:
|
||||
|
||||
std::vector<double> getNegAndPosXcoords() const;
|
||||
std::vector<double> adjustedDepthCoordsAroundWellPathPosition(double wellPathDepthAtFracture) const;
|
||||
|
||||
cvf::ref<RigFractureGrid> createFractureGrid(const QString& resultName,
|
||||
int m_activeTimeStepIndex,
|
||||
int activeTimeStepIndex,
|
||||
RiaEclipseUnitTools::UnitSystemType fractureTemplateUnit,
|
||||
double m_wellPathDepthAtFracture);
|
||||
double wellPathIntersectionAtFractureDepth);
|
||||
|
||||
|
||||
void createFractureTriangleGeometry(double m_wellPathDepthAtFracture,
|
||||
void createFractureTriangleGeometry(double wellPathIntersectionAtFractureDepth,
|
||||
RiaEclipseUnitTools::UnitSystem neededUnit,
|
||||
const QString& fractureUserName,
|
||||
std::vector<cvf::Vec3f>* vertices,
|
||||
@ -89,17 +92,19 @@ public:
|
||||
|
||||
std::vector<cvf::Vec3f> createFractureBorderPolygon(const QString& resultName,
|
||||
const QString& resultUnit,
|
||||
int m_activeTimeStepIndex,
|
||||
double m_wellPathDepthAtFracture,
|
||||
int activeTimeStepIndex,
|
||||
double wellPathIntersectionAtFractureDepth,
|
||||
RiaEclipseUnitTools::UnitSystem neededUnit,
|
||||
const QString& fractureUserName);
|
||||
// Result Access
|
||||
|
||||
const std::vector<double>& timeSteps() const { return m_timeSteps; }
|
||||
void addTimeStep(double time) { if (!timeStepExisist(time)) m_timeSteps.push_back(time); }
|
||||
void addTimeStep(double time) { if (!timeStepExists(time)) m_timeSteps.push_back(time); }
|
||||
|
||||
std::vector<std::pair<QString, QString> > getStimPlanPropertyNamesUnits() const;
|
||||
private:
|
||||
bool numberOfParameterValuesOK(std::vector<std::vector<double>> propertyValuesAtTimestep);
|
||||
public:
|
||||
size_t totalNumberTimeSteps();
|
||||
void setDataAtTimeValue(QString resultName, QString unit, std::vector<std::vector<double>> data, double timeStepValue);
|
||||
const std::vector<std::vector<double>>& getDataAtTimeIndex(const QString& resultName, const QString& unit, size_t timeStepIndex) const;
|
||||
@ -107,37 +112,29 @@ public:
|
||||
const QString& unitName,
|
||||
size_t timeStepIndex) const;
|
||||
|
||||
void appendDataToResultStatistics(const QString& resultName, const QString& unit,
|
||||
MinMaxAccumulator& minMaxAccumulator,
|
||||
PosNegAccumulator& posNegAccumulator) const;
|
||||
void appendDataToResultStatistics(const QString& resultName, const QString& unit,
|
||||
MinMaxAccumulator& minMaxAccumulator,
|
||||
PosNegAccumulator& posNegAccumulator) const;
|
||||
|
||||
QStringList conductivityResultNames() const;
|
||||
|
||||
// Setup
|
||||
void reorderYgridToDepths();
|
||||
|
||||
private:
|
||||
bool timeStepExisist(double timeStepValue);
|
||||
bool timeStepExists(double timeStepValue);
|
||||
size_t getTimeStepIndex(double timeStepValue);
|
||||
size_t resultIndex(const QString& resultName, const QString& unit) const;
|
||||
size_t mirroredGridXCount() const { return m_gridXs.size() ? m_gridXs.size() + m_gridXs.size() - 1 : 0 ;}
|
||||
|
||||
std::vector<std::vector<double>> getMirroredDataAtTimeIndex(const QString& resultName,
|
||||
const QString& unitName,
|
||||
size_t timeStepIndex) const;
|
||||
|
||||
|
||||
private:
|
||||
RiaEclipseUnitTools::UnitSystem m_unitSet;
|
||||
std::vector<double> m_gridXs;
|
||||
std::vector<double> m_gridYs;
|
||||
std::vector<double> depths;
|
||||
// Data read from file
|
||||
RiaEclipseUnitTools::UnitSystem m_unitSet;
|
||||
std::vector<double> m_fileXs;
|
||||
std::vector<double> m_Ys;
|
||||
std::vector<double> m_timeSteps;
|
||||
|
||||
double m_topPerfTvd;
|
||||
double m_bottomPerfTvd;
|
||||
// Modified file data
|
||||
std::vector<RigStimPlanResultFrames> m_stimPlanResults;
|
||||
std::vector<double> m_Xs;
|
||||
bool m_xMirrorMode;
|
||||
|
||||
std::vector<double> m_timeSteps;
|
||||
std::vector<RigStimPlanResultFrames> m_stimPlanResults;
|
||||
double m_topPerfTvd;
|
||||
double m_bottomPerfTvd;
|
||||
};
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
Title Classes related to fractures
|
||||
|
||||
note as N1
|
||||
Updated 2017-06-09
|
||||
Updated 2018-02-07
|
||||
end note
|
||||
|
||||
class RimFracture {
|
||||
@ -29,6 +29,9 @@ class RimEllipseFractureTemplate {
|
||||
class RimStimPlanFractureTemplate {
|
||||
}
|
||||
|
||||
class RifStimPlanXmlReader {
|
||||
<<static>> readStimPlanXMLFile()
|
||||
}
|
||||
|
||||
RimFractureTemplate <|-- RimEllipseFractureTemplate
|
||||
RimFractureTemplate <|-- RimStimPlanFractureTemplate
|
||||
@ -80,9 +83,7 @@ class RicExportFractureCompletionsImpl{
|
||||
generateFracturesCompdatValues()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RimStimPlanFractureTemplate ---> RifStimPlanXmlReader
|
||||
RifStimPlanXmlReader ...> "create" RigStimPlanFractureDefinition
|
||||
|
||||
@enduml
|
||||
|
Loading…
Reference in New Issue
Block a user