Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions src/coreComponents/mesh/WellElementRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,21 @@ void WellElementRegion::generateWell( MeshLevel & mesh,
// 1) select the local perforations based on connectivity to the local reservoir elements
subRegion.connectPerforationsToMeshElements( mesh, lineBlock, geomTol );
globalIndex const matchedPerforations = MpiWrapper::sum( perforationData->size() );
//should we do this check in the well generator? Here we don't have the wellGeneratorDataContext
GEOS_THROW_IF( matchedPerforations != numPerforationsGlobal,
GEOS_FMT( "Invalid mapping perforation-to-element in {} {}. This happens when GEOSX cannot match "
"a perforation with a reservoir element. There are two common reasons for this error:\n"
" 1- The most common reason for this error is that a perforation is on a section of "
" the well polyline located outside the domain.\n"
" 2- This error can also happen if a perforation falls on a mesh face or a mesh vertex."
" Please try to move the perforation slightly (to the interior of the perforated cell) "
"to see if it fixes the problem.",
InternalWellGenerator::catalogName(),
getWellGeneratorName() ),
InputError, getDataContext() );
// TODO: should we do this check in the well generator? Here we don't have the wellGeneratorDataContext
GEOS_THROW_IF_LT_MSG( matchedPerforations, numPerforationsGlobal,
GEOS_FMT( "Invalid mapping in {} {}: {} perforation(s) not found in domain. Verify perforations are "
"within the domain boundaries.",
InternalWellGenerator::catalogName(),
getWellGeneratorName(),
numPerforationsGlobal - matchedPerforations ),
InputError, getDataContext() );

GEOS_THROW_IF_GT_MSG( matchedPerforations, numPerforationsGlobal,
GEOS_FMT( "Invalid mapping in {} {}: Perforations falsely matched to multiple cells, likely "
"indicating bad mesh quality.",
InternalWellGenerator::catalogName(),
getWellGeneratorName() ),
InputError, getDataContext() );
Comment thread
dkachuma marked this conversation as resolved.

// 2) classify well elements based on connectivity to local mesh partition
array1d< integer > elemStatusGlobal;
Expand Down
42 changes: 33 additions & 9 deletions src/coreComponents/mesh/WellElementSubRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,8 @@ void WellElementSubRegion::connectPerforationsToMeshElements( MeshLevel & mesh,
lineBlock.getName(), iperfGlobal,
location[0], location[1], location[2] ) );

bool perfFound = false;

localIndex erStart = -1, erEnd = -1;

localIndex const targetRegionIndex = elemManager.getRegions().getIndex( perfTargetRegionGlobal[iperfGlobal] );
Expand All @@ -936,14 +938,28 @@ void WellElementSubRegion::connectPerforationsToMeshElements( MeshLevel & mesh,
localIndex esrMatched = -1;
localIndex eiMatched = -1;
globalIndex giMatched = -1;
integer const resElemFound = searchLocalElements( mesh,
location,
m_searchDepth,
er,
esrMatched,
eiMatched,
giMatched,
geomTol );
integer resElemFound = searchLocalElements( mesh,
location,
m_searchDepth,
er,
esrMatched,
eiMatched,
giMatched,
geomTol );

// Multiple ranks can match the element of the well perforation occurs at the interface of 2 or multiple
// cells (face, edge or even vertex). We will arbitrarily assign the perforation to the process with the
// lowest global id
integer const matchedRanks = MpiWrapper::sum( resElemFound ? 1 : 0 );
if( 1 < matchedRanks )
{
globalIndex const minId = MpiWrapper::min( giMatched < 0 ? LvArray::NumericLimits< globalIndex >::max : giMatched );
// If this process does not have the lowest Id we will say it hasn't found the element
if( minId != giMatched )
{
resElemFound = 0;
}
}
Comment on lines +950 to +962

// if the element was found
if( resElemFound )
Expand All @@ -968,9 +984,17 @@ void WellElementSubRegion::connectPerforationsToMeshElements( MeshLevel & mesh,
}

// if one rank has found the element, all ranks exit the search
if( MpiWrapper::allReduce( resElemFound, MpiWrapper::Reduction::LogicalOr ))
perfFound = perfFound || ( 0 < matchedRanks );
if( perfFound )
break;
}

// We will issue this only as a warning to capture all failed perforations.
// If the feailure is irrecoverable, an error will be issued in WellElementRegion
GEOS_WARNING_IF( !perfFound && MpiWrapper::commRank() == 0,
GEOS_FMT( "Failed to locate perforation {} for well {} with location ({}, {}, {}). "
"This is because the perforation is on a section of the well polyline located outside the domain.",
perfName[iperfGlobal], lineBlock.getName(), location[0], location[1], location[2] ));
}

// set the size based on the number of perforations matched with local reservoir elements
Expand Down
Loading