diff --git a/inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_mfd.xml b/inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_mfd.xml
new file mode 100644
index 00000000000..4954c251290
--- /dev/null
+++ b/inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_mfd.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_tpfa.xml b/inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_tpfa.xml
new file mode 100644
index 00000000000..a7038800200
--- /dev/null
+++ b/inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_tpfa.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cmake/GeosxOptions.cmake b/src/cmake/GeosxOptions.cmake
index fe3adabcc4b..ebc45c3e929 100644
--- a/src/cmake/GeosxOptions.cmake
+++ b/src/cmake/GeosxOptions.cmake
@@ -147,7 +147,7 @@ message( "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}" )
blt_append_custom_compiler_flag( FLAGS_VAR CMAKE_CXX_FLAGS DEFAULT "${OpenMP_CXX_FLAGS}" )
blt_append_custom_compiler_flag( FLAGS_VAR CMAKE_CXX_FLAGS
GNU "-Wpedantic -pedantic-errors -Wshadow -Wfloat-equal -Wcast-align -Wcast-qual"
- CLANG "-Wpedantic -pedantic-errors -Wshadow -Wfloat-equal -Wno-cast-align -Wcast-qual"
+ CLANG "-Wpedantic -pedantic-errors -Wshadow -Wfloat-equal -Wno-cast-align -Wcast-qual -Wno-shorten-64-to-32"
)
blt_append_custom_compiler_flag( FLAGS_VAR CMAKE_CXX_FLAGS_DEBUG
diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/CompositionalMultiphaseHybridFVM.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/CompositionalMultiphaseHybridFVM.hpp
index 5f1b8a87f98..7081d021e9e 100644
--- a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/CompositionalMultiphaseHybridFVM.hpp
+++ b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/CompositionalMultiphaseHybridFVM.hpp
@@ -81,10 +81,12 @@ class CompositionalMultiphaseHybridFVM : public MGRStrategyBase< 3 >
// Level 1
m_levelFRelaxType[1] = MGRFRelaxationType::none;
- m_levelInterpType[1] = MGRInterpolationType::jacobi;
+ m_levelFRelaxIters[1] = 1;
+ m_levelInterpType[1] = MGRInterpolationType::injection;
m_levelRestrictType[1] = MGRRestrictionType::blockColLumped; // True-IMPES
m_levelCoarseGridMethod[1] = MGRCoarseGridMethod::galerkin;
- m_levelGlobalSmootherType[1] = MGRGlobalSmootherType::none;
+ m_levelGlobalSmootherType[1] = MGRGlobalSmootherType::ilu0;
+ m_levelGlobalSmootherIters[1] = 1;
// Level 2
m_levelFRelaxType[2] = MGRFRelaxationType::jacobi;
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp
index f4a8d3c3ffd..f661eb86f38 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp
@@ -144,7 +144,8 @@ void CompositionalMultiphaseFVM::postInputInitialization()
FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName );
auto const & upwindingParams = fluxApprox.upwindingParams();
if( upwindingParams.upwindingScheme == UpwindingScheme::C1PPU ||
- upwindingParams.upwindingScheme == UpwindingScheme::IHU )
+ upwindingParams.upwindingScheme == UpwindingScheme::IHU ||
+ upwindingParams.upwindingScheme == UpwindingScheme::HU2PH )
{
GEOS_ERROR( GEOS_FMT( "{}: {} is not available for {}",
getDataContext(),
@@ -273,7 +274,9 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt,
kernelFlags.set( KernelFlags::C1PPU );
else if( upwindingParams.upwindingScheme == UpwindingScheme::IHU )
kernelFlags.set( KernelFlags::IHU );
-
+ else if( upwindingParams.upwindingScheme == UpwindingScheme::HU2PH )
+ kernelFlags.set( KernelFlags::HU2PH );
+
string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() );
fluxApprox.forAllStencils( mesh, [&] ( auto & stencil )
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp
index 7f1998b66a1..229f276f6b5 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp
@@ -83,8 +83,6 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies )
// Register the face data for temperature
faceManager.registerField< flow::faceTemperature >( getName() );
-
-
// Register the bc face data for pressure
faceManager.registerField< flow::bcPressure >( getName() );
@@ -106,11 +104,11 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies )
reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents );
// Register boundary face indicator (1 for boundary faces with Dirichlet BCs, 0 for interior)
- // Used to skip flux continuity constraints for boundary faces
faceManager.registerField< flow::isBoundaryFace >( getName() );
- // auxiliary data for the buoyancy coefficient
- faceManager.registerField< flow::mimGravityCoefficient >( getName() );
+ // precomputed mimetic gravity-driven trans coefficient on faces
+ faceManager.registerField< flow::mimeticTransGgradZ >( getName() );
+
} );
}
@@ -241,67 +239,57 @@ void CompositionalMultiphaseHybridFVM::precomputeData( MeshLevel & mesh, string_
{
FlowSolverBase::precomputeData( mesh, regionNames );
- NodeManager const & nodeManager = mesh.getNodeManager();
- FaceManager & faceManager = mesh.getFaceManager();
-
- array1d< RAJA::ReduceSum< serialReduce, real64 > > mimFaceGravCoefNumerator;
- array1d< RAJA::ReduceSum< serialReduce, real64 > > mimFaceGravCoefDenominator;
- mimFaceGravCoefNumerator.resize( faceManager.size() );
- mimFaceGravCoefDenominator.resize( faceManager.size() );
-
- // node data
-
- arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition = nodeManager.referencePosition();
-
- // face data
-
- arrayView1d< real64 const > const & transMultiplier =
- faceManager.getField< flow::transMultiplier >();
-
- arrayView1d< real64 > const mimFaceGravCoef =
- faceManager.getField< flow::mimGravityCoefficient >();
-
- ArrayOfArraysView< localIndex const > const & faceToNodes = faceManager.nodeList().toViewConst();
-
- real64 const lengthTolerance = m_lengthTolerance;
-
- mesh.getElemManager().forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const,
- CellElementSubRegion & subRegion )
+ // Pre-compute and initialize face mimeticTransGgradZ once (only for HybridMimetic discretization)
{
- arrayView2d< real64 const > const & elemCenter =
- subRegion.template getReference< array2d< real64 > >( CellElementSubRegion::viewKeyStruct::elementCenterString() );
- string const & permModelName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() );
- arrayView3d< real64 const > const & elemPerm =
- getConstitutiveModel< PermeabilityBase >( subRegion, permModelName ).permeability();
- arrayView1d< real64 const > const elemGravCoef =
- subRegion.template getReference< array1d< real64 > >( flow::gravityCoefficient::key() );
- arrayView1d< real64 const > const & elemVolume = subRegion.getElementVolume();
- arrayView2d< localIndex const > const & elemToFaces = subRegion.faceList();
-
- // here we precompute some quantities (mimFaceFracCoef) used in the FluxKernel to assemble the one-sided gravity term in the transport
- // scheme
- // This one-sided gravity term is currently always treated with TPFA, as in MRST.
- // In the future, I will change that (here and in the FluxKernel) to have a consistent inner product for the gravity term as well
- compositionalMultiphaseHybridFVMKernels::
- simpleKernelLaunchSelector< PrecomputeKernel,
- mimeticInnerProduct::TPFAInnerProduct >( subRegion.numFacesPerElement(),
- subRegion.size(),
- faceManager.size(),
- nodePosition,
- faceToNodes,
- elemCenter,
- elemVolume,
- elemPerm,
- elemGravCoef,
- elemToFaces,
- transMultiplier,
- lengthTolerance,
- mimFaceGravCoefNumerator.toView(),
- mimFaceGravCoefDenominator.toView(),
- mimFaceGravCoef );
+ DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" );
+ NumericalMethodsManager const & nm = domain.getNumericalMethodManager();
+ FiniteVolumeManager const & fvManager = nm.getFiniteVolumeManager();
- } );
+ HybridMimeticDiscretization const & hm = fvManager.getHybridMimeticDiscretization( m_discretizationName );
+ mimeticInnerProduct::MimeticInnerProductBase const & ip = hm.getReference< mimeticInnerProduct::MimeticInnerProductBase >( HybridMimeticDiscretization::viewKeyStruct::innerProductString() );
+ real64 const lengthTolerance = domain.getMeshBody( 0 ).getGlobalLengthScale() * m_lengthTolerance;
+ forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, string_array const & regionNames )
+ {
+ FaceManager & faceManager = mesh.getFaceManager();
+ // Temporary accumulators
+ array1d< real64 > invSum( faceManager.size() ); invSum.setValues< parallelDevicePolicy<> >( 0.0 );
+ array1d< integer > count( faceManager.size() ); count.setValues< parallelDevicePolicy<> >( 0 );
+
+ NodeManager const & nodeManager = mesh.getNodeManager();
+ mesh.getElemManager().forElementSubRegionsComplete< CellElementSubRegion >( regionNames,
+ [&]( localIndex const, localIndex const er, localIndex const esr, ElementRegionBase const &,
+ CellElementSubRegion const & subRegion )
+ {
+ GEOS_UNUSED_VAR( er );
+ GEOS_UNUSED_VAR( esr );
+ string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() );
+ PermeabilityBase const & permeability = getConstitutiveModel< PermeabilityBase >( subRegion, permName );
+ PrecomputeMimeticTransGgradZKernel::createAndLaunch< parallelDevicePolicy<> >( ip,
+ nodeManager,
+ faceManager,
+ subRegion,
+ permeability,
+ lengthTolerance,
+ invSum.toView(),
+ count.toView() );
+ } );
+
+ // Reduce to effective value per face and write to field
+ arrayView1d< real64 > mimeticTransGgradZ = faceManager.getField< flow::mimeticTransGgradZ >();
+ arrayView1d< integer const > ghost = faceManager.ghostRank();
+ forAll< parallelDevicePolicy<> >( faceManager.size(), [=] GEOS_HOST_DEVICE ( localIndex const kf )
+ {
+ if( ghost[kf] >= 0 )
+ {
+ return;
+ }
+ real64 const s = invSum[kf];
+ integer const c = count[kf];
+ mimeticTransGgradZ[kf] = (c > 0 && s > 0.0) ? static_cast< real64 >( c ) / s : 0.0;
+ } );
+ } );
+ }
}
void CompositionalMultiphaseHybridFVM::implicitStepSetup( real64 const & time_n,
@@ -417,8 +405,8 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt,
// get the face-centered depth
arrayView1d< real64 const > const & faceGravCoef =
faceManager.getField< flow::gravityCoefficient >();
- arrayView1d< real64 const > const & mimFaceGravCoef =
- faceManager.getField< flow::mimGravityCoefficient >();
+ arrayView1d< real64 const > const & mimeticTransGgradZ =
+ faceManager.getField< flow::mimeticTransGgradZ >();
// get the face-centered transMultiplier
arrayView1d< real64 const > const & transMultiplier =
@@ -468,7 +456,7 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt,
isBoundaryFaceView,
facePres,
faceGravCoef,
- mimFaceGravCoef,
+ mimeticTransGgradZ,
transMultiplier,
compFlowAccessors.get( flow::phaseMobility{} ),
compFlowAccessors.get( flow::dPhaseMobility{} ),
@@ -809,8 +797,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n
} );
}
- // CRITICAL: Move the SAME array views that were just modified back to device memory
- // Don't get new views - use the views that evaluateBCFaceProperties actually modified
// evaluateBCFaceProperties uses serialPolicy (host), DirichletFluxKernel uses parallelDevicePolicy (device)
facePhaseMob.move( parallelDeviceMemorySpace, false );
facePhaseMassDens.move( parallelDeviceMemorySpace, false );
@@ -980,12 +966,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n
// Mathematical procedure to enforce prescribed value in Ax = b:
// 1. For row i: Zero all entries except diagonal, set A[i,i] = 1, set b[i] = x_spec
// 2. For all other rows k: subtract A[k,i] * x_spec from b[k], then set A[k,i] = 0
- //
- // Note: Step 2 (removing column influence) should ideally be done, but in practice
- // for boundary face DOFs in hybrid FVM, the column entries from interior faces to
- // boundary faces are typically zero or minimal because boundary faces don't strongly
- // couple to interior equations. The strong coupling is boundary->interior (via fluxes).
- // For exact enforcement in non-trivial cases, column zeroing would be needed.
if( localRow >= 0 && localRow < localMatrix.numRows() )
{
@@ -1009,7 +989,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n
// Set RHS to the prescribed boundary value (absolute value)
localRhs[localRow] = presFace[kf] - presFaceBC[kf];
}
-
} );
} );
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp
index 22f363f2c22..a8023ba1821 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp
@@ -185,13 +185,13 @@ DECLARE_FIELD( gravityCoefficient,
WRITE_AND_READ,
"Gravity coefficient (dot product of gravity acceleration by gravity vector)" );
-DECLARE_FIELD( mimGravityCoefficient,
- "mimGravityCoefficient",
+DECLARE_FIELD( mimeticTransGgradZ,
+ "mimeticTransGgradZ",
array1d< real64 >,
0,
NOPLOT,
WRITE_AND_READ,
- "Mimetic gravity coefficient" );
+ "Consistent mimetic operator applied to g grad(z) (harmonic average of element contributions)" );
DECLARE_FIELD( macroElementIndex,
"macroElementIndex",
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp
index d713a3d0a7e..9d35d7c7e76 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp
@@ -31,10 +31,12 @@
#include "mesh/ElementRegionManager.hpp"
#include "mesh/ObjectManagerBase.hpp"
#include "physicsSolvers/PhysicsSolverBaseKernels.hpp"
+#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp"
#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp"
#include "physicsSolvers/fluidFlow/StencilAccessors.hpp"
#include "physicsSolvers/fluidFlow/kernels/compositional/PropertyKernelBase.hpp"
#include "physicsSolvers/fluidFlow/kernels/compositional/KernelLaunchSelectors.hpp"
+#include "finiteVolume/MimeticInnerProductDispatch.hpp"
namespace geos
@@ -43,6 +45,66 @@ namespace geos
namespace compositionalMultiphaseHybridFVMKernels
{
+//namespace internal
+/******************************** Kernel switches ********************************/
+
+namespace internal
+{
+
+template< typename T, typename LAMBDA >
+void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda )
+{
+ static_assert( std::is_integral< T >::value, "KernelLaunchSelectorFaceSwitch: type should be integral" );
+
+ switch( value )
+ {
+ case 4:
+ {
+ return lambda( std::integral_constant< int, 4 >{} );
+ }
+ case 5:
+ {
+ return lambda( std::integral_constant< int, 5 >{} );
+ }
+ case 6:
+ {
+ return lambda( std::integral_constant< int, 6 >{} );
+ }
+ case 7:
+ {
+ return lambda( std::integral_constant< int, 7 >{} );
+ }
+ case 8:
+ {
+ return lambda( std::integral_constant< int, 8 >{} );
+ }
+ case 9:
+ {
+ return lambda( std::integral_constant< int, 9 >{} );
+ }
+ case 10:
+ {
+ return lambda( std::integral_constant< int, 10 >{} );
+ }
+ case 11:
+ {
+ return lambda( std::integral_constant< int, 11 >{} );
+ }
+ case 12:
+ {
+ return lambda( std::integral_constant< int, 12 >{} );
+ }
+ case 13:
+ {
+ return lambda( std::integral_constant< int, 13 >{} );
+ }
+ default:
+ GEOS_ERROR( "Unknown numFacesInElem value: " << value );
+ }
+}
+
+} // namespace internal
+
// struct to specify local and neighbor derivatives
struct Pos
{
@@ -320,7 +382,7 @@ struct AssemblerKernelHelper
* @param[in] dPhaseMob the derivatives of the phase mobilities in the element
* @param[in] dCompFrac_dCompDens the derivatives of the component fractions wrt component density
* @param[in] phaseCompFrac the phase component fractions in the domain
- * @param[in] dPhaseCompFrac the derivatives of the phase component fractions wrt pressure and component fractions
+ * @param[in] dPhaseCompFrac the derivatives of the phase component fractions in the domain wrt pressure and component fractions
* @param[in] elemDofNumber the dof numbers of the element in the domain
* @param[in] oneSidedVolFlux the volumetric fluxes at this element's faces
* @param[in] dOneSidedVolFlux_dPres the derivatives of the vol fluxes wrt to this element's cell centered pressure
@@ -341,7 +403,8 @@ struct AssemblerKernelHelper
SortedArrayView< localIndex const > const & regionFilter,
arrayView1d< globalIndex const > const & faceDofNumber,
arrayView1d< integer const > const & isBoundaryFace,
- arrayView1d< real64 const > const & mimFaceGravCoef,
+ arrayView1d< real64 const > const & mimeticTransGgradZ,
+ arrayView1d< real64 const > const & faceGravCoef,
arraySlice1d< localIndex const > const & elemToFaces,
real64 const & elemGravCoef,
integer const useTotalMassEquation,
@@ -355,7 +418,7 @@ struct AssemblerKernelHelper
ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > > const & phaseCompFrac,
ElementViewConst< arrayView5d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac,
ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber,
- arraySlice2d< real64 const > const & transMatrixGrav,
+ arraySlice2d< real64 const > const & transMatrix,
real64 const (&oneSidedVolFlux)[ NF ],
real64 const (&dOneSidedVolFlux_dPres)[ NF ],
real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ],
@@ -526,7 +589,7 @@ struct AssemblerKernel
arrayView1d< integer const > const & isBoundaryFace,
arrayView1d< real64 const > const & facePres,
arrayView1d< real64 const > const & faceGravCoef,
- arrayView1d< real64 const > const & mimFaceGravCoef,
+ arrayView1d< real64 const > const & mimeticTransGgradZ,
arraySlice1d< localIndex const > const & elemToFaces,
real64 const & elemPres,
real64 const & elemGravCoef,
@@ -545,7 +608,6 @@ struct AssemblerKernel
globalIndex const rankOffset,
real64 const & dt,
arraySlice2d< real64 const > const & transMatrix,
- arraySlice2d< real64 const > const & transMatrixGrav,
CRSMatrixView< real64, globalIndex const > const & localMatrix,
arrayView1d< real64 > const & localRhs );
};
@@ -708,6 +770,7 @@ struct FluxKernel
* @param[in] rankOffset the offset of this rank
* @param[in] lengthTolerance tolerance used in the transmissibility matrix computation
* @param[in] dt time step size
+ * @param[in] transMatrix the transmissibility matrix in this element
* @param[inout] matrix the system matrix
* @param[inout] rhs the system right-hand side vector
*/
@@ -727,7 +790,7 @@ struct FluxKernel
arrayView1d< integer const > const & isBoundaryFace,
arrayView1d< real64 const > const & facePres,
arrayView1d< real64 const > const & faceGravCoef,
- arrayView1d< real64 const > const & mimFaceGravCoef,
+ arrayView1d< real64 const > const & mimeticTransGgradZ,
arrayView1d< real64 const > const & transMultiplier,
ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob,
ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob,
@@ -1174,33 +1237,32 @@ struct SolutionCheckKernel
};
-/******************************** PrecomputeKernel ********************************/
+/******************************** PrecomputeMimeticTransGgradZKernel ********************************/
-struct PrecomputeKernel
+struct PrecomputeMimeticTransGgradZKernel
{
template< typename IP_TYPE, integer NF >
static void
launch( localIndex const subRegionSize,
- localIndex const faceManagerSize,
arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition,
ArrayOfArraysView< localIndex const > const & faceToNodes,
arrayView2d< real64 const > const & elemCenter,
arrayView1d< real64 const > const & elemVolume,
arrayView3d< real64 const > const & elemPerm,
arrayView1d< real64 const > const & elemGravCoef,
+ arrayView1d< real64 const > const & faceGravCoef,
arrayView2d< localIndex const > const & elemToFaces,
arrayView1d< real64 const > const & transMultiplier,
real64 const & lengthTolerance,
- arrayView1d< RAJA::ReduceSum< serialReduce, real64 > > const & mimFaceGravCoefNumerator,
- arrayView1d< RAJA::ReduceSum< serialReduce, real64 > > const & mimFaceGravCoefDenominator,
- arrayView1d< real64 > const & mimFaceGravCoef )
+ arrayView1d< real64 > const & faceInvSum,
+ arrayView1d< integer > const & faceCount )
{
- forAll< serialPolicy >( subRegionSize, [=] ( localIndex const ei )
+ forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const ei )
{
- stackArray2d< real64, NF *NF > transMatrix( NF, NF );
+ stackArray2d< real64, NF * NF > transMatrix( NF, NF );
- real64 const perm[ 3 ] = { elemPerm[ei][0][0], elemPerm[ei][0][1], elemPerm[ei][0][2] };
+ real64 const perm[3] = { elemPerm[ei][0][0], elemPerm[ei][0][1], elemPerm[ei][0][2] };
IP_TYPE::template compute< NF >( nodePosition,
transMultiplier,
@@ -1212,19 +1274,65 @@ struct PrecomputeKernel
lengthTolerance,
transMatrix );
- for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc )
+ real64 const ccGravCoef = elemGravCoef[ei];
+ for( integer i = 0; i < NF; ++i )
{
- mimFaceGravCoefNumerator[elemToFaces[ei][ifaceLoc]] += elemGravCoef[ei] * transMatrix[ifaceLoc][ifaceLoc];
- mimFaceGravCoefDenominator[elemToFaces[ei][ifaceLoc]] += transMatrix[ifaceLoc][ifaceLoc];
+ localIndex const kf = elemToFaces[ei][i];
+
+ real64 T_g_delta_z = 0.0;
+ for( integer j = 0; j < NF; ++j )
+ {
+ real64 const fGravCoef = faceGravCoef[elemToFaces[ei][j]];
+ real64 const gravCoefDif = ccGravCoef - fGravCoef;
+ T_g_delta_z += transMatrix[i][j] * gravCoefDif;
+ }
+ RAJA::atomicAdd( parallelDeviceAtomic{}, &faceInvSum[kf], 1.0 / LvArray::math::abs( T_g_delta_z ) );
+ RAJA::atomicAdd( parallelDeviceAtomic{}, &faceCount[kf], 1 );
}
} );
+ }
- forAll< serialPolicy >( faceManagerSize, [=] ( localIndex const iface )
+ template< typename POLICY >
+ static void
+ createAndLaunch( mimeticInnerProduct::MimeticInnerProductBase const & ip,
+ NodeManager const & nodeManager,
+ FaceManager const & faceManager,
+ CellElementSubRegion const & subRegion,
+ constitutive::PermeabilityBase const & permeability,
+ real64 const lengthTolerance,
+ arrayView1d< real64 > const & faceInvSum,
+ arrayView1d< integer > const & faceCount )
+ {
+ arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition = nodeManager.referencePosition();
+ ArrayOfArraysView< localIndex const > const & faceToNodes = faceManager.nodeList().toViewConst();
+ arrayView1d< real64 const > const & transMultiplier = faceManager.getField< fields::flow::transMultiplier >();
+ arrayView1d< real64 const > const & faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >();
+
+ arrayView2d< real64 const > const & elemCenter = subRegion.getElementCenter();
+ arrayView1d< real64 const > const & elemVolume = subRegion.getElementVolume();
+ arrayView3d< real64 const > const & elemPerm = permeability.permeability();
+ arrayView1d< real64 const > const & elemGravCoef = subRegion.getField< fields::flow::gravityCoefficient >();
+ arrayView2d< localIndex const > const & elemToFaces = subRegion.faceList();
+
+ mimeticInnerProductDispatch( ip, [&]( auto const & innerProduct )
{
- if( !isZero( mimFaceGravCoefDenominator[iface].get() ) )
+ using IP_TYPE = std::remove_const_t< TYPEOFREF( innerProduct ) >;
+ internal::kernelLaunchSelectorFaceSwitch( subRegion.numFacesPerElement(), [&]( auto NF )
{
- mimFaceGravCoef[iface] = mimFaceGravCoefNumerator[iface].get() / mimFaceGravCoefDenominator[iface].get();
- }
+ PrecomputeMimeticTransGgradZKernel::launch< IP_TYPE, NF() >( subRegion.size(),
+ nodePosition,
+ faceToNodes,
+ elemCenter,
+ elemVolume,
+ elemPerm,
+ elemGravCoef,
+ faceGravCoef,
+ elemToFaces,
+ transMultiplier,
+ lengthTolerance,
+ faceInvSum,
+ faceCount );
+ } );
} );
}
};
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp
index 64f8d7f0d58..3075c22a3e9 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp
@@ -619,7 +619,8 @@ AssemblerKernelHelper::
SortedArrayView< localIndex const > const & regionFilter,
arrayView1d< globalIndex const > const & faceDofNumber,
arrayView1d< integer const > const & isBoundaryFace,
- arrayView1d< real64 const > const & mimFaceGravCoef,
+ arrayView1d< real64 const > const & mimeticTransGgradZ,
+ arrayView1d< real64 const > const & faceGravCoef,
arraySlice1d< localIndex const > const & elemToFaces,
real64 const & elemGravCoef,
integer const useTotalMassEquation,
@@ -633,7 +634,7 @@ AssemblerKernelHelper::
ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > > const & phaseCompFrac,
ElementViewConst< arrayView5d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac,
ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber,
- arraySlice2d< real64 const > const & transMatrixGrav,
+ arraySlice2d< real64 const > const & transMatrix,
real64 const (&oneSidedVolFlux)[ NF ],
real64 const (&dOneSidedVolFlux_dPres)[ NF ],
real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ],
@@ -704,7 +705,6 @@ AssemblerKernelHelper::
localIndex const neighborDofNumber = elemDofNumber[neighborIds[0]][neighborIds[1]][neighborIds[2]];
// 2) *************** Assemble viscous terms ******************
-
// 2.a) Compute the upwinded x_{c, \ell} \rho_{\ell} \frac{\lambda_{\ell}}{\lambda_T} for each phase at this face
UpwindingHelper::upwindViscousCoefficient< NC, NP >( localIds,
neighborIds,
@@ -740,11 +740,23 @@ AssemblerKernelHelper::
dDivMassFluxes_dFaceVars,
dofColIndicesElemVars );
-
// 3) *************** Assemble buoyancy terms ******************
- real64 const transGravCoef = (localIds[0] != neighborIds[0] || localIds[1] != neighborIds[1] || localIds[2] != neighborIds[2])
- * transMatrixGrav[ifaceLoc][ifaceLoc] * (elemGravCoef - mimFaceGravCoef[elemToFaces[ifaceLoc]]);
+ // The sign of gFlux_i determines direction for buoyancy w.r.t the consistent inner product.
+ real64 gFlux_i = 0.0;
+ for( integer jfaceLoc=0; jfaceLoc 0.0 ) - integer( gFlux_i < 0.0 );
+
+ // Buoyancy transmissibility applied on ifaceLoc face. The boolean comparison acts
+ // as a 0/1 mask that disables the buoyancy flux for domain boundaries.
+ real64 const transGravCoef = sign * (localIds[0] != neighborIds[0] || localIds[1] != neighborIds[1] || localIds[2] != neighborIds[2]) * mimeticTransGgradZ[elemToFaces[ifaceLoc]];
// 3.a) Compute the upwinded x_{c, \ell} \rho_{\ell} \frac{\lambda_{\ell}\lambda_m}{\lambda_T}
// and (\rho_{\ell} - \rho_m) g \Delta z for each phase at this face
@@ -1108,7 +1120,7 @@ AssemblerKernel::
arrayView1d< integer const > const & isBoundaryFace,
arrayView1d< real64 const > const & facePres,
arrayView1d< real64 const > const & faceGravCoef,
- arrayView1d< real64 const > const & mimFaceGravCoef,
+ arrayView1d< real64 const > const & mimeticTransGgradZ,
arraySlice1d< localIndex const > const & elemToFaces,
real64 const & elemPres,
real64 const & elemGravCoef,
@@ -1127,7 +1139,6 @@ AssemblerKernel::
globalIndex const rankOffset,
real64 const & dt,
arraySlice2d< real64 const > const & transMatrix,
- arraySlice2d< real64 const > const & transMatrixGrav,
CRSMatrixView< real64, globalIndex const > const & localMatrix,
arrayView1d< real64 > const & localRhs )
{
@@ -1184,7 +1195,8 @@ AssemblerKernel::
regionFilter,
faceDofNumber,
isBoundaryFace,
- mimFaceGravCoef,
+ mimeticTransGgradZ,
+ faceGravCoef,
elemToFaces,
elemGravCoef,
useTotalMassEquation,
@@ -1198,7 +1210,7 @@ AssemblerKernel::
phaseCompFrac,
dPhaseCompFrac,
elemDofNumber,
- transMatrixGrav,
+ transMatrix,
oneSidedVolFlux,
dOneSidedVolFlux_dPres,
dOneSidedVolFlux_dFacePres,
@@ -1243,7 +1255,7 @@ FluxKernel::
arrayView1d< integer const > const & isBoundaryFace,
arrayView1d< real64 const > const & facePres,
arrayView1d< real64 const > const & faceGravCoef,
- arrayView1d< real64 const > const & mimFaceGravCoef,
+ arrayView1d< real64 const > const & mimeticTransGgradZ,
arrayView1d< real64 const > const & transMultiplier,
ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob,
ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob,
@@ -1293,8 +1305,6 @@ FluxKernel::
{
// transmissibility matrix
stackArray2d< real64, NF *NF > transMatrix( NF, NF );
- stackArray2d< real64, NF *NF > transMatrixGrav( NF, NF );
-
real64 const perm[ 3 ] = { elemPerm[ei][0][0], elemPerm[ei][0][1], elemPerm[ei][0][2] };
// recompute the local transmissibility matrix at each iteration
@@ -1309,19 +1319,6 @@ FluxKernel::
lengthTolerance,
transMatrix );
- // currently the gravity term in the transport scheme is treated as in MRST, that is, always with TPFA
- // this is why below we have to recompute the TPFA transmissibility in addition to the transmissibility matrix above
- // TODO: treat the gravity term with a consistent inner product
- mimeticInnerProduct::TPFAInnerProduct::compute< NF >( nodePosition,
- transMultiplier,
- faceToNodes,
- elemToFaces[ei],
- elemCenter[ei],
- elemVolume[ei],
- perm,
- lengthTolerance,
- transMatrixGrav );
-
// perform flux assembly in this element
compositionalMultiphaseHybridFVMKernels::AssemblerKernel::compute< NF, NC, NP >( er, esr, ei,
regionFilter,
@@ -1333,7 +1330,7 @@ FluxKernel::
isBoundaryFace,
facePres,
faceGravCoef,
- mimFaceGravCoef,
+ mimeticTransGgradZ,
elemToFaces[ei],
elemPres[ei],
elemGravCoef[ei],
@@ -1352,7 +1349,6 @@ FluxKernel::
rankOffset,
dt,
transMatrix,
- transMatrixGrav,
localMatrix,
localRhs );
} );