From 7ddfaeb2347fc1d233e9c1af11c5800c13ca0ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Jensen?= Date: Thu, 8 Feb 2018 11:05:01 +0100 Subject: [PATCH] #2388 fractures. Support for asymmetric stim plan --- .../FileInterface/RifStimPlanXmlReader.cpp | 80 ++++--- .../FileInterface/RifStimPlanXmlReader.h | 13 +- .../RivWellFracturePartMgr.cpp | 24 +- .../RivWellFracturePartMgr.h | 2 - .../RimStimPlanFractureTemplate.cpp | 7 +- .../RigStimPlanFractureDefinition.cpp | 221 ++++++++++-------- .../RigStimPlanFractureDefinition.h | 93 ++++---- doc/fracture_clases.plantuml | 11 +- 8 files changed, 236 insertions(+), 215 deletions(-) diff --git a/ApplicationCode/FileInterface/RifStimPlanXmlReader.cpp b/ApplicationCode/FileInterface/RifStimPlanXmlReader.cpp index 095c214e77..c3deeeec33 100644 --- a/ApplicationCode/FileInterface/RifStimPlanXmlReader.cpp +++ b/ApplicationCode/FileInterface/RifStimPlanXmlReader.cpp @@ -28,17 +28,23 @@ #include // Needed for HUGE_VAL on Linux + +//-------------------------------------------------------------------------------------------------- +/// Internal functions +//-------------------------------------------------------------------------------------------------- +bool hasNegativeValues(std::vector xs); + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref 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 stimPlanFileData = new RigStimPlanFractureDefinition; - size_t startingNegXsValues = 0; { QFile dataFile(stimPlanFileName); if (!dataFile.open(QFile::ReadOnly)) @@ -50,7 +56,7 @@ cvf::ref 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 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 RifStimPlanXmlReader::readStimPlanXMLFil { double timeStepValue = getAttributeValueDouble(xmlStream2, "value"); - std::vector> propertyValuesAtTimestep = getAllDepthDataAtTimeStep(xmlStream2, startingNegXsValues); - + std::vector> propertyValuesAtTimestep = + stimPlanFileData->generateDataLayoutFromFileDataLayout(getAllDepthDataAtTimeStep(xmlStream2)); + bool valuesOK = stimPlanFileData->numberOfParameterValuesOK(propertyValuesAtTimestep); if (!valuesOK) { @@ -153,17 +160,16 @@ cvf::ref 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 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 gridValues; getGriddingValues(xmlStream, gridValues, startNegValuesYs); - stimPlanFileData->setGridYs(gridValues); - stimPlanFileData->reorderYgridToDepths(); + // Reorder and change sign + std::vector 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> RifStimPlanXmlReader::getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream, size_t startingNegValuesXs) +std::vector> RifStimPlanXmlReader::getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream) { std::vector> propertyValuesAtTimestep; @@ -245,14 +258,10 @@ std::vector> RifStimPlanXmlReader::getAllDepthDataAtTimeSte QString depthDataStr = xmlStream.text().toString(); for (int i = 0; i < depthDataStr.split(' ').size(); i++) { - if (i < static_cast(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 xs) +{ + return xs[0] < -RigStimPlanFractureDefinition::THRESHOLD_VALUE; +} diff --git a/ApplicationCode/FileInterface/RifStimPlanXmlReader.h b/ApplicationCode/FileInterface/RifStimPlanXmlReader.h index 95070a8c7b..7521323f1a 100644 --- a/ApplicationCode/FileInterface/RifStimPlanXmlReader.h +++ b/ApplicationCode/FileInterface/RifStimPlanXmlReader.h @@ -33,16 +33,23 @@ class QXmlStreamReader; class RifStimPlanXmlReader { public: - static cvf::ref readStimPlanXMLFile(const QString& stimPlanFileName, double conductivityScalingFactor, QString * errorMessage); + enum MirrorMode { MIRROR_OFF = 0, MIRROR_ON = 1, MIRROR_AUTO = 2}; + + static cvf::ref 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& gridValues, size_t& startNegValues); - static std::vector> getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream, size_t startingNegValuesXs); + static std::vector> getAllDepthDataAtTimeStep(QXmlStreamReader &xmlStream); }; diff --git a/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.cpp b/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.cpp index 261f8b8f51..419af4ac66 100644 --- a/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.cpp +++ b/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.cpp @@ -229,23 +229,6 @@ void RivWellFracturePartMgr::appendGeometryPartsToModel(cvf::ModelBasicList* mod appendFracturePerforationLengthParts(eclView, model); } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RivWellFracturePartMgr::mirrorDataAtSingleDepth(std::vector depthData) -{ - std::vector 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 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 RivWellFracturePartMgr::createStimPlanColorInterpolatedSurfa { size_t idx = 0; const std::vector > dataToPlot = stimPlanFracTemplate->resultValues(activeView.fractureColors->uiResultName(), activeView.fractureColors->unit(), stimPlanFracTemplate->activeTimeStepIndex()); - for (const std::vector& unmirroredDataAtDepth : dataToPlot) + for (const std::vector& dataAtY : dataToPlot) { - const std::vector mirroredValuesAtDepth = mirrorDataAtSingleDepth(unmirroredDataAtDepth); - for (double val : mirroredValuesAtDepth) + for (double val : dataAtY) { perNodeResultValues[idx++] = val; } diff --git a/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.h b/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.h index 955a1b220a..614344f226 100644 --- a/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.h +++ b/ApplicationCode/ModelVisualization/RivWellFracturePartMgr.h @@ -57,8 +57,6 @@ public: void appendGeometryPartsToModel(cvf::ModelBasicList* model, const RimEclipseView& eclView); - static std::vector mirrorDataAtSingleDepth(std::vector depthData); - const QString resultInfoText(const RimEclipseView& activeView, cvf::Vec3d domainIntersectionPoint) const; const RigFractureCell* getFractureCellAtDomainCoord(cvf::Vec3d domainCoord) const; diff --git a/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp b/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp index 68ab5b19d1..a49beec6e2 100644 --- a/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp +++ b/ApplicationCode/ProjectDataModel/Completions/RimStimPlanFractureTemplate.cpp @@ -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(attribute); if ( myAttr ) diff --git a/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.cpp b/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.cpp index 1df1b09e1d..d0f3e6bbf2 100644 --- a/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.cpp +++ b/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.cpp @@ -30,14 +30,16 @@ #include + +//-------------------------------------------------------------------------------------------------- +/// Internal functions +//-------------------------------------------------------------------------------------------------- +size_t findMirrorXIndex(std::vector xs); + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RigStimPlanResultFrames::RigStimPlanResultFrames() -{ - -} - +const double RigStimPlanFractureDefinition::THRESHOLD_VALUE = 1e-5; //-------------------------------------------------------------------------------------------------- /// @@ -116,23 +118,60 @@ void RigStimPlanFractureDefinition::setTvdToBottomPerf(double bottomPerfTvd, Ria //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RigStimPlanFractureDefinition::getNegAndPosXcoords() const +void RigStimPlanFractureDefinition::generateXsFromFileXs(bool xMirrorMode) { - std::vector 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 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(xs.begin(), xs.end()); + } + else + { + m_Xs = m_fileXs; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RigStimPlanFractureDefinition::generateDataLayoutFromFileDataLayout(std::vector> fileXYData) +{ + if (m_xMirrorMode) + { + std::vector> xyData; + size_t mirrorIndex = findMirrorXIndex(m_fileXs); + + for (const auto& yData : fileXYData) + { + std::list 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(xValues.begin(), xValues.end())); + } + return xyData; + } + else + { + return fileXYData; + } } //-------------------------------------------------------------------------------------------------- @@ -140,13 +179,12 @@ std::vector RigStimPlanFractureDefinition::getNegAndPosXcoords() const //-------------------------------------------------------------------------------------------------- bool RigStimPlanFractureDefinition::numberOfParameterValuesOK(std::vector> 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 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 RigStimPlanFractureDefinition::adjustedDepthCoordsAroundWellPathPosition(double wellPathDepthAtFracture) const +std::vector RigStimPlanFractureDefinition::adjustedYCoordsAroundWellPathPosition(double wellPathIntersectionAtFractureDepth) const { - std::vector depthRelativeToWellPath; + std::vector 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 > RigStimPlanFractureDefinition::getStim return propertyNamesUnits; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector> RigStimPlanFractureDefinition::getMirroredDataAtTimeIndex(const QString& resultName, - const QString& unitName, - size_t timeStepIndex) const -{ - std::vector> notMirrordedData = this->getDataAtTimeIndex(resultName, unitName, timeStepIndex); - std::vector> mirroredData; - - for ( std::vector depthData : notMirrordedData ) - { - std::vector mirrordDepthData = RivWellFracturePartMgr::mirrorDataAtSingleDepth(depthData); - mirroredData.push_back(mirrordDepthData); - } - - return mirroredData; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RigStimPlanFractureDefinition::createFractureGrid(const QString& resultName, - int m_activeTimeStepIndex, + int activeTimeStepIndex, RiaEclipseUnitTools::UnitSystemType fractureTemplateUnit, - double m_wellPathDepthAtFracture) + double wellPathIntersectionAtFractureDepth) { std::vector stimPlanCells; std::pair wellCenterStimPlanCellIJ = std::make_pair(0, 0); @@ -217,17 +235,17 @@ cvf::ref RigStimPlanFractureDefinition::createFractureGrid(cons QString condUnit = RiaDefines::unitStringConductivity(fractureTemplateUnit); - std::vector> conductivityValuesAtTimeStep = this->getMirroredDataAtTimeIndex(resultName, - condUnit, - m_activeTimeStepIndex); + std::vector> conductivityValuesAtTimeStep = this->getDataAtTimeIndex(resultName, + condUnit, + activeTimeStepIndex); - std::vector depthCoordsAtNodes = this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture); - std::vector xCoordsAtNodes = this->getNegAndPosXcoords(); + std::vector yCoordsAtNodes = this->adjustedYCoordsAroundWellPathPosition(wellPathIntersectionAtFractureDepth); + std::vector xCoordsAtNodes = this->m_Xs; std::vector xCoords; for ( int i = 0; i < static_cast(xCoordsAtNodes.size()) - 1; i++ ) xCoords.push_back((xCoordsAtNodes[i] + xCoordsAtNodes[i + 1]) / 2); std::vector depthCoords; - for ( int i = 0; i < static_cast(depthCoordsAtNodes.size()) - 1; i++ ) depthCoords.push_back((depthCoordsAtNodes[i] + depthCoordsAtNodes[i + 1]) / 2); + for ( int i = 0; i < static_cast(yCoordsAtNodes.size()) - 1; i++ ) depthCoords.push_back((yCoordsAtNodes[i] + yCoordsAtNodes[i + 1]) / 2); for ( int i = 0; i < static_cast(xCoords.size()) - 1; i++ ) { @@ -276,8 +294,8 @@ cvf::ref RigStimPlanFractureDefinition::createFractureGrid(cons cvf::ref 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 RigStimPlanFractureDefinition::fractureGridResults(const QSt size_t timeStepIndex) const { std::vector fractureGridResults; - std::vector> resultValuesAtTimeStep = this->getMirroredDataAtTimeIndex(resultName, - unitName, - timeStepIndex); + const std::vector>& resultValuesAtTimeStep = this->getDataAtTimeIndex(resultName, + unitName, + timeStepIndex); - for ( int i = 0; i < static_cast(mirroredGridXCount()) - 2; i++ ) + for ( int i = 0; i < static_cast(xCount()) - 2; i++ ) { - for ( int j = 0; j < static_cast(depthCount()) - 2; j++ ) + for ( int j = 0; j < static_cast(yCount()) - 2; j++ ) { if ( j+1 < static_cast(resultValuesAtTimeStep.size()) && i+1 < static_cast(resultValuesAtTimeStep[j + 1].size()) ) { @@ -315,16 +333,16 @@ std::vector RigStimPlanFractureDefinition::fractureGridResults(const QSt //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RigStimPlanFractureDefinition::createFractureTriangleGeometry(double m_wellPathDepthAtFracture, +void RigStimPlanFractureDefinition::createFractureTriangleGeometry(double wellPathIntersectionAtFractureDepth, RiaEclipseUnitTools::UnitSystem neededUnit, const QString& fractureUserName, std::vector* vertices, std::vector* triangleIndices) { - std::vector xCoords = this->getNegAndPosXcoords(); + std::vector xCoords = this->m_Xs; cvf::uint lenXcoords = static_cast(xCoords.size()); - std::vector adjustedDepths = this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture); + std::vector 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 &polygon) //-------------------------------------------------------------------------------------------------- std::vector 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 polygon; - std::vector> dataAtTimeStep = this->getDataAtTimeIndex(resultName, resultUnit, m_activeTimeStepIndex); + std::vector> dataAtTimeStep = this->getDataAtTimeIndex(resultName, resultUnit, activeTimeStepIndex); - std::vector adjustedDepths = this->adjustedDepthCoordsAroundWellPathPosition(m_wellPathDepthAtFracture); + std::vector adjustedYs = this->adjustedYCoordsAroundWellPathPosition(wellPathIntersectionAtFractureDepth); for ( int k = 0; k < static_cast(dataAtTimeStep.size()); k++ ) { @@ -442,18 +460,18 @@ std::vector RigStimPlanFractureDefinition::createFractureBorderPolyg { if ( (i > 0) && ((dataAtTimeStep[k])[(i - 1)] > 1e-7) ) //side neighbour cell different from 0 { - polygon.push_back(cvf::Vec3f(static_cast(this->m_gridXs[i]), - static_cast(adjustedDepths[k]), 0.0f)); + polygon.push_back(cvf::Vec3f(static_cast(this->m_Xs[i]), + static_cast(adjustedYs[k]), 0.0f)); } else if ( (k < static_cast(dataAtTimeStep.size()) - 1) && ((dataAtTimeStep[k + 1])[(i)] > 1e-7) )//cell below different from 0 { - polygon.push_back(cvf::Vec3f(static_cast(this->m_gridXs[i]), - static_cast(adjustedDepths[k]), 0.0f)); + polygon.push_back(cvf::Vec3f(static_cast(this->m_Xs[i]), + static_cast(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(this->m_gridXs[i]), - static_cast(adjustedDepths[k]), 0.0f)); + polygon.push_back(cvf::Vec3f(static_cast(this->m_Xs[i]), + static_cast(adjustedYs[k]), 0.0f)); } } } @@ -518,28 +536,15 @@ std::vector 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 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 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; +} diff --git a/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.h b/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.h index 4181d4691f..3a667d2f31 100644 --- a/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.h +++ b/ApplicationCode/ReservoirDataModel/RigStimPlanFractureDefinition.h @@ -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 > > 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& 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& 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> generateDataLayoutFromFileDataLayout(std::vector> rawXYData); + + + std::vector adjustedYCoordsAroundWellPathPosition(double wellPathIntersectionAtFractureDepth) const; +public: - std::vector getNegAndPosXcoords() const; - std::vector adjustedDepthCoordsAroundWellPathPosition(double wellPathDepthAtFracture) const; - cvf::ref 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* vertices, @@ -89,17 +92,19 @@ public: std::vector 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& 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 > getStimPlanPropertyNamesUnits() const; +private: bool numberOfParameterValuesOK(std::vector> propertyValuesAtTimestep); +public: size_t totalNumberTimeSteps(); void setDataAtTimeValue(QString resultName, QString unit, std::vector> data, double timeStepValue); const std::vector>& 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> getMirroredDataAtTimeIndex(const QString& resultName, - const QString& unitName, - size_t timeStepIndex) const; - private: - RiaEclipseUnitTools::UnitSystem m_unitSet; - std::vector m_gridXs; - std::vector m_gridYs; - std::vector depths; + // Data read from file + RiaEclipseUnitTools::UnitSystem m_unitSet; + std::vector m_fileXs; + std::vector m_Ys; + std::vector m_timeSteps; - double m_topPerfTvd; - double m_bottomPerfTvd; + // Modified file data + std::vector m_stimPlanResults; + std::vector m_Xs; + bool m_xMirrorMode; - std::vector m_timeSteps; - std::vector m_stimPlanResults; + double m_topPerfTvd; + double m_bottomPerfTvd; }; - - diff --git a/doc/fracture_clases.plantuml b/doc/fracture_clases.plantuml index f6fd1ddedc..b4e0b2dd83 100644 --- a/doc/fracture_clases.plantuml +++ b/doc/fracture_clases.plantuml @@ -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 { + <> readStimPlanXMLFile() +} RimFractureTemplate <|-- RimEllipseFractureTemplate RimFractureTemplate <|-- RimStimPlanFractureTemplate @@ -80,9 +83,7 @@ class RicExportFractureCompletionsImpl{ generateFracturesCompdatValues() } - - - - +RimStimPlanFractureTemplate ---> RifStimPlanXmlReader +RifStimPlanXmlReader ...> "create" RigStimPlanFractureDefinition @enduml