///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2021 - Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #pragma once #include "RimNamedObject.h" #include "RigStimPlanFractureDefinition.h" class RigFractureCell; class RigSlice2D; class RigHistogramData; class Layer { public: Layer( double topDepth, double bottomDepth ) : m_topDepth( topDepth ) , m_bottomDepth( bottomDepth ){}; double topDepth() const { return m_topDepth; }; double bottomDepth() const { return m_bottomDepth; }; double centerDepth() const { return ( m_bottomDepth + m_topDepth ) / 2.0; }; double thickness() const { return m_topDepth - m_bottomDepth; }; private: double m_topDepth; double m_bottomDepth; }; //================================================================================================== /// /// //================================================================================================== class RimEnsembleFractureStatistics : public RimNamedObject { CAF_PDM_HEADER_INIT; public: enum class StatisticsType { MEAN, MIN, MAX, P10, P50, P90, OCCURRENCE }; enum class MeshAlignmentType { PERFORATION_DEPTH, MESH_DEPTH }; enum class MeshType { ADAPTIVE, UNIFORM, NAIVE }; enum class MeanType { HARMONIC, ARITHMETIC, GEOMETRIC, MINIMUM }; enum class AdaptiveNumLayersType { MINIMUM, MAXIMUM, AVERAGE, USER_DEFINED }; RimEnsembleFractureStatistics(); ~RimEnsembleFractureStatistics() override; void addFilePath( const QString& filePath ); void loadAndUpdateData(); std::vector> readFractureDefinitions() const; static std::vector> createFractureGrids( const std::vector>& stimPlanFractureDefinitions, RiaDefines::EclipseUnitSystem unitSystem, const QString& resultName, MeshAlignmentType meshAlignmentType ); bool excludeZeroWidthFractures() const; protected: void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; QString generateFilePathsTable(); std::vector computeStatistics(); static double computeDepthOfWellPathAtFracture( cvf::ref stimPlanFractureDefinitionData ); static bool isCoordinateInsideFractureCell( double x, double y, const RigFractureCell& cell ); std::pair>, std::vector> readFractureDefinitions( const std::vector& filePaths, RiaDefines::EclipseUnitSystem unitSystem ) const; static std::set> findAllResultNames( const std::vector>& stimPlanFractureDefinitions ); std::tuple findSamplingIntervals( const std::vector>& stimPlanFractureDefinitions, std::vector& gridXs, std::vector& gridYs ) const; void generateUniformMesh( double minX, double maxX, double minY, double maxY, std::vector& gridXs, std::vector& gridYs ) const; void generateNaiveMesh( double minX, double maxX, double minY, double maxY, const std::vector>& stimPlanFractureDefinitions, std::vector& gridXs, std::vector& gridYs ) const; void generateAdaptiveMesh( double minX, double maxX, double minY, double maxY, const std::vector>& stimPlanFractureDefinitions, std::vector& gridXs, std::vector& gridYs ) const; int getTargetNumberOfLayers( const std::vector>& stimPlanFractureDefinitions ) const; static std::tuple findMaxGridExtents( const std::vector>& stimPlanFractureDefinitions, MeshAlignmentType meshAlignmentType ); void computeMeanThicknessPerLayer( const std::vector& layers, int targetNumLayers, double minY, double binSize, std::vector& means, std::vector& baseDepth ) const; static void generateAllLayers( const std::vector>& stimPlanFractureDefinitions, std::vector& layers, MeshAlignmentType meshAlignmentType ); static void sampleAllGrids( const std::vector>& fractureGrids, const std::vector& samplesX, const std::vector& samplesY, std::vector>& samples, std::shared_ptr areaGrid, std::shared_ptr distanceGrid ); static std::shared_ptr setCellsToFillTargetArea( const RigSlice2D& grid, const RigSlice2D& occurrenceGrid, const RigSlice2D& areaGrid, const RigSlice2D& distanceGrid, double targetArea ); static void generateStatisticsGrids( const std::vector>& samples, size_t numSamplesX, size_t numSamplesY, size_t numGrids, std::map>& statisticsGrids, const std::vector>& statisticsTypes, const RigHistogramData& areaHistogram, std::shared_ptr areaGrid, std::shared_ptr distanceGrid ); static bool writeStatisticsToCsv( const QString& filePath, const RigSlice2D& samples ); static double linearSampling( double minValue, double maxValue, int numSamples, std::vector& samples ); QString generateStatisticsTable( const std::vector>& stimPlanFractureDefinitions ) const; caf::PdmField> m_filePaths; caf::PdmField m_filePathsTable; caf::PdmField m_statisticsTable; caf::PdmField m_excludeZeroWidthFractures; caf::PdmField m_computeStatistics; caf::PdmField m_numSamplesX; caf::PdmField m_numSamplesY; caf::PdmField> m_meshType; caf::PdmField> m_meshAlignmentType; caf::PdmField> m_adaptiveMeanType; caf::PdmField> m_adaptiveNumLayersType; caf::PdmField m_adaptiveNumLayers; caf::PdmField>> m_selectedStatisticsType; };