diff --git a/ApplicationLibCode/Application/Tools/RiaLogging.cpp b/ApplicationLibCode/Application/Tools/RiaLogging.cpp index 014dcfc2818..dfd86968148 100644 --- a/ApplicationLibCode/Application/Tools/RiaLogging.cpp +++ b/ApplicationLibCode/Application/Tools/RiaLogging.cpp @@ -20,6 +20,7 @@ #include "RiaGuiApplication.h" #include "RiaRegressionTestRunner.h" +#include #include #include @@ -263,6 +264,15 @@ void RiaLogging::debug( const QString& message ) } } +//-------------------------------------------------------------------------------------------------- +/// Usage: RiaLogging::debugTimer( "Message", [&]() { code(); } ); +//-------------------------------------------------------------------------------------------------- +void RiaLogging::debugTimer( const QString& message, std::function callable ) +{ + RiaScopeTimer timing( message ); + callable(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -404,3 +414,27 @@ std::vector RiaThreadSafeLogger::messages() const { return m_messages; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaScopeTimer::RiaScopeTimer( const QString& message ) + : m_startTime( std::chrono::high_resolution_clock::now() ) + , m_message( message ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaScopeTimer::~RiaScopeTimer() +{ + auto end = std::chrono::high_resolution_clock::now(); + + // Default unit for duration is seconds + std::chrono::duration duration = end - m_startTime; + + auto text = m_message + QString( " (duration : %1 seconds)" ).arg( duration.count() ); + + RiaLogging::debug( text ); +} diff --git a/ApplicationLibCode/Application/Tools/RiaLogging.h b/ApplicationLibCode/Application/Tools/RiaLogging.h index c0e8e5bf1b2..44b603258f2 100644 --- a/ApplicationLibCode/Application/Tools/RiaLogging.h +++ b/ApplicationLibCode/Application/Tools/RiaLogging.h @@ -18,11 +18,14 @@ #pragma once +#include +#include #include #include #include -class QString; +#include + class QWidget; enum class RILogLevel @@ -52,6 +55,28 @@ class RiaLogger virtual void debug( const char* message ) = 0; }; +//================================================================================================== +// +// Timing class for measuring time spent in a scope. Will create a debug log message and the time spent. +// +// Usage: +// { +// RiaScopeTimer timer( "Message" ); +// // Code to measure +// } +// +//================================================================================================== +class RiaScopeTimer +{ +public: + RiaScopeTimer( const QString& message ); + ~RiaScopeTimer(); + +private: + std::chrono::time_point m_startTime; + QString m_message; +}; + //================================================================================================== // // @@ -70,6 +95,8 @@ class RiaLogging static void info( const QString& message ); static void debug( const QString& message ); + static void debugTimer( const QString& message, std::function callable ); + static void errorInMessageBox( QWidget* parent, const QString& title, const QString& text ); private: diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp index 845e4f8e19b..45bd87dcdcc 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp @@ -719,14 +719,14 @@ void RimEclipseCase::loadAndSynchronizeInputProperties( bool importGridOrFaultDa //-------------------------------------------------------------------------------------------------- void RimEclipseCase::ensureFaultDataIsComputed() { - RigEclipseCaseData* rigEclipseCase = eclipseCaseData(); - if ( rigEclipseCase ) + if ( !m_readerSettings.importFaults ) return; + + if ( RigEclipseCaseData* rigEclipseCase = eclipseCaseData() ) { - if ( m_readerSettings.importFaults ) - { - RigActiveCellInfo* actCellInfo = rigEclipseCase->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ); - rigEclipseCase->mainGrid()->calculateFaults( actCellInfo ); - } + RiaScopeTimer timing( "Calculate faults" ); + + RigActiveCellInfo* actCellInfo = rigEclipseCase->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ); + rigEclipseCase->mainGrid()->calculateFaults( actCellInfo ); } } diff --git a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp index 62a351de753..0dd51c3a5e7 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.cpp @@ -479,6 +479,48 @@ void RigMainGrid::computeBoundingBox() } } +namespace StructGridDefines +{ +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +consteval auto cubeFaceIndices() +{ + // + // 7---------6 + // /| /| |k + // / | / | | /j + // 4---------5 | |/ + // | 3------|--2 *---i + // | / | / + // |/ |/ + // 0---------1 + + return std::array>, 6>{ + { { cvf::StructGridInterface::FaceType::NEG_K, { 0, 3, 2, 1 } }, + { cvf::StructGridInterface::FaceType::POS_K, { 4, 5, 6, 7 } }, + { cvf::StructGridInterface::FaceType::NEG_J, { 0, 1, 5, 4 } }, + { cvf::StructGridInterface::FaceType::POS_J, { 3, 7, 6, 2 } }, + { cvf::StructGridInterface::FaceType::NEG_I, { 0, 4, 7, 3 } }, + { cvf::StructGridInterface::FaceType::POS_I, { 1, 2, 6, 5 } } } }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +auto createFaceIndicesMap() +{ + std::map> faultFaceToFaceIdxs; + + for ( const auto& [key, value] : cubeFaceIndices() ) + { + faultFaceToFaceIdxs[key] = value; + } + + return faultFaceToFaceIdxs; +} +}; // namespace StructGridDefines + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -515,8 +557,12 @@ void RigMainGrid::calculateFaults( const RigActiveCellInfo* activeCellInfo ) const std::vector& vxs = m_mainGrid->nodes(); + auto faultFaceToFaceIdxs = StructGridDefines::createFaceIndicesMap(); + std::vector& unNamedFaultFaces = unNamedFault->faultFaces(); std::vector& unNamedFaultFacesInactive = unNamedFaultWithInactive->faultFaces(); + +#pragma omp parallel for for ( int gcIdx = 0; gcIdx < static_cast( m_cells.size() ); ++gcIdx ) { addUnNamedFaultFaces( gcIdx, @@ -526,7 +572,8 @@ void RigMainGrid::calculateFaults( const RigActiveCellInfo* activeCellInfo ) unNamedFaultWithInactiveIdx, unNamedFaultFaces, unNamedFaultFacesInactive, - m_faultsPrCellAcc.p() ); + m_faultsPrCellAcc.p(), + faultFaceToFaceIdxs ); } } @@ -540,15 +587,14 @@ void RigMainGrid::addUnNamedFaultFaces( int gcIdx, int unNamedFaultWithInactiveIdx, std::vector& unNamedFaultFaces, std::vector& unNamedFaultFacesInactive, - RigFaultsPrCellAccumulator* faultsPrCellAcc ) const + RigFaultsPrCellAccumulator* faultsPrCellAcc, + const std::map>& faceMap ) const { if ( m_cells[gcIdx].isInvalid() ) { return; } - size_t neighborReservoirCellIdx; - size_t neighborGridCellIdx; size_t i = 0; size_t j = 0; size_t k = 0; @@ -564,47 +610,76 @@ void RigMainGrid::addUnNamedFaultFaces( int gcIdx, { cvf::StructGridInterface::FaceType face = cvf::StructGridInterface::FaceType( faceIdx ); - // For faces that has no used defined Fault assigned: + int faultState = -1; + // #pragma omp critical + { + faultState = faultsPrCellAcc->faultIdx( gcIdx, face ); + } - if ( m_faultsPrCellAcc->faultIdx( gcIdx, face ) == RigFaultsPrCellAccumulator::NO_FAULT ) + // For faces that has no used defined Fault assigned: + if ( faultState == RigFaultsPrCellAccumulator::NO_FAULT ) { // Find neighbor cell if ( firstNO_FAULTFaceForCell ) // To avoid doing this for every face, and only when detecting a NO_FAULT { - size_t gridLocalCellIndex; - hostGrid = gridAndGridLocalIdxFromGlobalCellIdx( gcIdx, &gridLocalCellIndex ); + size_t index = gcIdx; + + i = index % m_cellCount.x(); + index /= m_cellCount.x(); + j = index % m_cellCount.y(); + k = index / m_cellCount.y(); - hostGrid->ijkFromCellIndex( gridLocalCellIndex, &i, &j, &k ); isCellActive = activeCellInfo->isActive( gcIdx ); firstNO_FAULTFaceForCell = false; } - if ( !hostGrid->cellIJKNeighbor( i, j, k, face, &neighborGridCellIdx ) ) - { - continue; - } + size_t ni, nj, nk; + hostGrid->neighborIJKAtCellFace( i, j, k, face, &ni, &nj, &nk ); - neighborReservoirCellIdx = hostGrid->reservoirCellIndex( neighborGridCellIdx ); - if ( m_cells[neighborReservoirCellIdx].isInvalid() ) + if ( ni >= m_cellCount.x() || nj >= m_cellCount.y() || nk >= m_cellCount.z() ) { continue; } - bool isNeighborCellActive = activeCellInfo->isActive( neighborReservoirCellIdx ); + const size_t nbGridLocalCellIndex = ni + nj * m_cellCount.x() + nk * m_cellCount.x() * m_cellCount.y(); + const size_t neighborReservoirCellIdx = m_indexToStartOfCells + nbGridLocalCellIndex; + const auto& nbCell = m_mainGrid->globalCellArray()[neighborReservoirCellIdx]; + + if ( nbCell.isInvalid() ) continue; + + const double threshold = 1e-6; + const double tol = threshold * threshold; - double tolerance = 1e-6; + // cvf::ubyte faceNodeIndices[4]; + size_t faceIdxs[4]; - std::array faceIdxs; - m_cells[gcIdx].faceIndices( face, &faceIdxs ); - std::array nbFaceIdxs; - m_cells[neighborReservoirCellIdx].faceIndices( StructGridInterface::oppositeFace( face ), &nbFaceIdxs ); + // m_mainGrid->cellFaceVertexIndices( face, faceNodeIndices ); + auto faceNodeIndices = faceMap.at( face ); + + const auto& cornerIndices = m_cells[gcIdx].cornerIndices(); + faceIdxs[0] = cornerIndices[faceNodeIndices[0]]; + faceIdxs[1] = cornerIndices[faceNodeIndices[1]]; + faceIdxs[2] = cornerIndices[faceNodeIndices[2]]; + faceIdxs[3] = cornerIndices[faceNodeIndices[3]]; + + // cvf::ubyte nbFaceNodeIndices[4]; + size_t nbFaceIdxs[4]; + + // m_mainGrid->cellFaceVertexIndices( StructGridInterface::oppositeFace( face ), nbFaceNodeIndices ); + auto nbFaceNodeIndices = faceMap.at( StructGridInterface::oppositeFace( face ) ); + + const auto& nbCornerIndices = m_cells[neighborReservoirCellIdx].cornerIndices(); + nbFaceIdxs[0] = nbCornerIndices[nbFaceNodeIndices[0]]; + nbFaceIdxs[1] = nbCornerIndices[nbFaceNodeIndices[1]]; + nbFaceIdxs[2] = nbCornerIndices[nbFaceNodeIndices[2]]; + nbFaceIdxs[3] = nbCornerIndices[nbFaceNodeIndices[3]]; bool sharedFaceVertices = true; - if ( sharedFaceVertices && vxs[faceIdxs[0]].pointDistance( vxs[nbFaceIdxs[0]] ) > tolerance ) sharedFaceVertices = false; - if ( sharedFaceVertices && vxs[faceIdxs[1]].pointDistance( vxs[nbFaceIdxs[3]] ) > tolerance ) sharedFaceVertices = false; - if ( sharedFaceVertices && vxs[faceIdxs[2]].pointDistance( vxs[nbFaceIdxs[2]] ) > tolerance ) sharedFaceVertices = false; - if ( sharedFaceVertices && vxs[faceIdxs[3]].pointDistance( vxs[nbFaceIdxs[1]] ) > tolerance ) sharedFaceVertices = false; + if ( sharedFaceVertices && vxs[faceIdxs[0]].pointDistanceSquared( vxs[nbFaceIdxs[0]] ) > tol ) sharedFaceVertices = false; + if ( sharedFaceVertices && vxs[faceIdxs[1]].pointDistanceSquared( vxs[nbFaceIdxs[3]] ) > tol ) sharedFaceVertices = false; + if ( sharedFaceVertices && vxs[faceIdxs[2]].pointDistanceSquared( vxs[nbFaceIdxs[2]] ) > tol ) sharedFaceVertices = false; + if ( sharedFaceVertices && vxs[faceIdxs[3]].pointDistanceSquared( vxs[nbFaceIdxs[1]] ) > tol ) sharedFaceVertices = false; if ( sharedFaceVertices ) { @@ -612,17 +687,21 @@ void RigMainGrid::addUnNamedFaultFaces( int gcIdx, } // To avoid doing this calculation for the opposite face - int faultIdx = unNamedFaultIdx; + bool isNeighborCellActive = activeCellInfo->isActive( m_indexToStartOfCells + nbGridLocalCellIndex ); + int faultIdx = unNamedFaultIdx; if ( !( isCellActive && isNeighborCellActive ) ) faultIdx = unNamedFaultWithInactiveIdx; - faultsPrCellAcc->setFaultIdx( gcIdx, face, faultIdx ); - faultsPrCellAcc->setFaultIdx( neighborReservoirCellIdx, StructGridInterface::oppositeFace( face ), faultIdx ); +#pragma omp critical + { + faultsPrCellAcc->setFaultIdx( gcIdx, face, faultIdx ); + faultsPrCellAcc->setFaultIdx( neighborReservoirCellIdx, StructGridInterface::oppositeFace( face ), faultIdx ); + + // Add as fault face only if the grid index is less than the neighbors - // Add as fault face only if the grid index is less than the neighbors + size_t cellIdxLow = std::min( static_cast( gcIdx ), neighborReservoirCellIdx ); + size_t cellIdxHigh = std::max( static_cast( gcIdx ), neighborReservoirCellIdx ); - if ( static_cast( gcIdx ) < neighborReservoirCellIdx ) - { - RigFault::FaultFace ff( gcIdx, cvf::StructGridInterface::FaceType( faceIdx ), neighborReservoirCellIdx ); + RigFault::FaultFace ff( cellIdxLow, cvf::StructGridInterface::FaceType( faceIdx ), cellIdxHigh ); if ( isCellActive && isNeighborCellActive ) { unNamedFaultFaces.push_back( ff ); @@ -632,10 +711,6 @@ void RigMainGrid::addUnNamedFaultFaces( int gcIdx, unNamedFaultFacesInactive.push_back( ff ); } } - else - { - CVF_FAIL_MSG( "Found fault with global neighbor index less than the native index. " ); - } } } } diff --git a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h index d0a851dad48..507ea5d1573 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h +++ b/ApplicationLibCode/ReservoirDataModel/RigMainGrid.h @@ -74,14 +74,15 @@ class RigMainGrid : public RigGridBase cvf::Collection& faults(); void calculateFaults( const RigActiveCellInfo* activeCellInfo ); - void addUnNamedFaultFaces( int gcIdx, - const RigActiveCellInfo* activeCellInfo, - const std::vector& vxs, - int unNamedFaultIdx, - int unNamedFaultWithInactiveIdx, - std::vector& unNamedFaultFaces, - std::vector& unNamedFaultFacesInactive, - RigFaultsPrCellAccumulator* faultsPrCellAcc ) const; + void addUnNamedFaultFaces( int gcIdx, + const RigActiveCellInfo* activeCellInfo, + const std::vector& vxs, + int unNamedFaultIdx, + int unNamedFaultWithInactiveIdx, + std::vector& unNamedFaultFaces, + std::vector& unNamedFaultFacesInactive, + RigFaultsPrCellAccumulator* faultsPrCellAcc, + const std::map>& faceMap ) const; void distributeNNCsToFaults();