2015-05-26 01:57:53 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Copyright (C) 2015- Statoil ASA
|
|
|
|
// Copyright (C) 2015- Ceetron Solutions AS
|
2019-09-06 03:40:57 -05:00
|
|
|
//
|
2015-05-26 01:57:53 -05:00
|
|
|
// 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.
|
2019-09-06 03:40:57 -05:00
|
|
|
//
|
2015-05-26 01:57:53 -05:00
|
|
|
// 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.
|
2019-09-06 03:40:57 -05:00
|
|
|
//
|
|
|
|
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
2015-05-26 01:57:53 -05:00
|
|
|
// for more details.
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "RigFemPartGrid.h"
|
|
|
|
|
|
|
|
#include "RigFemPart.h"
|
2020-03-02 01:37:36 -06:00
|
|
|
|
|
|
|
#include <array>
|
2021-04-06 14:04:31 -05:00
|
|
|
#include <climits>
|
2015-05-29 04:27:23 -05:00
|
|
|
#include <cmath>
|
2015-05-26 01:57:53 -05:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-11-07 02:01:31 -06:00
|
|
|
RigFemPartGrid::RigFemPartGrid()
|
|
|
|
: m_femPart( nullptr )
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2020-02-12 04:13:38 -06:00
|
|
|
RigFemPartGrid::~RigFemPartGrid()
|
|
|
|
{
|
|
|
|
}
|
2015-05-26 01:57:53 -05:00
|
|
|
|
2019-11-07 02:01:31 -06:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void RigFemPartGrid::setFemPart( const RigFemPart* femPart )
|
|
|
|
{
|
|
|
|
m_femPart = femPart;
|
|
|
|
generateStructGridData();
|
|
|
|
}
|
|
|
|
|
2015-05-27 08:35:14 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-27 08:35:14 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-05-29 00:53:03 -05:00
|
|
|
void RigFemPartGrid::generateStructGridData()
|
2015-05-27 08:35:14 -05:00
|
|
|
{
|
2015-05-29 00:53:03 -05:00
|
|
|
//[X] 1. Calculate neighbors for each element
|
|
|
|
//[X] record the ones with 3 or fewer neighbors as possible grid corners
|
2019-09-06 03:40:57 -05:00
|
|
|
//[X] 2. Loop over the possible corner cells,
|
|
|
|
//[X] find the one that corresponds to IJK = 000
|
2015-05-29 02:24:31 -05:00
|
|
|
//[X] by finding the one closest to origo // Does not work
|
|
|
|
//[X] by Determining what surfs correspond to NEG IJK surfaces in that element,
|
|
|
|
// and that none of those faces have a neighbor
|
2019-09-06 03:40:57 -05:00
|
|
|
//[X] 4. Assign IJK = 000 to that element
|
2015-05-29 00:53:03 -05:00
|
|
|
//[X] Store IJK in elm idx array
|
|
|
|
//[X] 5. Loop along POS I surfaces increment I for each element and assign IJK
|
|
|
|
//[X] when at end, go to POS J neighbor, increment J, repeat above.
|
|
|
|
//[X] etc for POS Z
|
2019-09-06 03:40:57 -05:00
|
|
|
//[X] Find max IJK as you go,
|
2015-05-29 00:53:03 -05:00
|
|
|
//[ ] also assert that there are no NEG I/NEG J/NEG Z neighbors when starting on a new row
|
|
|
|
//[ ] (Need to find min, and offset IJK values if there exists such)
|
|
|
|
//[ ] 6. If IJK to elm idx is needed, allocate "grid" with maxI,maxJ,maxZ values
|
|
|
|
//[ ] Loop over elms, assign elmIdx to IJK address in grid
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
int elmIdxForIJK_000 = findElmIdxForIJK000();
|
|
|
|
|
|
|
|
if ( elmIdxForIJK_000 == -1 ) return;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2015-05-29 02:24:31 -05:00
|
|
|
// Find the IJK faces based on the corner cell
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
cvf::Vec3i ijkMainFaceIndices = findMainIJKFaces( elmIdxForIJK_000 );
|
2015-05-27 08:35:14 -05:00
|
|
|
|
2015-05-29 00:53:03 -05:00
|
|
|
// assign ijk to cells
|
2015-05-27 08:35:14 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
m_ijkPrElement.resize( m_femPart->elementCount(), cvf::Vec3i( -1, -1, -1 ) );
|
2015-05-27 08:35:14 -05:00
|
|
|
|
2015-05-29 02:24:31 -05:00
|
|
|
int posIFaceIdx = ijkMainFaceIndices[0];
|
|
|
|
int posJFaceIdx = ijkMainFaceIndices[1];
|
|
|
|
int posKFaceIdx = ijkMainFaceIndices[2];
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2020-06-03 15:31:58 -05:00
|
|
|
m_elementIJKCounts = cvf::Vec3st( 0, 0, 0 );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2020-10-09 06:43:31 -05:00
|
|
|
int elmIdxInK = elmIdxForIJK_000;
|
|
|
|
int kCoord = 0;
|
2019-09-06 03:40:57 -05:00
|
|
|
while ( true )
|
2015-05-29 00:53:03 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
int elmIdxInJ = elmIdxInK;
|
|
|
|
cvf::Vec3f startElmInKNormalJ = m_femPart->faceNormal( elmIdxInJ, posJFaceIdx );
|
|
|
|
cvf::Vec3f startElmInKNormalI = m_femPart->faceNormal( elmIdxInJ, posIFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
int jCoord = 0;
|
2019-09-06 03:40:57 -05:00
|
|
|
while ( true )
|
2015-05-29 00:53:03 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
int elmIdxInI = elmIdxInJ;
|
|
|
|
cvf::Vec3f startElmInJNormalI = m_femPart->faceNormal( elmIdxInI, posIFaceIdx );
|
|
|
|
int iCoord = 0;
|
|
|
|
while ( true )
|
2015-05-29 00:53:03 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( elmIdxInI >= 0 && size_t( elmIdxInI ) < m_ijkPrElement.size() );
|
2015-05-29 00:53:03 -05:00
|
|
|
// Assign ijk coordinate
|
2019-09-06 03:40:57 -05:00
|
|
|
m_ijkPrElement[elmIdxInI] = cvf::Vec3i( iCoord, jCoord, kCoord );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
++iCoord;
|
|
|
|
|
|
|
|
// Find neighbor and exit if at end
|
2019-09-06 03:40:57 -05:00
|
|
|
int neighborElmIdx = m_femPart->elementNeighbor( elmIdxInI, posIFaceIdx );
|
|
|
|
if ( neighborElmIdx == -1 ) break;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Find the continuing face in the neighbor element (opposite of the neighbor face)
|
2019-09-06 03:40:57 -05:00
|
|
|
int neighborNegFaceIdx = m_femPart->neighborFace( elmIdxInI, posIFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
RigElementType eType = m_femPart->elementType( neighborElmIdx );
|
|
|
|
posIFaceIdx = RigFemTypes::oppositeFace( eType, neighborNegFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Step to neighbor
|
|
|
|
elmIdxInI = neighborElmIdx;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Scoped to show that nothing bleeds further to K-loop
|
|
|
|
{
|
2020-06-03 15:31:58 -05:00
|
|
|
if ( iCoord > static_cast<int>( m_elementIJKCounts[0] ) ) m_elementIJKCounts[0] = iCoord;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
++jCoord;
|
|
|
|
|
|
|
|
// Find neighbor and exit if at end
|
2019-09-06 03:40:57 -05:00
|
|
|
int neighborElmIdx = m_femPart->elementNeighbor( elmIdxInJ, posJFaceIdx );
|
|
|
|
if ( neighborElmIdx == -1 ) break;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Find the continuing face in the neighbor element (opposite of the neighbor face)
|
2019-09-06 03:40:57 -05:00
|
|
|
int neighborNegFaceIdx = m_femPart->neighborFace( elmIdxInJ, posJFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
RigElementType eType = m_femPart->elementType( neighborElmIdx );
|
|
|
|
posJFaceIdx = RigFemTypes::oppositeFace( eType, neighborNegFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Now where is posIFace of the new J cell ?
|
2019-09-06 03:40:57 -05:00
|
|
|
posIFaceIdx = perpendicularFaceInDirection( startElmInJNormalI, neighborNegFaceIdx, neighborElmIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Step to neighbor
|
|
|
|
elmIdxInJ = neighborElmIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2020-06-03 15:31:58 -05:00
|
|
|
if ( jCoord > static_cast<int>( m_elementIJKCounts[1] ) ) m_elementIJKCounts[1] = jCoord;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
++kCoord;
|
|
|
|
|
|
|
|
// Find neighbor and exit if at end
|
2019-09-06 03:40:57 -05:00
|
|
|
int neighborElmIdx = m_femPart->elementNeighbor( elmIdxInK, posKFaceIdx );
|
|
|
|
if ( neighborElmIdx == -1 ) break;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Find the continuing face in the neighbor element (opposite of the neighbor face)
|
2019-09-06 03:40:57 -05:00
|
|
|
int neighborNegFaceIdx = m_femPart->neighborFace( elmIdxInK, posKFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
RigElementType eType = m_femPart->elementType( neighborElmIdx );
|
|
|
|
posKFaceIdx = RigFemTypes::oppositeFace( eType, neighborNegFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Now where is posJFace of the new K cell ?
|
2019-09-06 03:40:57 -05:00
|
|
|
posJFaceIdx = perpendicularFaceInDirection( startElmInKNormalJ, neighborNegFaceIdx, neighborElmIdx );
|
|
|
|
posIFaceIdx = perpendicularFaceInDirection( startElmInKNormalI, neighborNegFaceIdx, neighborElmIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
|
|
|
// Step to neighbor
|
|
|
|
elmIdxInK = neighborElmIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-03 15:31:58 -05:00
|
|
|
if ( kCoord > static_cast<int>( m_elementIJKCounts[2] ) ) m_elementIJKCounts[2] = kCoord;
|
2015-05-29 00:53:03 -05:00
|
|
|
}
|
2015-10-18 02:43:05 -05:00
|
|
|
|
2020-06-03 15:31:58 -05:00
|
|
|
m_elmIdxPrIJK.resize( m_elementIJKCounts[0], m_elementIJKCounts[1], m_elementIJKCounts[2] );
|
2015-10-18 02:43:05 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( int elmIdx = 0; elmIdx < m_femPart->elementCount(); ++elmIdx )
|
2015-10-18 02:43:05 -05:00
|
|
|
{
|
2018-05-25 02:35:53 -05:00
|
|
|
size_t i, j, k;
|
2019-09-06 03:40:57 -05:00
|
|
|
bool validIndex = ijkFromCellIndex( elmIdx, &i, &j, &k );
|
|
|
|
if ( validIndex )
|
2018-05-25 02:35:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
m_elmIdxPrIJK.at( i, j, k ) = elmIdx;
|
2018-05-25 02:35:53 -05:00
|
|
|
}
|
2015-10-18 02:43:05 -05:00
|
|
|
}
|
2018-03-06 02:33:03 -06:00
|
|
|
|
|
|
|
// IJK bounding box
|
2019-09-06 03:40:57 -05:00
|
|
|
m_reservoirIJKBoundingBox.first = cvf::Vec3st( INT_MAX, INT_MAX, INT_MAX );
|
|
|
|
m_reservoirIJKBoundingBox.second = cvf::Vec3st( 0, 0, 0 );
|
|
|
|
cvf::Vec3st& min = m_reservoirIJKBoundingBox.first;
|
|
|
|
cvf::Vec3st& max = m_reservoirIJKBoundingBox.second;
|
2018-03-06 02:33:03 -06:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( int elmIdx = 0; elmIdx < m_femPart->elementCount(); ++elmIdx )
|
2018-03-06 02:33:03 -06:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
RigElementType elementType = m_femPart->elementType( elmIdx );
|
|
|
|
size_t i, j, k;
|
|
|
|
bool validIndex = ijkFromCellIndex( elmIdx, &i, &j, &k );
|
|
|
|
if ( elementType == HEX8P && validIndex )
|
2018-03-06 02:33:03 -06:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( i < min.x() ) min.x() = i;
|
|
|
|
if ( j < min.y() ) min.y() = j;
|
|
|
|
if ( k < min.z() ) min.z() = k;
|
|
|
|
if ( i > max.x() ) max.x() = i;
|
|
|
|
if ( j > max.y() ) max.y() = j;
|
|
|
|
if ( k > max.z() ) max.z() = k;
|
2018-03-06 02:33:03 -06:00
|
|
|
}
|
|
|
|
}
|
2015-05-27 08:35:14 -05:00
|
|
|
}
|
|
|
|
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-05-29 02:24:31 -05:00
|
|
|
int RigFemPartGrid::findElmIdxForIJK000()
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2015-05-27 08:35:14 -05:00
|
|
|
const std::vector<int>& possibleGridCorners = m_femPart->possibleGridCornerElements();
|
2019-09-06 03:40:57 -05:00
|
|
|
size_t possibleCornerCount = possibleGridCorners.size();
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( size_t pcIdx = 0; pcIdx < possibleCornerCount; ++pcIdx )
|
2015-05-27 08:35:14 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
int elmIdx = possibleGridCorners[pcIdx];
|
|
|
|
cvf::Vec3i ijkMainFaceIndices = findMainIJKFaces( elmIdx );
|
2015-05-26 01:57:53 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( m_femPart->elementNeighbor( elmIdx, ijkMainFaceIndices[0] ) != -1 &&
|
|
|
|
m_femPart->elementNeighbor( elmIdx, ijkMainFaceIndices[1] ) != -1 &&
|
|
|
|
m_femPart->elementNeighbor( elmIdx, ijkMainFaceIndices[2] ) != -1 )
|
2015-05-27 08:35:14 -05:00
|
|
|
{
|
2015-05-29 02:24:31 -05:00
|
|
|
return elmIdx;
|
2015-05-27 08:35:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-29 02:24:31 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-29 02:24:31 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
cvf::Vec3i RigFemPartGrid::findMainIJKFaces( int elementIndex ) const
|
2015-05-29 02:24:31 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
cvf::Vec3i ijkMainFaceIndices = cvf::Vec3i( -1, -1, -1 );
|
2015-05-29 02:24:31 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
RigElementType eType = m_femPart->elementType( elementIndex );
|
2020-06-03 15:31:58 -05:00
|
|
|
int faceCount = RigFemTypes::elementFaceCount( eType );
|
2019-09-06 03:40:57 -05:00
|
|
|
std::vector<cvf::Vec3f> normals( faceCount );
|
|
|
|
for ( int faceIdx = 0; faceIdx < faceCount; ++faceIdx )
|
2015-05-29 02:24:31 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
normals[faceIdx] = m_femPart->faceNormal( elementIndex, faceIdx );
|
2015-05-29 02:24:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Record three independent main direction vectors for the element, and what face they are created from
|
|
|
|
cvf::Vec3f mainElmDirections[3];
|
2019-09-06 03:40:57 -05:00
|
|
|
int mainElmDirOriginFaces[3];
|
|
|
|
if ( eType == HEX8 || eType == HEX8P )
|
2015-05-29 02:24:31 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
mainElmDirections[0] = normals[0] - normals[1]; // To get a better "average" direction vector
|
|
|
|
mainElmDirections[1] = normals[2] - normals[3];
|
|
|
|
mainElmDirections[2] = normals[4] - normals[5];
|
2015-05-29 02:24:31 -05:00
|
|
|
mainElmDirOriginFaces[0] = 0;
|
|
|
|
mainElmDirOriginFaces[1] = 2;
|
|
|
|
mainElmDirOriginFaces[2] = 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-05-29 04:27:23 -05:00
|
|
|
mainElmDirections[0] = cvf::Vec3f::ZERO;
|
|
|
|
mainElmDirections[1] = cvf::Vec3f::ZERO;
|
|
|
|
mainElmDirections[2] = cvf::Vec3f::ZERO;
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-29 02:24:31 -05:00
|
|
|
}
|
|
|
|
|
2015-12-03 03:12:03 -06:00
|
|
|
mainElmDirections[0].normalize();
|
|
|
|
mainElmDirections[1].normalize();
|
|
|
|
mainElmDirections[2].normalize();
|
|
|
|
|
2015-05-29 02:24:31 -05:00
|
|
|
// Match the element main directions with best XYZ match (IJK respectively)
|
2015-12-03 03:12:03 -06:00
|
|
|
// Find the mainElmDirection with the largest component starting with Z
|
|
|
|
// and use that for the corresponding IJK direction.
|
2019-09-06 03:40:57 -05:00
|
|
|
// Find the Z (for K) first. Then select among the other two the Y (for J),
|
2015-12-03 03:12:03 -06:00
|
|
|
// and select the remaining for I
|
2015-05-29 02:24:31 -05:00
|
|
|
|
2020-11-06 03:46:38 -06:00
|
|
|
int mainElmDirectionIdxForIJK[3] = { -1, -1, -1 };
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( int cIdx = 2; cIdx >= 0; --cIdx ) // Check Z first as it is more important
|
2015-05-29 02:24:31 -05:00
|
|
|
{
|
2015-12-03 03:12:03 -06:00
|
|
|
double maxAbsComp = -1.0;
|
2019-09-06 03:40:57 -05:00
|
|
|
int usedDir1 = -1;
|
|
|
|
int usedDir2 = -1;
|
2015-12-03 03:12:03 -06:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( int dIdx = 0; dIdx < 3; ++dIdx )
|
2015-05-29 02:24:31 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( dIdx == usedDir1 || dIdx == usedDir2 ) continue;
|
2015-12-03 03:12:03 -06:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
float absComp = fabs( mainElmDirections[dIdx][cIdx] );
|
|
|
|
if ( absComp > maxAbsComp )
|
2015-05-29 02:24:31 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
maxAbsComp = absComp;
|
2015-05-29 02:24:31 -05:00
|
|
|
mainElmDirectionIdxForIJK[cIdx] = dIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( usedDir1 == -1 )
|
|
|
|
usedDir1 = mainElmDirectionIdxForIJK[cIdx];
|
|
|
|
else
|
|
|
|
usedDir2 = mainElmDirectionIdxForIJK[cIdx];
|
2015-05-29 02:24:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Assign the correct face based on the main direction
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
ijkMainFaceIndices[0] = ( mainElmDirections[mainElmDirectionIdxForIJK[0]] * cvf::Vec3f::X_AXIS > 0 )
|
|
|
|
? mainElmDirOriginFaces[mainElmDirectionIdxForIJK[0]]
|
|
|
|
: RigFemTypes::oppositeFace( eType, mainElmDirOriginFaces[mainElmDirectionIdxForIJK[0]] );
|
|
|
|
ijkMainFaceIndices[1] = ( mainElmDirections[mainElmDirectionIdxForIJK[1]] * cvf::Vec3f::Y_AXIS > 0 )
|
|
|
|
? mainElmDirOriginFaces[mainElmDirectionIdxForIJK[1]]
|
|
|
|
: RigFemTypes::oppositeFace( eType, mainElmDirOriginFaces[mainElmDirectionIdxForIJK[1]] );
|
|
|
|
ijkMainFaceIndices[2] = ( mainElmDirections[mainElmDirectionIdxForIJK[2]] * -cvf::Vec3f::Z_AXIS > 0 )
|
|
|
|
? mainElmDirOriginFaces[mainElmDirectionIdxForIJK[2]]
|
|
|
|
: RigFemTypes::oppositeFace( eType, mainElmDirOriginFaces[mainElmDirectionIdxForIJK[2]] );
|
2015-05-29 02:24:31 -05:00
|
|
|
|
|
|
|
return ijkMainFaceIndices;
|
2015-05-29 00:53:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2018-03-06 02:33:03 -06:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
std::pair<cvf::Vec3st, cvf::Vec3st> RigFemPartGrid::reservoirIJKBoundingBox() const
|
|
|
|
{
|
|
|
|
return m_reservoirIJKBoundingBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-05-29 00:53:03 -05:00
|
|
|
/// Find the face that is not perpFaceIdx or its opposite, and has normal closest to direction
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
int RigFemPartGrid::perpendicularFaceInDirection( cvf::Vec3f direction, int perpFaceIdx, int elmIdx )
|
2015-05-29 00:53:03 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
RigElementType eType = m_femPart->elementType( elmIdx );
|
2020-06-03 15:31:58 -05:00
|
|
|
int faceCount = RigFemTypes::elementFaceCount( eType );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
int oppFace = RigFemTypes::oppositeFace( eType, perpFaceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
double minDiffSqLength = HUGE_VAL;
|
2015-05-29 00:53:03 -05:00
|
|
|
cvf::Vec3f faceNormal;
|
|
|
|
direction.normalize();
|
|
|
|
int bestFace = -1;
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( int faceIdx = 0; faceIdx < faceCount; ++faceIdx )
|
2015-05-29 00:53:03 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( faceIdx == perpFaceIdx || faceIdx == oppFace ) continue;
|
2015-05-29 00:53:03 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
faceNormal = m_femPart->faceNormal( elmIdx, faceIdx );
|
2015-05-29 00:53:03 -05:00
|
|
|
faceNormal.normalize();
|
2019-09-06 03:40:57 -05:00
|
|
|
float diffSqLength = ( direction - faceNormal ).lengthSquared();
|
|
|
|
if ( diffSqLength < minDiffSqLength )
|
2015-05-29 00:53:03 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
bestFace = faceIdx;
|
2015-05-29 00:53:03 -05:00
|
|
|
minDiffSqLength = diffSqLength;
|
|
|
|
}
|
|
|
|
}
|
2015-05-27 08:35:14 -05:00
|
|
|
|
2015-05-29 00:53:03 -05:00
|
|
|
return bestFace;
|
2015-05-27 08:35:14 -05:00
|
|
|
}
|
2015-05-26 01:57:53 -05:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
size_t RigFemPartGrid::gridPointCountI() const
|
|
|
|
{
|
2020-06-03 15:31:58 -05:00
|
|
|
return m_elementIJKCounts[0] + 1;
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
size_t RigFemPartGrid::gridPointCountJ() const
|
|
|
|
{
|
2020-06-03 15:31:58 -05:00
|
|
|
return m_elementIJKCounts[1] + 1;
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
size_t RigFemPartGrid::gridPointCountK() const
|
|
|
|
{
|
2020-06-03 15:31:58 -05:00
|
|
|
return m_elementIJKCounts[2] + 1;
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
bool RigFemPartGrid::isCellValid( size_t i, size_t j, size_t k ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
cvf::Vec3d RigFemPartGrid::minCoordinate() const
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return cvf::Vec3d::ZERO;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
cvf::Vec3d RigFemPartGrid::maxCoordinate() const
|
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return cvf::Vec3d::ZERO;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
bool RigFemPartGrid::cellIJKNeighbor( size_t i, size_t j, size_t k, FaceType face, size_t* neighborCellIndex ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
size_t RigFemPartGrid::cellIndexFromIJK( size_t i, size_t j, size_t k ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
return m_elmIdxPrIJK.at( i, j, k );
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
bool RigFemPartGrid::ijkFromCellIndex( size_t cellIndex, size_t* i, size_t* j, size_t* k ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( cellIndex < m_ijkPrElement.size() )
|
2018-05-25 02:35:53 -05:00
|
|
|
{
|
2018-08-22 03:35:30 -05:00
|
|
|
int signed_i = m_ijkPrElement[cellIndex][0];
|
|
|
|
int signed_j = m_ijkPrElement[cellIndex][1];
|
|
|
|
int signed_k = m_ijkPrElement[cellIndex][2];
|
2018-05-25 02:35:53 -05:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
if ( signed_i >= 0 && signed_j >= 0 && signed_k >= 0 )
|
2018-08-22 03:35:30 -05:00
|
|
|
{
|
|
|
|
*i = signed_i;
|
|
|
|
*j = signed_j;
|
|
|
|
*k = signed_k;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2018-05-25 02:35:53 -05:00
|
|
|
return false;
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
bool RigFemPartGrid::cellIJKFromCoordinate( const cvf::Vec3d& coord, size_t* i, size_t* j, size_t* k ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
void RigFemPartGrid::cellCornerVertices( size_t cellIndex, cvf::Vec3d vertices[8] ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-01-21 08:45:35 -06:00
|
|
|
const std::vector<cvf::Vec3f>& nodeCoords = m_femPart->nodes().coordinates;
|
2019-09-06 03:40:57 -05:00
|
|
|
const int* cornerIndices = m_femPart->connectivities( cellIndex );
|
2019-01-21 08:45:35 -06:00
|
|
|
|
2019-09-06 03:40:57 -05:00
|
|
|
for ( size_t i = 0; i < 8; ++i )
|
2019-01-21 08:45:35 -06:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
vertices[i] = cvf::Vec3d( nodeCoords[cornerIndices[i]] );
|
2019-01-21 08:45:35 -06:00
|
|
|
}
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
cvf::Vec3d RigFemPartGrid::cellCentroid( size_t cellIndex ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2020-03-02 01:37:36 -06:00
|
|
|
std::array<cvf::Vec3d, 8> cellVertices;
|
|
|
|
this->cellCornerVertices( cellIndex, cellVertices.data() );
|
|
|
|
|
|
|
|
cvf::Vec3d centroid( 0.0, 0.0, 0.0 );
|
|
|
|
for ( int i = 0; i < 8; ++i )
|
|
|
|
{
|
|
|
|
centroid += cellVertices[i];
|
|
|
|
}
|
|
|
|
return centroid / 8.0;
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
void RigFemPartGrid::cellMinMaxCordinates( size_t cellIndex, cvf::Vec3d* minCoordinate, cvf::Vec3d* maxCoordinate ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
size_t RigFemPartGrid::gridPointIndexFromIJK( size_t i, size_t j, size_t k ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return cvf::UNDEFINED_SIZE_T;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
///
|
2015-05-26 01:57:53 -05:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2019-09-06 03:40:57 -05:00
|
|
|
cvf::Vec3d RigFemPartGrid::gridPointCoordinate( size_t i, size_t j, size_t k ) const
|
2015-05-26 01:57:53 -05:00
|
|
|
{
|
2019-09-06 03:40:57 -05:00
|
|
|
CVF_ASSERT( false );
|
2015-05-26 01:57:53 -05:00
|
|
|
return cvf::Vec3d::ZERO;
|
|
|
|
}
|