///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 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 "RimFishbonesMultipleSubs.h" #include "RigFishbonesGeometry.h" #include "RigWellPath.h" #include "RimProject.h" #include "RimWellPath.h" #include "RimFishbonesCollection.h" #include "cafPdmUiDoubleValueEditor.h" #include "cafPdmUiListEditor.h" #include "cvfAssert.h" #include "cvfBoundingBox.h" #include #include #include "cvfMath.h" CAF_PDM_SOURCE_INIT(RimFishbonesMultipleSubs, "FishbonesMultipleSubs"); namespace caf { template<> void AppEnum::setUp() { addItem(RimFishbonesMultipleSubs::FB_SUB_COUNT_END, "FB_SUB_COUNT", "Start/End/Number of Subs"); addItem(RimFishbonesMultipleSubs::FB_SUB_SPACING_END, "FB_SUB_SPACING", "Start/End/Spacing"); addItem(RimFishbonesMultipleSubs::FB_SUB_USER_DEFINED, "FB_SUB_CUSTOM", "User Specification"); setDefault(RimFishbonesMultipleSubs::FB_SUB_COUNT_END); } template<> void AppEnum::setUp() { addItem(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_FIXED, "FB_LATERAL_ORIENTATION_FIXED", "Fixed Angle"); addItem(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_RANDOM, "FB_LATERAL_ORIENTATION_RANDOM", "Random Angle"); setDefault(RimFishbonesMultipleSubs::FB_LATERAL_ORIENTATION_RANDOM); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimFishbonesMultipleSubs::RimFishbonesMultipleSubs() { CAF_PDM_InitObject("FishbonesMultipleSubs", ":/FishBoneGroup16x16.png", "", ""); CAF_PDM_InitField(&m_isActive, "Active", true, "Active", "", "", ""); m_isActive.uiCapability()->setUiHidden(true); CAF_PDM_InitFieldNoDefault(&m_name, "Name", "Name", "", "", ""); m_name.registerGetMethod(this, &RimFishbonesMultipleSubs::generatedName); m_name.uiCapability()->setUiReadOnly(true); m_name.xmlCapability()->setIOWritable(false); CAF_PDM_InitField(&fishbonesColor, "Color", cvf::Color3f(0.999f, 0.333f, 0.999f), "Fishbones Color", "", "", ""); CAF_PDM_InitField(&m_lateralCountPerSub, "LateralCountPerSub", 3, "Laterals Per Sub", "", "", ""); CAF_PDM_InitField(&m_lateralLength, "LateralLength", QString("11.0"), "Length(s) [m]", "", "Specify multiple length values if the sub lengths differ", ""); CAF_PDM_InitField(&m_lateralExitAngle, "LateralExitAngle", 35.0, "Exit Angle [deg]", "", "", ""); CAF_PDM_InitField(&m_lateralBuildAngle, "LateralBuildAngle", 6.0, "Build Angle [deg/m]", "", "", ""); CAF_PDM_InitField(&m_lateralTubingDiameter, "LateralTubingDiameter", 8.0, "Tubing Diameter [mm]", "", "", ""); CAF_PDM_InitField(&m_lateralOpenHoleRoghnessFactor, "LateralOpenHoleRoghnessFactor", 0.001, "Open Hole Roghness Factor [m]", "", "", ""); CAF_PDM_InitField(&m_lateralTubingRoghnessFactor, "LateralTubingRoghnessFactor", 1e-5, "Tubing Roghness Factor [m]", "", "", ""); CAF_PDM_InitField(&m_lateralInstallSuccessFraction, "LateralInstallSuccessFraction", 1.0, "Install Success Rate [0..1]", "", "", ""); CAF_PDM_InitField(&m_icdCount, "IcdCount", 2, "ICDs per Sub", "", "", ""); CAF_PDM_InitField(&m_icdOrificeDiameter, "IcdOrificeDiameter", 7.0, "ICD Orifice Diameter [mm]", "", "", ""); CAF_PDM_InitField(&m_icdFlowCoefficient, "IcdFlowCoefficient", 1.5, "ICD Flow Coefficient", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_locationOfSubs, "LocationOfSubs", "Measured Depths [m]", "", "", ""); m_locationOfSubs.uiCapability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); CAF_PDM_InitField(&m_subsLocationMode, "SubsLocationMode", caf::AppEnum(FB_SUB_COUNT_END), "Location Defined By", "", "", ""); CAF_PDM_InitField(&m_rangeStart, "RangeStart", 100.0, "Start MD [m]", "", "", ""); m_rangeStart.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleValueEditor::uiEditorTypeName()); CAF_PDM_InitField(&m_rangeEnd, "RangeEnd", 250.0, "End MD [m]", "", "", ""); m_rangeEnd.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleValueEditor::uiEditorTypeName()); CAF_PDM_InitFieldNoDefault(&m_rangeSubSpacing, "RangeSubSpacing", "Spacing [m]", "", "", ""); m_rangeSubSpacing.uiCapability()->setUiEditorTypeName(caf::PdmUiDoubleValueEditor::uiEditorTypeName()); CAF_PDM_InitField(&m_rangeSubCount, "RangeSubCount", 13, "Number of Subs", "", "", ""); CAF_PDM_InitField(&m_subsOrientationMode, "SubsOrientationMode", caf::AppEnum(FB_LATERAL_ORIENTATION_RANDOM), "Orientation", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_installationRotationAngles, "InstallationRotationAngles", "Installation Rotation Angles [deg]", "", "", ""); m_installationRotationAngles.uiCapability()->setUiHidden(true); CAF_PDM_InitField(&m_fixedInstallationRotationAngle, "FixedInstallationRotationAngle", 0.0, " Fixed Angle [deg]", "", "", ""); CAF_PDM_InitFieldNoDefault(&m_pipeProperties, "PipeProperties", "Pipe Properties", "", "", ""); m_pipeProperties.uiCapability()->setUiHidden(true); m_pipeProperties.uiCapability()->setUiTreeChildrenHidden(true); m_pipeProperties = new RimFishbonesPipeProperties; m_rigFishbonesGeometry = std::unique_ptr(new RigFisbonesGeometry(this)); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimFishbonesMultipleSubs::~RimFishbonesMultipleSubs() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimFishbonesMultipleSubs::isActive() const { return m_isActive; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimFishbonesMultipleSubs::generatedName() const { caf::PdmChildArrayField* container = dynamic_cast*>(this->parentField()); CVF_ASSERT(container); size_t index = container->index(this); return QString("Fishbone %1").arg(index); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::setMeasuredDepthAndCount(double measuredDepth, double spacing, int subCount) { m_subsLocationMode = FB_SUB_SPACING_END; m_rangeStart = measuredDepth; m_rangeEnd = measuredDepth + spacing * subCount; m_rangeSubCount = subCount; computeRangesAndLocations(); computeRotationAngles(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::measuredDepth(size_t subIndex) const { CVF_ASSERT(subIndex < m_locationOfSubs().size()); return m_locationOfSubs()[subIndex]; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::rotationAngle(size_t index) const { if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED) { return m_fixedInstallationRotationAngle; } else { CVF_ASSERT(index < m_installationRotationAngles().size()); return m_installationRotationAngles()[index]; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::exitAngle() const { return m_lateralExitAngle; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::buildAngle() const { return m_lateralBuildAngle; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::tubingDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const { RimWellPath* wellPath; firstAncestorOrThisOfTypeAsserted(wellPath); if (unitSystem == RiaEclipseUnitTools::UNITS_METRIC) { if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD) { return RiaEclipseUnitTools::inchToMeter(m_lateralTubingDiameter()); } else { return m_lateralTubingDiameter() / 1000; } } else if (unitSystem == RiaEclipseUnitTools::UNITS_FIELD) { if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_METRIC) { return RiaEclipseUnitTools::meterToFeet(m_lateralTubingDiameter() / 1000); } else { return RiaEclipseUnitTools::inchToFeet(m_lateralTubingDiameter()); } } CVF_ASSERT(false); return 0.0; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::effectiveDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const { double innerRadius = tubingDiameter(unitSystem) / 2; double outerRadius = holeDiameter(unitSystem) / 2; double innerArea = cvf::PI_D * innerRadius * innerRadius; double outerArea = cvf::PI_D * outerRadius * outerRadius; double effectiveArea = outerArea - innerArea; double effectiveRadius = cvf::Math::sqrt(effectiveArea / cvf::PI_D); return effectiveRadius * 2; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::openHoleRoughnessFactor(RiaEclipseUnitTools::UnitSystem unitSystem) const { RimWellPath* wellPath; firstAncestorOrThisOfTypeAsserted(wellPath); if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD && unitSystem == RiaEclipseUnitTools::UNITS_METRIC) { return RiaEclipseUnitTools::feetToMeter(m_lateralOpenHoleRoghnessFactor()); } else if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_METRIC && unitSystem == RiaEclipseUnitTools::UNITS_FIELD) { return RiaEclipseUnitTools::meterToFeet(m_lateralOpenHoleRoghnessFactor()); } return m_lateralOpenHoleRoghnessFactor(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RimFishbonesMultipleSubs::icdOrificeDiameter(RiaEclipseUnitTools::UnitSystem unitSystem) const { RimWellPath* wellPath; firstAncestorOrThisOfTypeAsserted(wellPath); if (unitSystem == RiaEclipseUnitTools::UNITS_METRIC) { if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD) { return RiaEclipseUnitTools::inchToMeter(m_icdOrificeDiameter()); } else { return m_icdOrificeDiameter() / 1000; } } else if (unitSystem == RiaEclipseUnitTools::UNITS_FIELD) { if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_METRIC) { return RiaEclipseUnitTools::meterToFeet(m_icdOrificeDiameter() / 1000); } else { return RiaEclipseUnitTools::inchToFeet(m_icdOrificeDiameter()); } } CVF_ASSERT(false); return 0.0; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimFishbonesMultipleSubs::lateralLengths() const { QStringList items = m_lateralLength().split(' '); double currentLength = 0.0; std::vector lengths; for (int i = 0; i < static_cast(m_lateralCountPerSub); i++) { if (i < items.size()) { bool conversionOk = false; double candidateValue = items[i].toDouble(&conversionOk); if (conversionOk) { currentLength = candidateValue; } } lengths.push_back(currentLength); } return lengths; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimFishbonesMultipleSubs::coordsForLateral(size_t subIndex, size_t lateralIndex) const { std::vector> coordsAndMD = m_rigFishbonesGeometry->coordsForLateral(subIndex, lateralIndex); std::vector domainCoords; for (const auto& coordMD : coordsAndMD) { domainCoords.push_back(coordMD.first); } return domainCoords; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector> RimFishbonesMultipleSubs::coordsAndMDForLateral(size_t subIndex, size_t lateralIndex) const { return m_rigFishbonesGeometry->coordsForLateral(subIndex, lateralIndex); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::recomputeLateralLocations() { computeRangesAndLocations(); computeRotationAngles(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::setUnitSystemSpecificDefaults() { RimWellPath* wellPath; firstAncestorOrThisOfType(wellPath); if (wellPath) { if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_METRIC) { m_lateralLength = "11"; m_lateralBuildAngle = 6.0; m_lateralTubingDiameter = 8; m_lateralOpenHoleRoghnessFactor = 0.001; m_lateralTubingRoghnessFactor = 1e-05; m_icdOrificeDiameter = 7; } else if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD) { m_lateralLength = "36"; m_lateralBuildAngle = 1.83; m_lateralTubingDiameter = 0.31; m_lateralOpenHoleRoghnessFactor = 0.0032; m_lateralTubingRoghnessFactor = 3.28e-05; m_icdOrificeDiameter = 0.28; } m_pipeProperties->setUnitSystemSpecificDefaults(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) { bool recomputeLocations = false; if (changedField == &m_subsLocationMode) { if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END) { recomputeLocations = true; } } if (changedField == &m_rangeStart || changedField == &m_rangeEnd || changedField == &m_rangeSubCount || changedField == &m_rangeSubSpacing) { recomputeLocations = true; RimWellPath* wellPath = nullptr; this->firstAncestorOrThisOfTypeAsserted(wellPath); RigWellPath* rigWellPathGeo = wellPath->wellPathGeometry(); if (rigWellPathGeo && !rigWellPathGeo->m_measuredDepths.empty()) { double lastWellPathMD = rigWellPathGeo->m_measuredDepths.back(); m_rangeStart = cvf::Math::clamp(m_rangeStart(), 0.0, lastWellPathMD); m_rangeEnd = cvf::Math::clamp(m_rangeEnd(), m_rangeStart(), lastWellPathMD); } } if (changedField == &m_rangeSubSpacing) { // Minimum distance between fishbones is 13.0m // Use 10.0m to allow for some flexibility double minimumDistanceMeter = 10.0; RimWellPath* wellPath = nullptr; this->firstAncestorOrThisOfTypeAsserted(wellPath); if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD) { double minimumDistanceFeet = RiaEclipseUnitTools::meterToFeet(minimumDistanceMeter); m_rangeSubSpacing = cvf::Math::clamp(m_rangeSubSpacing(), minimumDistanceFeet, std::max(m_rangeSubSpacing(), minimumDistanceFeet)); } else { m_rangeSubSpacing = cvf::Math::clamp(m_rangeSubSpacing(), minimumDistanceMeter, std::max(m_rangeSubSpacing(), minimumDistanceMeter)); } } if (recomputeLocations) { computeRangesAndLocations(); } if (recomputeLocations || changedField == &m_locationOfSubs || changedField == &m_subsOrientationMode) { computeRotationAngles(); } if (changedField == &m_locationOfSubs || changedField == &m_lateralInstallSuccessFraction || changedField == &m_lateralCountPerSub) { computeSubLateralIndices(); } RimProject* proj; this->firstAncestorOrThisOfTypeAsserted(proj); proj->reloadCompletionTypeResultsInAllViews(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimFishbonesMultipleSubs::userDescriptionField() { return &m_name; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimFishbonesMultipleSubs::objectToggleField() { return &m_isActive; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::computeRangesAndLocations() { if (m_subsLocationMode == FB_SUB_COUNT_END) { int divisor = 1; if (m_rangeSubCount > 2) divisor = m_rangeSubCount - 1; m_rangeSubSpacing = fabs(m_rangeStart - m_rangeEnd) / divisor; } else if (m_subsLocationMode == FB_SUB_SPACING_END) { m_rangeSubCount = (fabs(m_rangeStart - m_rangeEnd) / m_rangeSubSpacing) + 1; if (m_rangeSubCount < 1) { m_rangeSubCount = 1; } } if (m_subsLocationMode == FB_SUB_COUNT_END || m_subsLocationMode == FB_SUB_SPACING_END) { std::vector validMeasuredDepths; { RimWellPath* wellPath = nullptr; this->firstAncestorOrThisOfTypeAsserted(wellPath); RigWellPath* rigWellPathGeo = wellPath->wellPathGeometry(); if (rigWellPathGeo && rigWellPathGeo->m_measuredDepths.size() > 1) { double firstWellPathMD = rigWellPathGeo->m_measuredDepths.front(); double lastWellPathMD = rigWellPathGeo->m_measuredDepths.back(); for (auto md : locationsFromStartSpacingAndCount(m_rangeStart, m_rangeSubSpacing, m_rangeSubCount)) { if (md > firstWellPathMD && md < lastWellPathMD) { validMeasuredDepths.push_back(md); } } } } m_locationOfSubs = validMeasuredDepths; } RimFishbonesCollection* collection; this->firstAncestorOrThisOfTypeAsserted(collection); computeSubLateralIndices(); collection->recalculateStartMD(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) { { RimWellPath* wellPath; firstAncestorOrThisOfType(wellPath); if (wellPath) { if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_METRIC) { m_lateralLength.uiCapability()->setUiName("Length(s) [m]"); m_lateralBuildAngle.uiCapability()->setUiName("Build Angle [deg/m]"); m_lateralTubingDiameter.uiCapability()->setUiName("Tubing Diameter [mm]"); m_lateralOpenHoleRoghnessFactor.uiCapability()->setUiName("Open Hole Roughness Factor [m]"); m_lateralTubingRoghnessFactor.uiCapability()->setUiName("Tubing Roughness Factor [m]"); m_icdOrificeDiameter.uiCapability()->setUiName("ICD Orifice Diameter [mm]"); m_locationOfSubs.uiCapability()->setUiName("Measured Depths [m]"); m_rangeStart.uiCapability()->setUiName("Start MD [m]"); m_rangeEnd.uiCapability()->setUiName("End MD [m]"); m_rangeSubSpacing.uiCapability()->setUiName("Spacing [m]"); } else if (wellPath->unitSystem() == RiaEclipseUnitTools::UNITS_FIELD) { m_lateralLength.uiCapability()->setUiName("Length(s) [ft]"); m_lateralBuildAngle.uiCapability()->setUiName("Build Angle [deg/ft]"); m_lateralTubingDiameter.uiCapability()->setUiName("Tubing Diameter [in]"); m_lateralOpenHoleRoghnessFactor.uiCapability()->setUiName("Open Hole Roughness Factor [ft]"); m_lateralTubingRoghnessFactor.uiCapability()->setUiName("Tubing Roughness Factor [ft]"); m_icdOrificeDiameter.uiCapability()->setUiName("ICD Orifice Diameter [in]"); m_locationOfSubs.uiCapability()->setUiName("Measured Depths [ft]"); m_rangeStart.uiCapability()->setUiName("Start MD [ft]"); m_rangeEnd.uiCapability()->setUiName("End MD [ft]"); m_rangeSubSpacing.uiCapability()->setUiName("Spacing [ft]"); } } } { caf::PdmUiGroup* group = uiOrdering.addNewGroup("Appearance"); group->add(&fishbonesColor); } { caf::PdmUiGroup* group = uiOrdering.addNewGroup("Location"); group->add(&m_subsLocationMode); if (m_subsLocationMode() != FB_SUB_USER_DEFINED) { group->add(&m_rangeStart); group->add(&m_rangeEnd); if (m_subsLocationMode() == FB_SUB_COUNT_END) { group->add(&m_rangeSubCount); group->add(&m_rangeSubSpacing); } else if (m_subsLocationMode() == FB_SUB_SPACING_END) { group->add(&m_rangeSubSpacing); group->add(&m_rangeSubCount); } } group->add(&m_locationOfSubs); } { caf::PdmUiGroup* lateralConfigGroup = uiOrdering.addNewGroup("Lateral Configuration"); lateralConfigGroup->add(&m_lateralCountPerSub); lateralConfigGroup->add(&m_lateralLength); lateralConfigGroup->add(&m_lateralExitAngle); lateralConfigGroup->add(&m_lateralBuildAngle); lateralConfigGroup->add(&m_subsOrientationMode); if (m_subsOrientationMode == FB_LATERAL_ORIENTATION_FIXED) { lateralConfigGroup->add(&m_fixedInstallationRotationAngle); } lateralConfigGroup->add(&m_lateralInstallSuccessFraction); } { caf::PdmUiGroup* wellGroup = uiOrdering.addNewGroup("Well Properties"); m_pipeProperties->uiOrdering(uiConfigName, *wellGroup); } { caf::PdmUiGroup* mswGroup = uiOrdering.addNewGroup("Multi Segment Wells"); mswGroup->setCollapsedByDefault(true); mswGroup->add(&m_lateralTubingDiameter); mswGroup->add(&m_lateralOpenHoleRoghnessFactor); mswGroup->add(&m_lateralTubingRoghnessFactor); mswGroup->add(&m_icdCount); mswGroup->add(&m_icdOrificeDiameter); mswGroup->add(&m_icdFlowCoefficient); } // Visibility if (m_subsLocationMode == FB_SUB_USER_DEFINED) { m_locationOfSubs.uiCapability()->setUiReadOnly(false); m_rangeSubSpacing.uiCapability()->setUiReadOnly(true); m_rangeSubCount.uiCapability()->setUiReadOnly(true); m_rangeStart.uiCapability()->setUiReadOnly(true); m_rangeEnd.uiCapability()->setUiReadOnly(true); } else { m_locationOfSubs.uiCapability()->setUiReadOnly(true); m_rangeSubSpacing.uiCapability()->setUiReadOnly(false); m_rangeSubCount.uiCapability()->setUiReadOnly(false); m_rangeStart.uiCapability()->setUiReadOnly(false); m_rangeEnd.uiCapability()->setUiReadOnly(false); if (m_subsLocationMode == FB_SUB_COUNT_END) { m_rangeSubSpacing.uiCapability()->setUiReadOnly(true); m_rangeSubCount.uiCapability()->setUiReadOnly(false); } else { m_rangeSubSpacing.uiCapability()->setUiReadOnly(false); m_rangeSubCount.uiCapability()->setUiReadOnly(true); } } uiOrdering.skipRemainingFields(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::initAfterRead() { if (m_locationOfSubs().size() != m_installationRotationAngles().size()) { computeRotationAngles(); } computeSubLateralIndices(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::BoundingBox RimFishbonesMultipleSubs::boundingBoxInDomainCoords() const { cvf::BoundingBox bb; for (auto& sub : installedLateralIndices()) { for (size_t lateralIndex : sub.lateralIndices) { std::vector coords = coordsForLateral(sub.subIndex, lateralIndex); for (auto c : coords) { bb.add(c); } } } return bb; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::computeRotationAngles() { std::vector vals; for (size_t i = 0; i < m_locationOfSubs().size(); i++) { vals.push_back(RimFishbonesMultipleSubs::randomValueFromRange(0, 360)); } m_installationRotationAngles = vals; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimFishbonesMultipleSubs::computeSubLateralIndices() { m_subLateralIndices.clear(); for (size_t subIndex = 0; subIndex < m_locationOfSubs().size(); ++subIndex) { SubLateralIndex subLateralIndex; subLateralIndex.subIndex = subIndex; for (int lateralIndex = 0; lateralIndex < m_lateralCountPerSub(); ++lateralIndex) { subLateralIndex.lateralIndices.push_back(lateralIndex); } m_subLateralIndices.push_back(subLateralIndex); } double numLaterals = static_cast(m_locationOfSubs().size() * m_lateralCountPerSub); int numToRemove = static_cast(std::round((1 - m_lateralInstallSuccessFraction) * numLaterals)); srand(m_randomSeed()); while (numToRemove > 0) { int subIndexToRemove; do { subIndexToRemove = rand() % m_subLateralIndices.size(); } while (m_subLateralIndices[subIndexToRemove].lateralIndices.empty()); int lateralIndexToRemove = rand() % m_subLateralIndices[subIndexToRemove].lateralIndices.size(); m_subLateralIndices[subIndexToRemove].lateralIndices.erase(m_subLateralIndices[subIndexToRemove].lateralIndices.begin() + lateralIndexToRemove); --numToRemove; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimFishbonesMultipleSubs::locationsFromStartSpacingAndCount(double start, double spacing, size_t count) { std::vector measuredDepths; for (size_t i = 0; i < count; i++) { measuredDepths.push_back(start + spacing * i); } return measuredDepths; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- int RimFishbonesMultipleSubs::randomValueFromRange(int min, int max) { // See http://www.cplusplus.com/reference/cstdlib/rand/ int range = abs(max - min); int randomNumberInRange = rand() % range; int randomValue = min + randomNumberInRange; return randomValue; }