///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016- Statoil 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 // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimSimWellFracture.h" #include "RigCell.h" #include "RigMainGrid.h" #include "RigSimWellData.h" #include "RimEclipseView.h" #include "RimEllipseFractureTemplate.h" #include "RimFracture.h" #include "RimFractureTemplate.h" #include "RimProject.h" #include "RimSimWellInView.h" #include "RigWellPath.h" #include "cafPdmUiDoubleSliderEditor.h" CAF_PDM_SOURCE_INIT(RimSimWellFracture, "SimWellFracture"); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSimWellFracture::RimSimWellFracture(void) { CAF_PDM_InitObject("SimWellFracture", ":/FractureSymbol16x16.png", "", ""); CAF_PDM_InitField(&m_location, "MeasuredDepth", 0.0f, "Pseudo Length Location", "", "", ""); m_location.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleSliderEditor::uiEditorTypeName()); CAF_PDM_InitFieldNoDefault(&m_displayIJK, "Cell_IJK", "Cell IJK", "", "", ""); m_displayIJK.registerGetMethod(this, &RimSimWellFracture::createOneBasedIJKText); m_displayIJK.uiCapability()->setUiReadOnly(true); m_displayIJK.xmlCapability()->disableIO(); CAF_PDM_InitField(&m_branchIndex, "Branch", 0, "Branch", "", "", ""); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSimWellFracture::~RimSimWellFracture() {} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::setClosestWellCoord(cvf::Vec3d& position, size_t branchIndex) { computeSimWellBranchesIfRequired(); double location = m_branchCenterLines[branchIndex].locationAlongWellCoords(position); m_branchIndex = static_cast(branchIndex); m_location = location; updateFracturePositionFromLocation(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::updateAzimuthBasedOnWellAzimuthAngle() { computeSimWellBranchesIfRequired(); if (!fractureTemplate()) return; if (fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH || fractureTemplate()->orientationType() == RimFractureTemplate::TRANSVERSE_WELL_PATH) { double simWellAzimuth = wellAzimuthAtFracturePosition(); if (fractureTemplate()->orientationType() == RimFractureTemplate::ALONG_WELL_PATH) { m_azimuth = simWellAzimuth; } else if (fractureTemplate()->orientationType() == RimFractureTemplate::TRANSVERSE_WELL_PATH) { if (simWellAzimuth + 90 < 360) m_azimuth = simWellAzimuth + 90; else m_azimuth = simWellAzimuth - 90; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimSimWellFracture::wellAzimuthAtFracturePosition() const { double simWellAzimuth = m_branchCenterLines[m_branchIndex].simWellAzimuthAngle(fracturePosition()); if (simWellAzimuth < 0) simWellAzimuth += 360; return simWellAzimuth; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimSimWellFracture::wellDipAtFracturePosition() { computeSimWellBranchesIfRequired(); double simWellDip = m_branchCenterLines[m_branchIndex].simWellDipAngle(fracturePosition()); return simWellDip; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::loadDataAndUpdate() { computeSimWellBranchCenterLines(); updateFracturePositionFromLocation(); updateAzimuthBasedOnWellAzimuthAngle(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSimWellFracture::perforationLengthCenterLineCoords() const { std::vector coords; if (!m_branchCenterLines.empty() && m_branchIndex < static_cast(m_branchCenterLines.size())) { RigWellPath wellPathGeometry; wellPathGeometry.m_wellPathPoints = m_branchCenterLines[m_branchIndex].wellPathPoints(); wellPathGeometry.m_measuredDepths = m_branchCenterLines[m_branchIndex].measuredDepths(); double startMd = m_location - perforationLength() / 2.0; double endMd = m_location + perforationLength() / 2.0; coords = wellPathGeometry.clippedPointSubset(startMd, endMd).first; } return coords; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { RimFracture::fieldChangedByUi(changedField, oldValue, newValue); if (changedField == &m_location || changedField == &m_branchIndex) { updateFracturePositionFromLocation(); RimFractureTemplate::FracOrientationEnum orientation; if (fractureTemplate()) orientation = fractureTemplate()->orientationType(); else orientation = RimFractureTemplate::AZIMUTH; if (orientation != RimFractureTemplate::AZIMUTH) { updateAzimuthBasedOnWellAzimuthAngle(); } RimProject* proj; this->firstAncestorOrThisOfType(proj); if (proj) proj->reloadCompletionTypeResultsInAllViews(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::recomputeWellCenterlineCoordinates() { m_branchCenterLines.clear(); computeSimWellBranchesIfRequired(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::updateFracturePositionFromLocation() { computeSimWellBranchesIfRequired(); if (m_branchCenterLines.size() > 0) { cvf::Vec3d interpolated = m_branchCenterLines[m_branchIndex()].interpolatedPointAlongWellPath(m_location()); this->setAnchorPosition(interpolated); RimProject* proj; this->firstAncestorOrThisOfType(proj); if (proj) proj->scheduleCreateDisplayModelAndRedrawAllViews(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { RimFracture::defineUiOrdering(uiConfigName, uiOrdering); uiOrdering.add(nameField()); uiOrdering.add(&m_fractureTemplate); caf::PdmUiGroup* locationGroup = uiOrdering.addNewGroup("Location / Orientation"); locationGroup->add(&m_location); locationGroup->add(&m_branchIndex); locationGroup->add(&m_azimuth); locationGroup->add(&m_uiWellPathAzimuth); locationGroup->add(&m_uiWellFractureAzimuthDiff); locationGroup->add(&m_wellFractureAzimuthAngleWarning); locationGroup->add(&m_dip); locationGroup->add(&m_tilt); caf::PdmUiGroup* propertyGroup = uiOrdering.addNewGroup("Properties"); propertyGroup->add(&m_fractureUnit); propertyGroup->add(&m_stimPlanTimeIndexToPlot); propertyGroup->add(&m_perforationLength); propertyGroup->add(&m_perforationEfficiency); propertyGroup->add(&m_wellDiameter); caf::PdmUiGroup* fractureCenterGroup = uiOrdering.addNewGroup("Fracture Center Info"); fractureCenterGroup->add(&m_uiAnchorPosition); fractureCenterGroup->add(&m_displayIJK); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) { RimFracture::defineEditorAttribute(field, uiConfigName, attribute); if (field == &m_location) { caf::PdmUiDoubleSliderEditorAttribute* myAttr = dynamic_cast(attribute); if (myAttr) { computeSimWellBranchesIfRequired(); if (m_branchCenterLines.size() > 0) { const RigSimulationWellCoordsAndMD& pointAndMd = m_branchCenterLines[m_branchIndex]; myAttr->m_minimum = pointAndMd.measuredDepths().front(); myAttr->m_maximum = pointAndMd.measuredDepths().back(); myAttr->m_sliderTickCount = pointAndMd.measuredDepths().back(); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QList RimSimWellFracture::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) { QList options = RimFracture::calculateValueOptions(fieldNeedingOptions, useOptionsOnly); if (fieldNeedingOptions == &m_branchIndex) { if (m_branchCenterLines.size() == 0) { computeSimWellBranchesIfRequired(); } if (m_branchCenterLines.size() > 0) { size_t branchCount = m_branchCenterLines.size(); for (size_t bIdx = 0; bIdx < branchCount; ++bIdx) { // Use 1-based index in UI options.push_back(caf::PdmOptionItemInfo(QString::number(bIdx + 1), QVariant::fromValue(bIdx))); } } } return options; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigMainGrid* RimSimWellFracture::ownerCaseMainGrid() const { RimEclipseView* ownerEclView; this->firstAncestorOrThisOfType(ownerEclView); if (ownerEclView) return ownerEclView->mainGrid(); else return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::computeSimWellBranchesIfRequired() { if (m_branchCenterLines.size() == 0) { computeSimWellBranchCenterLines(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSimWellFracture::computeSimWellBranchCenterLines() { m_branchCenterLines.clear(); RimSimWellInView* rimWell = nullptr; this->firstAncestorOrThisOfType(rimWell); CVF_ASSERT(rimWell); std::vector> pipeBranchesCLCoords; std::vector> pipeBranchesCellIds; rimWell->calculateWellPipeStaticCenterLine(pipeBranchesCLCoords, pipeBranchesCellIds); for (const auto& branch : pipeBranchesCLCoords) { RigSimulationWellCoordsAndMD wellPathWithMD(branch); m_branchCenterLines.push_back(wellPathWithMD); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSimWellFracture::createOneBasedIJKText() const { RigMainGrid* mainGrid = ownerCaseMainGrid(); size_t i, j, k; size_t anchorCellIdx = mainGrid->findReservoirCellIndexFromPoint(anchorPosition()); if (anchorCellIdx == cvf::UNDEFINED_SIZE_T) return ""; size_t gridLocalCellIdx; const RigGridBase* hostGrid = mainGrid->gridAndGridLocalIdxFromGlobalCellIdx(anchorCellIdx, &gridLocalCellIdx); bool ok = hostGrid->ijkFromCellIndex(gridLocalCellIdx, &i, &j, &k); if (!ok) return ""; return QString("Grid %1: [%2, %3, %4]").arg(QString::fromStdString(hostGrid->gridName())).arg(i + 1).arg(j + 1).arg(k + 1); }