From f57757a05d402b1d0d5ca822a83a5e3a293e7569 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 11 Aug 2025 22:59:24 -0700 Subject: [PATCH 01/91] fix: Missing face boundary condition support wip: completing implementation of face BC Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 100 +++++++++++++++++- .../CompositionalMultiphaseHybridFVM.hpp | 17 +++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 6f8955ad23b..80cb42e199c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -24,6 +24,7 @@ #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" +#include "fieldSpecification/LogLevelsInfo.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" #include "finiteVolume/HybridMimeticDiscretization.hpp" #include "finiteVolume/MimeticInnerProductDispatch.hpp" @@ -572,7 +573,104 @@ void CompositionalMultiphaseHybridFVM::applyBoundaryConditions( real64 const tim CompositionalMultiphaseBase::applyBoundaryConditions( time_n, dt, domain, dofManager, localMatrix, localRhs ); - // TODO: implement face boundary conditions here + if( !m_keepVariablesConstantDuringInitStep ) + { + applyFaceDirichletBC( time_n, dt, dofManager, domain, localMatrix, localRhs ); + } +} + +namespace +{ +char const faceBcLogMessage[] = + "CompositionalMultiphaseHybridFVM {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " + "\nThe total number of target faces (including ghost faces) is {}. " + "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; +} + +void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); + + this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & ) + { + FaceManager & faceManager = mesh.getFaceManager(); + + arrayView1d< real64 const > const presFace = + faceManager.getField< flow::facePressure >(); + arrayView1d< globalIndex const > const faceDofNumber = + faceManager.getReference< array1d< globalIndex > >( faceDofKey ); + arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); + + globalIndex const rankOffset = dofManager.rankOffset(); + + fsManager.apply< FaceManager >( time_n + dt, + mesh, + flow::pressure::key(), + [&] ( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + FaceManager & targetGroup, + string const & ) + { + + // report at the first nonlinear iteration + if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + globalIndex const numTargetFaces = MpiWrapper::sum< globalIndex >( targetSet.size() ); + GEOS_LOG_LEVEL_RANK_0_ON_GROUP( logInfo::FaceBoundaryCondition, + GEOS_FMT( faceBcLogMessage, + this->getName(), time_n+dt, fs.getCatalogName(), fs.getName(), + setName, targetGroup.getName(), numTargetFaces ), + fs ); + } + + // Using the field specification functions to apply the boundary conditions to the system + fs.applyFieldValue< FieldSpecificationEqual, + parallelDevicePolicy<> >( targetSet, + time_n + dt, + targetGroup, + flow::facePressure::key() ); + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + + localIndex const kf = targetSet[a]; + if( faceGhostRank[kf] >= 0 ) + { + return; + } + + // Get the dof number of this face + globalIndex const dofIndex = faceDofNumber[kf]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // Apply field value to the lhs and rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + presFace[kf], + presFace[kf] ); + localRhs[localRow] = rhsValue; + } ); + + } ); + + } ); + } void CompositionalMultiphaseHybridFVM::applyAquiferBC( real64 const time, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp index e0be3309446..fc4c01c981f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp @@ -168,6 +168,23 @@ class CompositionalMultiphaseHybridFVM : public CompositionalMultiphaseBase virtual void initializePreSubGroups() override; + /** + * @brief Function to perform the application of Dirichlet BC data on faces + * @param[in] time_n current time + * @param[in] dt time step + * @param[in] dofManager degree-of-freedom manager associated with the linear system + * @param[in] domain the domain + * @param[inout] localMatrix the system matrix + * @param[inout] localRhs the system right-hand side vector + */ + void + applyFaceDirichletBC( real64 const time_n, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ); + protected: /// precompute the minGravityCoefficient for the buoyancy term From 9d88fe75045e085f5c3f104e88911a24d2d55082 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 11 Aug 2025 23:56:12 -0700 Subject: [PATCH 02/91] Update src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 80cb42e199c..b880c326281 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -24,7 +24,6 @@ #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" -#include "fieldSpecification/LogLevelsInfo.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" #include "finiteVolume/HybridMimeticDiscretization.hpp" #include "finiteVolume/MimeticInnerProductDispatch.hpp" From f627f659981d44e8f9734b4509b9af7dc25f707f Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 12 Aug 2025 00:05:56 -0700 Subject: [PATCH 03/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index b880c326281..568fb0de933 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -25,6 +25,7 @@ #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" +#include "fieldSpecification/LogLevelsInfo.hpp" #include "finiteVolume/HybridMimeticDiscretization.hpp" #include "finiteVolume/MimeticInnerProductDispatch.hpp" #include "mesh/mpiCommunications/CommunicationTools.hpp" From 60ae20529aed6dbd5418e799dd97ff8a970c01ef Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 14 Aug 2025 11:47:21 -0700 Subject: [PATCH 04/91] fix: Lambda capture 'mat' is not used --- .../linearAlgebra/interfaces/trilinos/EpetraMatrix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/linearAlgebra/interfaces/trilinos/EpetraMatrix.cpp b/src/coreComponents/linearAlgebra/interfaces/trilinos/EpetraMatrix.cpp index 77f2d27bc9a..b3bdf0ba47c 100644 --- a/src/coreComponents/linearAlgebra/interfaces/trilinos/EpetraMatrix.cpp +++ b/src/coreComponents/linearAlgebra/interfaces/trilinos/EpetraMatrix.cpp @@ -589,7 +589,7 @@ void EpetraMatrix::computeScalingVector( EpetraVector & scaling ) const scaling.create( numLocalRows(), comm() ); Epetra_Vector & vec = scaling.unwrapped(); real64 * const values = vec.Values(); - forAll< parallelHostPolicy >( vec.MyLength(), [=, &mat, &weights, &dofLabels]( int const localRow ) + forAll< parallelHostPolicy >( vec.MyLength(), [=, &weights, &dofLabels]( int const localRow ) { values[localRow] = weights[dofLabels[localRow]]; } ); From bb1e825ec8e454923dc9a81cb4a424d85db51e67 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sat, 11 Oct 2025 22:54:39 -0700 Subject: [PATCH 05/91] wip: consistent T g grad(z) --- .../CompositionalMultiphaseHybridFVM.cpp | 144 ++++++++---------- .../fluidFlow/FlowSolverBaseFields.hpp | 8 + ...ompositionalMultiphaseHybridFVMKernels.hpp | 99 +++++++++--- 3 files changed, 144 insertions(+), 107 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index cb2a68222f7..35d7bb15419 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -25,7 +25,6 @@ #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" -#include "fieldSpecification/LogLevelsInfo.hpp" #include "finiteVolume/HybridMimeticDiscretization.hpp" #include "finiteVolume/MimeticInnerProductDispatch.hpp" #include "mesh/mpiCommunications/CommunicationTools.hpp" @@ -76,6 +75,13 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) // auxiliary data for the buoyancy coefficient faceManager.registerField< flow::mimGravityCoefficient >( getName() ); + + // precomputed mimetic gravity-driven trans coefficient on faces + faceManager.registerField< flow::mimeticTransGgradZ >( getName() ); + + // Register the bc face data + faceManager.registerField< flow::bcPressure >( getName() ); + } ); } @@ -165,67 +171,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(); + if( !fvManager.hasGroup< HybridMimeticDiscretization >( m_discretizationName ) ) + { + return; // Not using hybrid mimetic discretization; nothing to precompute + } + 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, @@ -577,15 +573,6 @@ void CompositionalMultiphaseHybridFVM::applyBoundaryConditions( real64 const tim } } -namespace -{ -char const faceBcLogMessage[] = - "CompositionalMultiphaseHybridFVM {}: at time {}s, " - "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " - "\nThe total number of target faces (including ghost faces) is {}. " - "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; -} - void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n, real64 const dt, DofManager const & dofManager, @@ -597,7 +584,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); + string const faceDofKey = dofManager.getKey( flow::facePressure::key() ); this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, @@ -607,6 +594,8 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView1d< real64 const > const presFace = faceManager.getField< flow::facePressure >(); + arrayView1d< real64 const > const presFaceBC = + faceManager.getField< flow::bcPressure >(); arrayView1d< globalIndex const > const faceDofNumber = faceManager.getReference< array1d< globalIndex > >( faceDofKey ); arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); @@ -615,7 +604,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n fsManager.apply< FaceManager >( time_n + dt, mesh, - flow::pressure::key(), + flow::bcPressure::key(), [&] ( FieldSpecificationBase const & fs, string const & setName, SortedArrayView< localIndex const > const & targetSet, @@ -623,23 +612,12 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n string const & ) { - // report at the first nonlinear iteration - if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - globalIndex const numTargetFaces = MpiWrapper::sum< globalIndex >( targetSet.size() ); - GEOS_LOG_LEVEL_RANK_0_ON_GROUP( logInfo::FaceBoundaryCondition, - GEOS_FMT( faceBcLogMessage, - this->getName(), time_n+dt, fs.getCatalogName(), fs.getName(), - setName, targetGroup.getName(), numTargetFaces ), - fs ); - } - // Using the field specification functions to apply the boundary conditions to the system fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, time_n + dt, targetGroup, - flow::facePressure::key() ); + flow::bcPressure::key() ); forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) { @@ -660,7 +638,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n rankOffset, localMatrix, rhsValue, - presFace[kf], + presFaceBC[kf], presFace[kf] ); localRhs[localRow] = rhsValue; } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp index 50e79137a4b..0a3fa8288a0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp @@ -225,6 +225,14 @@ DECLARE_FIELD( transMultiplier, WRITE_AND_READ, "Permeability transmissibility multipliers" ); +DECLARE_FIELD( mimeticTransGgradZ, + "mimeticTransGgradZ", + array1d< real64 >, + 0, + LEVEL_0, + WRITE_AND_READ, + "Face field mimeticTransGgradZ: consistent mimetic operator applied to the gravitational potential (harmonic average of element contributions)" ); + DECLARE_FIELD( pressureScalingFactor, "pressureScalingFactor", array1d< real64 >, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 2d7fcccc661..a104d74678b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -35,6 +35,7 @@ #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 @@ -312,7 +313,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 @@ -605,6 +606,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 */ @@ -875,7 +877,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa ResidualNormKernel( globalIndex const rankOffset, arrayView1d< real64 const > const & localResidual, arrayView1d< globalIndex const > const & dofNumber, - arrayView1d< localIndex const > const & ghostRank, + arrayView1d< integer const > const & ghostRank, SortedArrayView< localIndex const > const & regionFilter, FaceManager const & faceManager, CompFlowAccessors const & compFlowAccessors, @@ -1070,33 +1072,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, @@ -1108,19 +1109,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 ); + } ); } ); } }; @@ -1137,12 +1184,16 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) switch( value ) { - case 4: - { lambda( std::integral_constant< T, 4 >() ); return;} - case 5: - { lambda( std::integral_constant< T, 5 >() ); return;} - case 6: - { lambda( std::integral_constant< T, 6 >() ); return;} + case 4: lambda( std::integral_constant< T, 4 >() ); return; + case 5: lambda( std::integral_constant< T, 5 >() ); return; + case 6: lambda( std::integral_constant< T, 6 >() ); return; + case 7: lambda( std::integral_constant< T, 7 >() ); return; + case 8: lambda( std::integral_constant< T, 8 >() ); return; + case 9: lambda( std::integral_constant< T, 9 >() ); return; + case 10: lambda( std::integral_constant< T, 10 >() ); return; + case 11: lambda( std::integral_constant< T, 11 >() ); return; + case 12: lambda( std::integral_constant< T, 12 >() ); return; + case 13: lambda( std::integral_constant< T, 13 >() ); return; default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); } } From 633bfdf678308946f6bfa93fe9dd1f16ad69a52e Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sat, 11 Oct 2025 23:09:04 -0700 Subject: [PATCH 06/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- .../compositional/CompositionalMultiphaseHybridFVMKernels.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index a104d74678b..ff617f28381 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -1140,8 +1140,8 @@ struct PrecomputeMimeticTransGgradZKernel { 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 >(); + arrayView1d< real64 const > const & transMultiplier = faceManager.getField< flow::transMultiplier >(); + arrayView1d< real64 const > const & faceGravCoef = faceManager.getField< flow::gravityCoefficient >(); arrayView2d< real64 const > const & elemCenter = subRegion.getElementCenter(); arrayView1d< real64 const > const & elemVolume = subRegion.getElementVolume(); From a4961319090fbaafeda49f561a001dfb69dfeffa Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sat, 11 Oct 2025 23:18:48 -0700 Subject: [PATCH 07/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- ...ompositionalMultiphaseHybridFVMKernels.hpp | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index ff617f28381..0ad896048d3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -31,6 +31,7 @@ #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" @@ -44,6 +45,32 @@ namespace geos namespace compositionalMultiphaseHybridFVMKernels { +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: lambda( std::integral_constant< T, 4 >() ); return; + case 5: lambda( std::integral_constant< T, 5 >() ); return; + case 6: lambda( std::integral_constant< T, 6 >() ); return; + case 7: lambda( std::integral_constant< T, 7 >() ); return; + case 8: lambda( std::integral_constant< T, 8 >() ); return; + case 9: lambda( std::integral_constant< T, 9 >() ); return; + case 10: lambda( std::integral_constant< T, 10 >() ); return; + case 11: lambda( std::integral_constant< T, 11 >() ); return; + case 12: lambda( std::integral_constant< T, 12 >() ); return; + case 13: lambda( std::integral_constant< T, 13 >() ); return; + default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); + } +} + +} // namespace internal + // struct to specify local and neighbor derivatives struct Pos { @@ -1140,8 +1167,8 @@ struct PrecomputeMimeticTransGgradZKernel { 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< flow::transMultiplier >(); - arrayView1d< real64 const > const & faceGravCoef = faceManager.getField< flow::gravityCoefficient >(); + 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(); @@ -1174,32 +1201,6 @@ struct PrecomputeMimeticTransGgradZKernel /******************************** 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: lambda( std::integral_constant< T, 4 >() ); return; - case 5: lambda( std::integral_constant< T, 5 >() ); return; - case 6: lambda( std::integral_constant< T, 6 >() ); return; - case 7: lambda( std::integral_constant< T, 7 >() ); return; - case 8: lambda( std::integral_constant< T, 8 >() ); return; - case 9: lambda( std::integral_constant< T, 9 >() ); return; - case 10: lambda( std::integral_constant< T, 10 >() ); return; - case 11: lambda( std::integral_constant< T, 11 >() ); return; - case 12: lambda( std::integral_constant< T, 12 >() ); return; - case 13: lambda( std::integral_constant< T, 13 >() ); return; - default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); - } -} - -} // namespace internal - template< typename KERNELWRAPPER, typename INNER_PRODUCT, typename ... ARGS > void simpleKernelLaunchSelector( localIndex numFacesInElem, ARGS && ... args ) { From e8a2a17bc00f54747a4747d2e5863b9cf098fcb3 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 00:00:53 -0700 Subject: [PATCH 08/91] wip: ongoing work with consistent gravity terms --- .../CompositionalMultiphaseHybridFVM.cpp | 2 +- .../fluidFlow/FlowSolverBaseFields.hpp | 14 +++------- ...ompositionalMultiphaseHybridFVMKernels.cpp | 6 ++--- ...ompositionalMultiphaseHybridFVMKernels.hpp | 15 +++-------- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 26 +++---------------- 5 files changed, 13 insertions(+), 50 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 35d7bb15419..ce2c9b8ec73 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -584,7 +584,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - string const faceDofKey = dofManager.getKey( flow::facePressure::key() ); + string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp index 0a3fa8288a0..6901436620b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp @@ -177,13 +177,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", @@ -225,14 +225,6 @@ DECLARE_FIELD( transMultiplier, WRITE_AND_READ, "Permeability transmissibility multipliers" ); -DECLARE_FIELD( mimeticTransGgradZ, - "mimeticTransGgradZ", - array1d< real64 >, - 0, - LEVEL_0, - WRITE_AND_READ, - "Face field mimeticTransGgradZ: consistent mimetic operator applied to the gravitational potential (harmonic average of element contributions)" ); - DECLARE_FIELD( pressureScalingFactor, "pressureScalingFactor", array1d< real64 >, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp index 1d134b611ea..1a40022f615 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp @@ -616,7 +616,7 @@ AssemblerKernelHelper:: arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< real64 const > const & mimFaceGravCoef, + arrayView1d< real64 const > const & mimeticTransGgradZ, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -630,7 +630,6 @@ AssemblerKernelHelper:: ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, - arraySlice2d< real64 const > const & transMatrixGrav, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], @@ -731,8 +730,7 @@ AssemblerKernelHelper:: // 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]]); + real64 const transGravCoef = mimeticTransGgradZelemToFaces[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 diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 0ad896048d3..0e936852168 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -58,13 +58,6 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) case 4: lambda( std::integral_constant< T, 4 >() ); return; case 5: lambda( std::integral_constant< T, 5 >() ); return; case 6: lambda( std::integral_constant< T, 6 >() ); return; - case 7: lambda( std::integral_constant< T, 7 >() ); return; - case 8: lambda( std::integral_constant< T, 8 >() ); return; - case 9: lambda( std::integral_constant< T, 9 >() ); return; - case 10: lambda( std::integral_constant< T, 10 >() ); return; - case 11: lambda( std::integral_constant< T, 11 >() ); return; - case 12: lambda( std::integral_constant< T, 12 >() ); return; - case 13: lambda( std::integral_constant< T, 13 >() ); return; default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); } } @@ -360,7 +353,7 @@ struct AssemblerKernelHelper arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< real64 const > const & mimFaceGravCoef, + arrayView1d< real64 const > const & mimeticTransGgradZ, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -374,7 +367,6 @@ 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, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], @@ -547,7 +539,7 @@ struct AssemblerKernel arrayView1d< integer const > const & faceGhostRank, 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, @@ -566,7 +558,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 ); }; @@ -652,7 +643,7 @@ struct FluxKernel arrayView1d< integer const > const & faceGhostRank, 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, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 91d6475b76d..b7d1e7ea15a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -615,7 +615,7 @@ AssemblerKernelHelper:: arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< real64 const > const & mimFaceGravCoef, + arrayView1d< real64 const > const & mimeticTransGgradZ, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -629,7 +629,6 @@ AssemblerKernelHelper:: ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, - arraySlice2d< real64 const > const & transMatrixGrav, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], @@ -730,8 +729,7 @@ AssemblerKernelHelper:: // 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]]); + real64 const transGravCoef = 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 @@ -1041,7 +1039,7 @@ AssemblerKernel:: arrayView1d< integer const > const & faceGhostRank, 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, @@ -1060,7 +1058,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 ) { @@ -1116,7 +1113,7 @@ AssemblerKernel:: elemList, regionFilter, faceDofNumber, - mimFaceGravCoef, + mimeticTransGgradZ, elemToFaces, elemGravCoef, useTotalMassEquation, @@ -1130,7 +1127,6 @@ AssemblerKernel:: phaseCompFrac, dPhaseCompFrac, elemDofNumber, - transMatrixGrav, oneSidedVolFlux, dOneSidedVolFlux_dPres, dOneSidedVolFlux_dFacePres, @@ -1239,19 +1235,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, @@ -1281,7 +1264,6 @@ FluxKernel:: rankOffset, dt, transMatrix, - transMatrixGrav, localMatrix, localRhs ); } ); From a203c65b2b34d1dc952261fb53a27af798567882 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 00:14:25 -0700 Subject: [PATCH 09/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index b7d1e7ea15a..da2fd24dfa3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1169,7 +1169,7 @@ FluxKernel:: arrayView1d< integer const > const & faceGhostRank, 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, @@ -1245,7 +1245,7 @@ FluxKernel:: faceGhostRank, facePres, faceGravCoef, - mimFaceGravCoef, + mimeticTransGgradZ, elemToFaces[ei], elemPres[ei], elemGravCoef[ei], From c3b4c1285bde0ed0ceb5d0e8d6f0c43d41f5bb7c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 00:19:19 -0700 Subject: [PATCH 10/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index da2fd24dfa3..7e264765e89 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1219,8 +1219,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 From afdb405b8ada1a777d2807b9e93b30a82b391ba2 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 00:32:44 -0700 Subject: [PATCH 11/91] wip: ongoing work with consistent gravity terms --- .../CompositionalMultiphaseHybridFVM.cpp | 6 ++--- ...ompositionalMultiphaseHybridFVMKernels.cpp | 25 +++---------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index ce2c9b8ec73..5412b50d073 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -341,8 +341,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 = @@ -391,7 +391,7 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, faceGhostRank, facePres, faceGravCoef, - mimFaceGravCoef, + mimeticTransGgradZ, transMultiplier, compFlowAccessors.get( flow::phaseMobility{} ), compFlowAccessors.get( flow::dPhaseMobility{} ), diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp index 1a40022f615..f862718549f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp @@ -1040,7 +1040,7 @@ AssemblerKernel:: arrayView1d< integer const > const & faceGhostRank, 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, @@ -1059,7 +1059,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 ) { @@ -1115,7 +1114,7 @@ AssemblerKernel:: elemList, regionFilter, faceDofNumber, - mimFaceGravCoef, + mimeticTransGgradZ, elemToFaces, elemGravCoef, useTotalMassEquation, @@ -1129,7 +1128,6 @@ AssemblerKernel:: phaseCompFrac, dPhaseCompFrac, elemDofNumber, - transMatrixGrav, oneSidedVolFlux, dOneSidedVolFlux_dPres, dOneSidedVolFlux_dFacePres, @@ -1172,7 +1170,7 @@ FluxKernel:: arrayView1d< integer const > const & faceGhostRank, 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, @@ -1222,7 +1220,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] }; @@ -1238,19 +1235,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, @@ -1261,7 +1245,7 @@ FluxKernel:: faceGhostRank, facePres, faceGravCoef, - mimFaceGravCoef, + mimeticTransGgradZ, elemToFaces[ei], elemPres[ei], elemGravCoef[ei], @@ -1280,7 +1264,6 @@ FluxKernel:: rankOffset, dt, transMatrix, - transMatrixGrav, localMatrix, localRhs ); } ); From 35c0c19e5df45adffbee5452f52900a5b6d89298 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 00:48:43 -0700 Subject: [PATCH 12/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 5412b50d073..14575bab5d1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -73,9 +73,6 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) faceManager.registerField< flow::facePressure_n >( 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() ); From e1ec4b1ad8bbce0a4035eeb8496d14c450d5d9e1 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 01:09:24 -0700 Subject: [PATCH 13/91] Update kernelSpecs.json --- .../physicsSolvers/fluidFlow/kernelSpecs.json | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index c398a1e7bd9..bd06e9bea57 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -93,7 +93,14 @@ "NFACES": [ 4, 5, - 6 + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13 ], "NCOMPS": [ 1, @@ -122,7 +129,14 @@ "NFACES": [ 4, 5, - 6 + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13 ], "NCOMPS": [ 1, @@ -137,6 +151,9 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", + "mimeticInnerProduct::QuasiTPFAInnerProduct", + "mimeticInnerProduct::QuasiRTInnerProduct", + "mimeticInnerProduct::SimpleInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, From 3035ace645c0cf16364860fc9c9b36aa178d0ca9 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 01:10:50 -0700 Subject: [PATCH 14/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- .../CompositionalMultiphaseHybridFVMKernels.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 0e936852168..86043ba0b11 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -58,6 +58,13 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) case 4: lambda( std::integral_constant< T, 4 >() ); return; case 5: lambda( std::integral_constant< T, 5 >() ); return; case 6: lambda( std::integral_constant< T, 6 >() ); return; + case 7: lambda( std::integral_constant< T, 7 >() ); return; + case 8: lambda( std::integral_constant< T, 8 >() ); return; + case 9: lambda( std::integral_constant< T, 9 >() ); return; + case 10: lambda( std::integral_constant< T, 10 >() ); return; + case 11: lambda( std::integral_constant< T, 11 >() ); return; + case 12: lambda( std::integral_constant< T, 12 >() ); return; + case 13: lambda( std::integral_constant< T, 13 >() ); return; default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); } } From b6cde0e7c51f7db727aabc45e53cef2aa4cab25c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 01:41:45 -0700 Subject: [PATCH 15/91] wip: ongoing work with consistent gravity terms afdb405b8a src --- ...sitionalMultiphaseHybridFVMKernels_assembly.cpp.template | 6 ++---- ...ompositionalMultiphaseHybridFVMKernels_flux.cpp.template | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template index d06fd73408c..d5a9a5c9f66 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template @@ -42,7 +42,7 @@ namespace compositionalMultiphaseHybridFVMKernels arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< real64 const > const & mimFaceGravCoef, + arrayView1d< real64 const > const & mimeticTransGgradZ, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -56,7 +56,6 @@ namespace compositionalMultiphaseHybridFVMKernels 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, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], @@ -134,7 +133,7 @@ namespace compositionalMultiphaseHybridFVMKernels arrayView1d< integer const > const & faceGhostRank, 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, @@ -153,7 +152,6 @@ namespace compositionalMultiphaseHybridFVMKernels 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 ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template index 76c8fef1aac..59fb705be55 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template @@ -27,7 +27,7 @@ namespace compositionalMultiphaseHybridFVMKernels arrayView1d< integer const > const & faceGhostRank, 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, From 0db774b51088dbb7c41df55106a5747a854075f4 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 03:19:14 -0700 Subject: [PATCH 16/91] Update kernelSpecs.json --- src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index bd06e9bea57..ffc6aa50e99 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -152,8 +152,6 @@ "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", "mimeticInnerProduct::QuasiTPFAInnerProduct", - "mimeticInnerProduct::QuasiRTInnerProduct", - "mimeticInnerProduct::SimpleInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, From 3eaa7c55522f239db9d2d49efd42f18a4b7151af Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 04:06:22 -0700 Subject: [PATCH 17/91] fix: consistent gravity term --- ...haseHybridFVMKernels_assembly.cpp.template | 2 ++ ...ompositionalMultiphaseHybridFVMKernels.hpp | 2 ++ ...itionalMultiphaseHybridFVMKernels_impl.hpp | 22 +++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template index d5a9a5c9f66..5127ba2d417 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template @@ -43,6 +43,7 @@ namespace compositionalMultiphaseHybridFVMKernels SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< real64 const > const & mimeticTransGgradZ, + arrayView1d< real64 const > const & faceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -56,6 +57,7 @@ namespace compositionalMultiphaseHybridFVMKernels 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 & transMatrix, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 86043ba0b11..20fce9654f5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -361,6 +361,7 @@ struct AssemblerKernelHelper SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< real64 const > const & mimeticTransGgradZ, + arrayView1d< real64 const > const & faceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -374,6 +375,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 & transMatrix, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 7e264765e89..e98899a03ae 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -616,6 +616,7 @@ AssemblerKernelHelper:: SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< real64 const > const & mimeticTransGgradZ, + arrayView1d< real64 const > const & faceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -629,6 +630,7 @@ AssemblerKernelHelper:: ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, + arraySlice2d< real64 const > const & transMatrix, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], @@ -728,8 +730,22 @@ AssemblerKernelHelper:: dofColIndicesFaceVars ); // 3) *************** Assemble buoyancy terms ****************** - - real64 const transGravCoef = mimeticTransGgradZ[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 @@ -1114,6 +1130,7 @@ AssemblerKernel:: regionFilter, faceDofNumber, mimeticTransGgradZ, + faceGravCoef, elemToFaces, elemGravCoef, useTotalMassEquation, @@ -1127,6 +1144,7 @@ AssemblerKernel:: phaseCompFrac, dPhaseCompFrac, elemDofNumber, + transMatrix, oneSidedVolFlux, dOneSidedVolFlux_dPres, dOneSidedVolFlux_dFacePres, From 6d731cbf8b0bcfde62d2338d5517bcbb7e745f4d Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 04:12:07 -0700 Subject: [PATCH 18/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 14575bab5d1..8e18de73dac 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -173,10 +173,7 @@ void CompositionalMultiphaseHybridFVM::precomputeData( MeshLevel & mesh, string_ DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); NumericalMethodsManager const & nm = domain.getNumericalMethodManager(); FiniteVolumeManager const & fvManager = nm.getFiniteVolumeManager(); - if( !fvManager.hasGroup< HybridMimeticDiscretization >( m_discretizationName ) ) - { - return; // Not using hybrid mimetic discretization; nothing to precompute - } + 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; From f8b8afa154e8f52a7405280ca840374a9bbeba56 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 04:19:10 -0700 Subject: [PATCH 19/91] Update CompositionalMultiphaseHybridFVMKernels.cpp --- ...CompositionalMultiphaseHybridFVMKernels.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp index f862718549f..e3c7955c86d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp @@ -617,6 +617,7 @@ AssemblerKernelHelper:: SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< real64 const > const & mimeticTransGgradZ, + arrayView1d< real64 const > const & faceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, @@ -630,6 +631,7 @@ AssemblerKernelHelper:: ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, + arraySlice2d< real64 const > const & transMatrix, real64 const (&oneSidedVolFlux)[ NF ], real64 const (&dOneSidedVolFlux_dPres)[ NF ], real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], @@ -730,7 +732,21 @@ AssemblerKernelHelper:: // 3) *************** Assemble buoyancy terms ****************** - real64 const transGravCoef = mimeticTransGgradZelemToFaces[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 From b384cd6be94c881b63e5acdb1158b06240c0bee0 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 04:21:23 -0700 Subject: [PATCH 20/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- .../compositional/CompositionalMultiphaseHybridFVMKernels.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 20fce9654f5..135bd947fad 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -904,7 +904,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa ResidualNormKernel( globalIndex const rankOffset, arrayView1d< real64 const > const & localResidual, arrayView1d< globalIndex const > const & dofNumber, - arrayView1d< integer const > const & ghostRank, + arrayView1d< localIndex const > const & ghostRank, SortedArrayView< localIndex const > const & regionFilter, FaceManager const & faceManager, CompFlowAccessors const & compFlowAccessors, From adc61e69d0df4a94ad87cb36817e5b7eb62227f1 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 12 Oct 2025 23:59:29 -0700 Subject: [PATCH 21/91] wip: improving solution strategy --- .../flowOnly_staircase_co2_3d_mfd.xml | 73 +++++++++++++++++++ .../flowOnly_staircase_co2_3d_tpfa.xml | 73 +++++++++++++++++++ .../CompositionalMultiphaseHybridFVM.hpp | 6 +- .../CompositionalMultiphaseHybridFVM.cpp | 2 +- 4 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_mfd.xml create mode 100644 inputFiles/compositionalMultiphaseFlow/issue_3497/flowOnly_staircase_co2_3d_tpfa.xml 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/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/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 8e18de73dac..a5fd60281dd 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -605,7 +605,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FaceManager & targetGroup, string const & ) { - + GEOS_UNUSED_VAR( setName ); // Using the field specification functions to apply the boundary conditions to the system fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, From f95ea48dc642d4d9c911b9322245ed0632e810c2 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 20 Oct 2025 16:21:20 -0700 Subject: [PATCH 22/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 32 +++++-------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index cb2a68222f7..0e4acbbda82 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -25,7 +25,6 @@ #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" -#include "fieldSpecification/LogLevelsInfo.hpp" #include "finiteVolume/HybridMimeticDiscretization.hpp" #include "finiteVolume/MimeticInnerProductDispatch.hpp" #include "mesh/mpiCommunications/CommunicationTools.hpp" @@ -73,6 +72,9 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) // primary variables: face pressure changes faceManager.registerField< flow::facePressure_n >( getName() ); + + // Register the bc face data + faceManager.registerField< flow::bcPressure >( getName() ); // auxiliary data for the buoyancy coefficient faceManager.registerField< flow::mimGravityCoefficient >( getName() ); @@ -577,15 +579,6 @@ void CompositionalMultiphaseHybridFVM::applyBoundaryConditions( real64 const tim } } -namespace -{ -char const faceBcLogMessage[] = - "CompositionalMultiphaseHybridFVM {}: at time {}s, " - "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " - "\nThe total number of target faces (including ghost faces) is {}. " - "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; -} - void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n, real64 const dt, DofManager const & dofManager, @@ -607,6 +600,8 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView1d< real64 const > const presFace = faceManager.getField< flow::facePressure >(); + arrayView1d< real64 const > const presFaceBC = + faceManager.getField< flow::bcPressure >(); arrayView1d< globalIndex const > const faceDofNumber = faceManager.getReference< array1d< globalIndex > >( faceDofKey ); arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); @@ -615,7 +610,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n fsManager.apply< FaceManager >( time_n + dt, mesh, - flow::pressure::key(), + flow::bcPressure::key(), [&] ( FieldSpecificationBase const & fs, string const & setName, SortedArrayView< localIndex const > const & targetSet, @@ -623,23 +618,12 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n string const & ) { - // report at the first nonlinear iteration - if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - globalIndex const numTargetFaces = MpiWrapper::sum< globalIndex >( targetSet.size() ); - GEOS_LOG_LEVEL_RANK_0_ON_GROUP( logInfo::FaceBoundaryCondition, - GEOS_FMT( faceBcLogMessage, - this->getName(), time_n+dt, fs.getCatalogName(), fs.getName(), - setName, targetGroup.getName(), numTargetFaces ), - fs ); - } - // Using the field specification functions to apply the boundary conditions to the system fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, time_n + dt, targetGroup, - flow::facePressure::key() ); + flow::bcPressure::key() ); forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) { @@ -660,7 +644,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n rankOffset, localMatrix, rhsValue, - presFace[kf], + presFaceBC[kf], presFace[kf] ); localRhs[localRow] = rhsValue; } ); From 4ac73f21321054c753a42675f5af4a49152006dc Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 20 Oct 2025 16:48:34 -0700 Subject: [PATCH 23/91] wip: add a kernel for handling composition boundary conditions --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 1 + .../DirichletMFDFluxComputeKernel.hpp | 584 ++++++++++++++++++ 2 files changed, 585 insertions(+) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 28ffa57e587..2f813514d29 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -75,6 +75,7 @@ set( fluidFlowSolvers_headers kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp kernels/compositional/DiffusionDispersionFluxComputeKernel.hpp kernels/compositional/DirichletFluxComputeKernel.hpp + kernels/compositional/DirichletMFDFluxComputeKernel.hpp kernels/compositional/DissipationFluxComputeKernel.hpp kernels/compositional/FluidUpdateKernel.hpp kernels/compositional/FluidUpdateKernel.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp new file mode 100644 index 00000000000..800eb7c70e3 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp @@ -0,0 +1,584 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file DirichletMFDFluxComputeKernel.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DIRICHLETMFDFLUXCOMPUTEKERNEL_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DIRICHLETMFDFLUXCOMPUTEKERNEL_HPP + +#include "codingUtilities/Utilities.hpp" +#include "common/DataLayouts.hpp" +#include "common/DataTypes.hpp" +#include "common/GEOS_RAJA_Interface.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "constitutive/fluid/multifluid/MultiFluidSelector.hpp" +#include "finiteVolume/BoundaryStencil.hpp" +#include "mesh/ElementRegionManager.hpp" +#include "mesh/ElementSubRegionBase.hpp" +#include "mesh/cell/CellElementSubRegion.hpp" +#include "mesh/FaceManager.hpp" +#include "mesh/NodeManager.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" +#include "physicsSolvers/fluidFlow/StencilAccessors.hpp" +#include "finiteVolume/mimeticInnerProducts/MimeticInnerProductBase.hpp" + +#include "FluxComputeKernel.hpp" + +namespace geos +{ + +namespace isothermalCompositionalMultiphaseFVMKernels +{ + +/******************************** DirichletMFDFluxComputeKernel ********************************/ + +/** + * @class DirichletMFDFluxComputeKernel + * @tparam NUM_COMP number of fluid components + * @tparam NUM_DOF number of degrees of freedom + * @tparam FLUIDWRAPPER the type of the fluid wrapper + * @tparam IP_TYPE the mimetic inner product type (e.g., TPFAInnerProduct, BdVLMInnerProduct) + * @tparam NF number of faces per element in the targeted subregion + * @brief Define the interface for the assembly kernel in charge of Dirichlet face flux terms using an MFD inner product + */ +template< integer NUM_COMP, integer NUM_DOF, typename FLUIDWRAPPER, typename IP_TYPE, integer NF > +class DirichletMFDFluxComputeKernel : public FluxComputeKernel< NUM_COMP, + NUM_DOF, + BoundaryStencilWrapper > +{ +public: + + /** + * @brief The type for element-based data. Consists entirely of ArrayView's. + * + * Can be converted from ElementRegionManager::ElementViewConstAccessor + * by calling .toView() or .toViewConst() on an accessor instance + */ + template< typename VIEWTYPE > + using ElementViewConst = ElementRegionManager::ElementViewConst< VIEWTYPE >; + + using AbstractBase = isothermalCompositionalMultiphaseFVMKernels::FluxComputeKernelBase; + using DofNumberAccessor = AbstractBase::DofNumberAccessor; + using CompFlowAccessors = AbstractBase::CompFlowAccessors; + using MultiFluidAccessors = AbstractBase::MultiFluidAccessors; + using CapPressureAccessors = AbstractBase::CapPressureAccessors; + using PermeabilityAccessors = AbstractBase::PermeabilityAccessors; + + using AbstractBase::m_dt; + using AbstractBase::m_numPhases; + using AbstractBase::m_rankOffset; + using AbstractBase::m_dofNumber; + using AbstractBase::m_ghostRank; + using AbstractBase::m_gravCoef; + using AbstractBase::m_pres; + using AbstractBase::m_phaseCompFrac; + using AbstractBase::m_dPhaseCompFrac; + using AbstractBase::m_dCompFrac_dCompDens; + using AbstractBase::m_localMatrix; + using AbstractBase::m_localRhs; + using AbstractBase::m_kernelFlags; + + using Base = isothermalCompositionalMultiphaseFVMKernels::FluxComputeKernel< NUM_COMP, NUM_DOF, BoundaryStencilWrapper >; + using Base::numComp; + using Base::numDof; + using Base::numEqn; + using Base::m_stencilWrapper; + using Base::m_phaseMob; + using Base::m_dPhaseMob; + using Base::m_phaseMassDens; + using Base::m_dPhaseMassDens; + using Base::m_permeability; + using Base::m_dPerm_dPres; + using Base::m_seri; + using Base::m_sesri; + using Base::m_sei; + + /** + * @brief Constructor for the kernel interface + * @param[in] numPhases the number of fluid phases + * @param[in] rankOffset the offset of my MPI rank + * @param[in] faceManager the face manager + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] fluidWrapper reference to the fluid wrapper + * @param[in] dofNumberAccessor + * @param[in] compFlowAccessors + * @param[in] multiFluidAccessors + * @param[in] capPressureAccessors + * @param[in] permeabilityAccessors + * @param[in] nodePosition reference positions of nodes + * @param[in] faceToNodes face-to-nodes connectivity + * @param[in] elemCenter element centers (in the targeted subregion) + * @param[in] elemVolume element volumes (in the targeted subregion) + * @param[in] elemToFaces element-to-faces connectivity (in the targeted subregion) + * @param[in] transMultiplier transmissibility multipliers per face + * @param[in] lengthTolerance geometric tolerance for IP computation + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + * @param[in] kernelFlags flags packed together + */ + DirichletMFDFluxComputeKernel( integer const numPhases, + globalIndex const rankOffset, + FaceManager const & faceManager, + BoundaryStencilWrapper const & stencilWrapper, + FLUIDWRAPPER const & fluidWrapper, + DofNumberAccessor const & dofNumberAccessor, + CompFlowAccessors const & compFlowAccessors, + MultiFluidAccessors const & multiFluidAccessors, + CapPressureAccessors const & capPressureAccessors, + PermeabilityAccessors const & permeabilityAccessors, + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, + ArrayOfArraysView< localIndex const > const & faceToNodes, + ElementViewConst< arrayView2d< real64 const > > const & elemCenter, + ElementViewConst< arrayView1d< real64 const > > const & elemVolume, + ElementViewConst< arrayView2d< localIndex const > > const & elemToFaces, + arrayView1d< real64 const > const & transMultiplier, + real64 const lengthTolerance, + real64 const dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs, + BitFlags< KernelFlags > kernelFlags ) + : Base( numPhases, + rankOffset, + stencilWrapper, + dofNumberAccessor, + compFlowAccessors, + multiFluidAccessors, + capPressureAccessors, + permeabilityAccessors, + dt, + localMatrix, + localRhs, + kernelFlags ), + m_facePres( faceManager.getField< fields::flow::facePressure >() ), + m_faceTemp( faceManager.getField< fields::flow::faceTemperature >() ), + m_faceCompFrac( faceManager.getField< fields::flow::faceGlobalCompFraction >() ), + m_faceGravCoef( faceManager.getField< fields::flow::gravityCoefficient >() ), + m_nodePosition( nodePosition ), + m_faceToNodes( faceToNodes ), + m_elemCenter( elemCenter ), + m_elemVolume( elemVolume ), + m_elemToFaces( elemToFaces ), + m_transMultiplier( transMultiplier ), + m_lengthTolerance( lengthTolerance ), + m_fluidWrapper( fluidWrapper ) + {} + + /** + * @struct StackVariables + * @brief Kernel variables (dof numbers, jacobian and residual) located on the stack + */ + struct StackVariables + { + public: + + GEOS_HOST_DEVICE + StackVariables( localIndex const GEOS_UNUSED_PARAM( size ), + localIndex GEOS_UNUSED_PARAM( numElems )) {} + + // Transmissibility + real64 transmissibility = 0.0; + + // Component fluxes and derivatives + + /// Component fluxes + real64 compFlux[numComp]{}; + /// Derivatives of component fluxes wrt pressure + real64 dCompFlux_dP[numComp]{}; + /// Derivatives of component fluxes wrt component densities + real64 dCompFlux_dC[numComp][numComp]{}; + + // Local degrees of freedom and local residual/jacobian + + /// Indices of the matrix rows/columns corresponding to the dofs in this face + globalIndex dofColIndices[numDof]{}; + + /// Storage for the face local residual vector + real64 localFlux[numEqn]{}; + /// Storage for the face local Jacobian matrix + real64 localFluxJacobian[numEqn][numDof]{}; + }; + + /** + * @brief Performs the setup phase for the kernel. + * @param[in] iconn the connection index + * @param[in] stack the stack variables + */ + GEOS_HOST_DEVICE + void setup( localIndex const iconn, + StackVariables & stack ) const + { + globalIndex const offset = + m_dofNumber[m_seri( iconn, BoundaryStencil::Order::ELEM )][m_sesri( iconn, BoundaryStencil::Order::ELEM )][m_sei( iconn, BoundaryStencil::Order::ELEM )]; + + for( integer jdof = 0; jdof < numDof; ++jdof ) + { + stack.dofColIndices[jdof] = offset + jdof; + } + } + + /** + * @brief Compute the local Dirichlet face flux contributions to the residual and Jacobian (MFD version) + */ + template< typename FUNC = NoOpFunc > + GEOS_HOST_DEVICE + void computeFlux( localIndex const iconn, + StackVariables & stack, + FUNC && compFluxKernelOp = NoOpFunc{} ) const + { + using Deriv = constitutive::multifluid::DerivativeOffset; + using Order = BoundaryStencil::Order; + + localIndex const er = m_seri( iconn, Order::ELEM ); + localIndex const esr = m_sesri( iconn, Order::ELEM ); + localIndex const ei = m_sei( iconn, Order::ELEM ); + localIndex const kf = m_sei( iconn, Order::FACE ); + + // Step 1: compute the one-sided MFD transmissibility at the boundary face + { + stackArray2d< real64, NF * NF > transMatrix( NF, NF ); + + // principal permeabilities (assumed stored in first comp index) + real64 const perm[3] = { m_permeability[er][esr][ei][0][0], + m_permeability[er][esr][ei][0][1], + m_permeability[er][esr][ei][0][2] }; + + IP_TYPE::template compute< NF >( m_nodePosition, + m_transMultiplier, + m_faceToNodes, + m_elemToFaces[er][esr][ei], + m_elemCenter[er][esr][ei], + m_elemVolume[er][esr][ei], + perm, + m_lengthTolerance, + transMatrix ); + + // find local face index corresponding to global face kf + integer ifaceLoc = 0; + for( integer j = 0; j < NF; ++j ) + { + if( m_elemToFaces[er][esr][ei][j] == kf ) + { + ifaceLoc = j; + break; + } + } + stack.transmissibility = transMatrix[ifaceLoc][ifaceLoc]; + } + + // Step 2: compute the fluid properties on the face + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseFrac( 1, 1, m_numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseDens( 1, 1, m_numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseMassDens( 1, 1, m_numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseVisc( 1, 1, m_numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseEnthalpy( 1, 1, m_numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, m_numPhases ); + StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NUM_COMP, + constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFrac( 1, 1, m_numPhases, NUM_COMP ); + real64 faceTotalDens = 0.0; + + constitutive::MultiFluidBase::KernelWrapper::computeValues( m_fluidWrapper, + m_facePres[kf], + m_faceTemp[kf], + m_faceCompFrac[kf], + facePhaseFrac[0][0], + facePhaseDens[0][0], + facePhaseMassDens[0][0], + facePhaseVisc[0][0], + facePhaseEnthalpy[0][0], + facePhaseInternalEnergy[0][0], + facePhaseCompFrac[0][0], + faceTotalDens ); + + // Step 3: loop over phases, compute and upwind phase flux and sum contributions to each component's flux + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + // working variables + real64 dDensMean_dC[numComp]{}; + real64 dF_dC[numComp]{}; + real64 dProp_dC[numComp]{}; + + real64 phaseFlux = 0.0; // for the lambda + real64 dPhaseFlux_dP = 0.0; + real64 dPhaseFlux_dC[numComp]{}; + + // Step 3.1: compute the average phase mass density at the face + applyChainRule( numComp, + m_dCompFrac_dCompDens[er][esr][ei], + m_dPhaseMassDens[er][esr][ei][0][ip], + dProp_dC, + Deriv::dC ); + + real64 const densMean = 0.5 * ( m_phaseMassDens[er][esr][ei][0][ip] + facePhaseMassDens[0][0][ip] ); + real64 const dDensMean_dP = 0.5 * m_dPhaseMassDens[er][esr][ei][0][ip][Deriv::dP]; + for( integer jc = 0; jc < numComp; ++jc ) + { + dDensMean_dC[jc] = 0.5 * dProp_dC[jc]; + } + + // Step 3.2: compute the MFD potential difference at the face (same expression; only T differs) + real64 const gravTimesDz = m_gravCoef[er][esr][ei] - m_faceGravCoef[kf]; + real64 const potDif = m_pres[er][esr][ei] - m_facePres[kf] - densMean * gravTimesDz; + + // Derivative of T wrt pressure unknown for general IP: set to 0 (approximation) + real64 const dTrans_dPres = 0.0; + real64 const f = stack.transmissibility * potDif; + real64 const dF_dP = stack.transmissibility * ( 1.0 - dDensMean_dP * gravTimesDz ) + dTrans_dPres * potDif; + for( integer jc = 0; jc < numComp; ++jc ) + { + dF_dC[jc] = -stack.transmissibility * dDensMean_dC[jc] * gravTimesDz; + } + + // Step 3.3: approximation for face mobility using total element mobility + real64 const facePhaseMob = ( facePhaseFrac[0][0][ip] > 0.0 ) + ? facePhaseFrac[0][0][ip] * faceTotalDens / facePhaseVisc[0][0][ip] + : 0.0; + + // Step 3.4: upwinding + if( potDif >= 0 ) // the element is upstream + { + phaseFlux = m_phaseMob[er][esr][ei][ip] * f; + dPhaseFlux_dP = m_phaseMob[er][esr][ei][ip] * dF_dP + m_dPhaseMob[er][esr][ei][ip][Deriv::dP] * f; + for( integer jc = 0; jc < numComp; ++jc ) + { + dPhaseFlux_dC[jc] = m_phaseMob[er][esr][ei][ip] * dF_dC[jc] + m_dPhaseMob[er][esr][ei][ip][Deriv::dC+jc] * f; + } + + arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE_COMP-3 > phaseCompFracSub = + m_phaseCompFrac[er][esr][ei][0][ip]; + arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC-3 > dPhaseCompFracSub = + m_dPhaseCompFrac[er][esr][ei][0][ip]; + + for( integer ic = 0; ic < numComp; ++ic ) + { + real64 const ycp = phaseCompFracSub[ic]; + stack.compFlux[ic] += phaseFlux * ycp; + stack.dCompFlux_dP[ic] += dPhaseFlux_dP * ycp + phaseFlux * dPhaseCompFracSub[ic][Deriv::dP]; + + applyChainRule( numComp, + m_dCompFrac_dCompDens[er][esr][ei], + dPhaseCompFracSub[ic], + dProp_dC, + Deriv::dC ); + for( integer jc = 0; jc < numComp; ++jc ) + { + stack.dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp + phaseFlux * dProp_dC[jc]; + } + } + } + else // the face is upstream + { + phaseFlux = facePhaseMob * f; + dPhaseFlux_dP = facePhaseMob * dF_dP; + for( integer jc = 0; jc < numComp; ++jc ) + { + dPhaseFlux_dC[jc] = facePhaseMob * dF_dC[jc]; + } + + for( integer ic = 0; ic < numComp; ++ic ) + { + real64 const ycp = facePhaseCompFrac[0][0][ip][ic]; + stack.compFlux[ic] += phaseFlux * ycp; + stack.dCompFlux_dP[ic] += dPhaseFlux_dP * ycp; + for( integer jc = 0; jc < numComp; ++jc ) + { + stack.dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp; + } + } + } + + // reuse hook + compFluxKernelOp( ip, er, esr, ei, kf, f, + facePhaseMob, facePhaseEnthalpy[0][0], facePhaseCompFrac[0][0], + phaseFlux, dPhaseFlux_dP, dPhaseFlux_dC ); + } + + // Step 4: populate local flux vector and derivatives + for( integer ic = 0; ic < numComp; ++ic ) + { + stack.localFlux[ic] = m_dt * stack.compFlux[ic]; + stack.localFluxJacobian[ic][0] = m_dt * stack.dCompFlux_dP[ic]; + for( integer jc = 0; jc < numComp; ++jc ) + { + stack.localFluxJacobian[ic][jc+1] = m_dt * stack.dCompFlux_dC[ic][jc]; + } + } + } + + /** + * @brief Performs the complete phase for the kernel. + */ + template< typename FUNC = NoOpFunc > + GEOS_HOST_DEVICE + void complete( localIndex const iconn, + StackVariables & stack, + FUNC && assemblyKernelOp = NoOpFunc{} ) const + { + using namespace compositionalMultiphaseUtilities; + using Order = BoundaryStencil::Order; + + if( AbstractBase::m_kernelFlags.isSet( KernelFlags::TotalMassEquation ) ) + { + // Apply equation/variable change transformation(s) + real64 work[numDof]{}; + shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numComp, numDof, stack.localFluxJacobian, work ); + shiftElementsAheadByOneAndReplaceFirstElementWithSum( numComp, stack.localFlux ); + } + + if( m_ghostRank[m_seri( iconn, Order::ELEM )][m_sesri( iconn, Order::ELEM )][m_sei( iconn, Order::ELEM )] < 0 ) + { + globalIndex const globalRow = m_dofNumber[m_seri( iconn, Order::ELEM )][m_sesri( iconn, Order::ELEM )][m_sei( iconn, Order::ELEM )]; + localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset ); + GEOS_ASSERT_GE( localRow, 0 ); + GEOS_ASSERT_GT( AbstractBase::m_localMatrix.numRows(), localRow + numComp ); + + for( integer ic = 0; ic < numComp; ++ic ) + { + RAJA::atomicAdd( parallelDeviceAtomic{}, &AbstractBase::m_localRhs[localRow + ic], stack.localFlux[ic] ); + AbstractBase::m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic > + ( localRow + ic, + stack.dofColIndices, + stack.localFluxJacobian[ic], + numDof ); + } + + assemblyKernelOp( localRow ); + } + } + +protected: + + /// Views on face pressure, temperature, and composition + arrayView1d< real64 const > const m_facePres; + arrayView1d< real64 const > const m_faceTemp; + arrayView2d< real64 const, compflow::USD_COMP > const m_faceCompFrac; + + /// View on the face gravity coefficient + arrayView1d< real64 const > const m_faceGravCoef; + + // Geometry/connectivity for IP computation + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const m_nodePosition; + ArrayOfArraysView< localIndex const > const m_faceToNodes; + ElementViewConst< arrayView2d< real64 const > > const m_elemCenter; + ElementViewConst< arrayView1d< real64 const > > const m_elemVolume; + ElementViewConst< arrayView2d< localIndex const > > const m_elemToFaces; + arrayView1d< real64 const > const m_transMultiplier; + real64 const m_lengthTolerance; + + /// Reference to the fluid wrapper + FLUIDWRAPPER const m_fluidWrapper; +}; + + +/** + * @class DirichletMFDFluxComputeKernelFactory + */ +class DirichletMFDFluxComputeKernelFactory +{ +public: + + /** + * @brief Create a new MFD Dirichlet kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @tparam IP_TYPE mimetic inner product type + * @tparam NF number of faces per element in the targeted subregion + */ + template< typename POLICY, typename IP_TYPE, integer NF > + static void + createAndLaunch( integer const numComps, + integer const numPhases, + globalIndex const rankOffset, + BitFlags< KernelFlags > kernelFlags, + string const & dofKey, + string const & solverName, + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, + FaceManager const & faceManager, + ElementRegionManager const & elemManager, + BoundaryStencilWrapper const & stencilWrapper, + constitutive::MultiFluidBase & fluidBase, + real64 const lengthTolerance, + real64 const dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // Select fluid wrapper based on number of components + constitutive::constitutiveComponentUpdatePassThru( fluidBase, numComps, [&]( auto & fluid, auto NC ) + { + using FluidType = TYPEOFREF( fluid ); + typename FluidType::KernelWrapper const fluidWrapper = fluid.createKernelWrapper(); + + integer constexpr NUM_COMP = NC(); + integer constexpr NUM_DOF = NC() + 1; + + // Identify a representative subregion from the stencil (same assumption as TPFA Dirichlet) + localIndex const er = stencilWrapper.getElementRegionIndices()( 0, BoundaryStencil::Order::ELEM ); + localIndex const esr = stencilWrapper.getElementSubRegionIndices()( 0, BoundaryStencil::Order::ELEM ); + ElementSubRegionBase const & subRegionBase = elemManager.getRegion( er ).getSubRegion( esr ); + + // Element geometry/connectivity arrays + ElementRegionManager::ElementViewConst< arrayView2d< real64 const > > elemCenter = + elemManager.constructArrayViewAccessor< real64, 2 >( CellElementSubRegion::viewKeyStruct::elementCenterString() ).toViewConst(); + ElementRegionManager::ElementViewConst< arrayView1d< real64 const > > elemVolume = + elemManager.constructArrayViewAccessor< real64, 1 >( CellElementSubRegion::viewKeyStruct::elementVolumeString() ).toViewConst(); + ElementRegionManager::ElementViewConst< arrayView2d< localIndex const > > elemToFaces = + elemManager.constructArrayViewAccessor< localIndex, 2 >( CellElementSubRegion::viewKeyStruct::faceListString() ).toViewConst(); + + // Face connectivity and multipliers + ArrayOfArraysView< localIndex const > faceToNodes = faceManager.nodeList().toViewConst(); + arrayView1d< real64 const > const & transMultiplier = faceManager.getField< fields::flow::transMultiplier >(); + + using kernelType = DirichletMFDFluxComputeKernel< NUM_COMP, NUM_DOF, typename FluidType::KernelWrapper, IP_TYPE, NF >; + typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); + typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); + typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); + typename kernelType::PermeabilityAccessors permeabilityAccessors( elemManager, solverName ); + + kernelType kernel( numPhases, + rankOffset, + faceManager, + stencilWrapper, + fluidWrapper, + elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ), + compFlowAccessors, + multiFluidAccessors, + capPressureAccessors, + permeabilityAccessors, + nodePosition, + faceToNodes, + elemCenter, + elemVolume, + elemToFaces, + transMultiplier, + lengthTolerance, + dt, + localMatrix, + localRhs, + kernelFlags ); + kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); + GEOS_UNUSED_VAR( subRegionBase ); + } ); + } +}; + +} // namespace isothermalCompositionalMultiphaseFVMKernels + +} // namespace geos + + +#endif // GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DIRICHLETMFDFLUXCOMPUTEKERNEL_HPP From f2af4741b9d0f2840e1c4d196e8df37a2822ed26 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 20 Oct 2025 17:52:42 -0700 Subject: [PATCH 24/91] wip: compiling code --- .../CompositionalMultiphaseHybridFVM.cpp | 108 +++++++++++++++++- .../DirichletMFDFluxComputeKernel.hpp | 29 ++--- 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 0e4acbbda82..1fc19fdfe95 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -27,6 +27,8 @@ #include "fieldSpecification/FieldSpecificationManager.hpp" #include "finiteVolume/HybridMimeticDiscretization.hpp" #include "finiteVolume/MimeticInnerProductDispatch.hpp" +#include "finiteVolume/FluxApproximationBase.hpp" +#include "finiteVolume/BoundaryStencil.hpp" #include "mesh/mpiCommunications/CommunicationTools.hpp" #include "physicsSolvers/LogLevelsInfo.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" @@ -35,6 +37,8 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/SolutionScalingKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/SolutionCheckKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/ResidualNormKernel.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp" +#include "mesh/CellElementSubRegion.hpp" /** * @namespace the geos namespace that encapsulates the majority of the code @@ -588,20 +592,119 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n { GEOS_MARK_FUNCTION; + using namespace isothermalCompositionalMultiphaseFVMKernels; + using namespace mimeticInnerProduct; + + // Build kernel flags (capillary pressure not supported here) + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; + if( m_useTotalMassEquation ) + { + kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); + } + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + + // Log message similar to the cell-centered FVM version + static char const faceBcLogMessage[] = + "CompositionalMultiphaseHybridFVM {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " + "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " + "\nThe total number of target faces (including ghost faces) is {}." + "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; + // For each mesh target, first apply face fields and assemble MFD Dirichlet fluxes, then keep strong enforcement of face bcPressure this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, string_array const & ) { + ElementRegionManager & elemManager = mesh.getElemManager(); + NodeManager const & nodeManager = mesh.getNodeManager(); FaceManager & faceManager = mesh.getFaceManager(); + // 1) Apply boundary field values to face-centered fields (pressure, composition, temperature) + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::pressure::key(), flow::facePressure::key() ); + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::globalCompFraction::key(), flow::faceGlobalCompFraction::key() ); + // NOTE: current MFD compositional implementation is isothermal; thermal support will be added later. + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::temperature::key(), flow::faceTemperature::key() ); + + // 2) Launch MFD Dirichlet flux kernel per BC face set using the selected inner product + fsManager.apply< FaceManager >( time_n + dt, + mesh, + flow::pressure::key(), + [&] ( FieldSpecificationBase const &, + string const & setName, + SortedArrayView< localIndex const > const &, + FaceManager &, + string const & ) + { + BoundaryStencil const & stencil = fluxApprox.getStencil< BoundaryStencil >( mesh, setName ); + if( stencil.size() == 0 ) + { + return; + } + + // Select fluid model from first cell adjacent to this face set (same approach as in FVM Dirichlet) + localIndex const er = stencil.getElementRegionIndices()( 0, BoundaryStencil::Order::ELEM ); + localIndex const esr = stencil.getElementSubRegionIndices()( 0, BoundaryStencil::Order::ELEM ); + ElementSubRegionBase & subRegion = elemManager.getRegion( er ).getSubRegion( esr ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & multiFluidBase = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + + BoundaryStencilWrapper const stencilWrapper = stencil.createKernelWrapper(); + string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // Inner product selection and NF dispatch + HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); + MimeticInnerProductBase const & mimIP = + hmDiscretization.getReference< MimeticInnerProductBase >( HybridMimeticDiscretization::viewKeyStruct::innerProductString() ); + + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition = nodeManager.referencePosition(); + integer const numFacesInElem = elemManager.getRegion( er ).getSubRegion< CellElementSubRegion >( esr ).numFacesPerElement(); + + mimeticInnerProductReducedDispatch( mimIP, [&] ( auto const ipType ) + { + using IP_T = std::remove_const_t< TYPEOFREF( ipType ) >; + if( numFacesInElem == 4 ) + { + DirichletMFDFluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<>, IP_T, 4 >( + m_numComponents, m_numPhases, dofManager.rankOffset(), kernelFlags, + elemDofKey, getName(), nodePosition, faceManager, elemManager, stencilWrapper, + multiFluidBase, m_lengthTolerance, dt, localMatrix, localRhs ); + } + else if( numFacesInElem == 5 ) + { + DirichletMFDFluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<>, IP_T, 5 >( + m_numComponents, m_numPhases, dofManager.rankOffset(), kernelFlags, + elemDofKey, getName(), nodePosition, faceManager, elemManager, stencilWrapper, + multiFluidBase, m_lengthTolerance, dt, localMatrix, localRhs ); + } + else if( numFacesInElem == 6 ) + { + DirichletMFDFluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<>, IP_T, 6 >( + m_numComponents, m_numPhases, dofManager.rankOffset(), kernelFlags, + elemDofKey, getName(), nodePosition, faceManager, elemManager, stencilWrapper, + multiFluidBase, m_lengthTolerance, dt, localMatrix, localRhs ); + } + else + { + GEOS_ERROR( GEOS_FMT( "Unsupported number of faces per element: {}", numFacesInElem ) ); + } + } ); + } ); + + // 3) Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) arrayView1d< real64 const > const presFace = faceManager.getField< flow::facePressure >(); arrayView1d< real64 const > const presFaceBC = faceManager.getField< flow::bcPressure >(); + string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); arrayView1d< globalIndex const > const faceDofNumber = faceManager.getReference< array1d< globalIndex > >( faceDofKey ); arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); @@ -617,7 +720,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FaceManager & targetGroup, string const & ) { - // Using the field specification functions to apply the boundary conditions to the system fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, @@ -652,9 +754,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } ); } ); - } - void CompositionalMultiphaseHybridFVM::applyAquiferBC( real64 const time, real64 const dt, DofManager const & dofManager, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp index 800eb7c70e3..bd3d03f56d2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp @@ -29,7 +29,7 @@ #include "finiteVolume/BoundaryStencil.hpp" #include "mesh/ElementRegionManager.hpp" #include "mesh/ElementSubRegionBase.hpp" -#include "mesh/cell/CellElementSubRegion.hpp" +#include "mesh/CellElementSubRegion.hpp" #include "mesh/FaceManager.hpp" #include "mesh/NodeManager.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" @@ -153,7 +153,7 @@ class DirichletMFDFluxComputeKernel : public FluxComputeKernel< NUM_COMP, real64 const dt, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs, - BitFlags< KernelFlags > kernelFlags ) + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags ) : Base( numPhases, rankOffset, stencilWrapper, @@ -504,7 +504,7 @@ class DirichletMFDFluxComputeKernelFactory createAndLaunch( integer const numComps, integer const numPhases, globalIndex const rankOffset, - BitFlags< KernelFlags > kernelFlags, + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, string const & dofKey, string const & solverName, arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, @@ -532,12 +532,12 @@ class DirichletMFDFluxComputeKernelFactory ElementSubRegionBase const & subRegionBase = elemManager.getRegion( er ).getSubRegion( esr ); // Element geometry/connectivity arrays - ElementRegionManager::ElementViewConst< arrayView2d< real64 const > > elemCenter = - elemManager.constructArrayViewAccessor< real64, 2 >( CellElementSubRegion::viewKeyStruct::elementCenterString() ).toViewConst(); - ElementRegionManager::ElementViewConst< arrayView1d< real64 const > > elemVolume = - elemManager.constructArrayViewAccessor< real64, 1 >( CellElementSubRegion::viewKeyStruct::elementVolumeString() ).toViewConst(); - ElementRegionManager::ElementViewConst< arrayView2d< localIndex const > > elemToFaces = - elemManager.constructArrayViewAccessor< localIndex, 2 >( CellElementSubRegion::viewKeyStruct::faceListString() ).toViewConst(); + ElementRegionManager::ElementViewAccessor< arrayView2d< real64 const > > elemCenter = + elemManager.constructArrayViewAccessor< real64, 2 >( CellElementSubRegion::viewKeyStruct::elementCenterString() ); + ElementRegionManager::ElementViewAccessor< arrayView1d< real64 const > > elemVolume = + elemManager.constructArrayViewAccessor< real64, 1 >( CellElementSubRegion::viewKeyStruct::elementVolumeString() ); + ElementRegionManager::ElementViewAccessor< arrayView2d< localIndex const > > elemToFaces = + elemManager.constructArrayViewAccessor< localIndex, 2 >( CellElementSubRegion::viewKeyStruct::faceListString() ); // Face connectivity and multipliers ArrayOfArraysView< localIndex const > faceToNodes = faceManager.nodeList().toViewConst(); @@ -549,21 +549,24 @@ class DirichletMFDFluxComputeKernelFactory typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permeabilityAccessors( elemManager, solverName ); + typename kernelType::DofNumberAccessor dofNumberAccessor = + elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); + kernelType kernel( numPhases, rankOffset, faceManager, stencilWrapper, fluidWrapper, - elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ), + dofNumberAccessor, compFlowAccessors, multiFluidAccessors, capPressureAccessors, permeabilityAccessors, nodePosition, faceToNodes, - elemCenter, - elemVolume, - elemToFaces, + elemCenter.toNestedViewConst(), + elemVolume.toNestedViewConst(), + elemToFaces.toNestedViewConst(), transMultiplier, lengthTolerance, dt, From c127d36ffe1c7b85ca1f8d217caa2f7e3c90d460 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 22 Oct 2025 09:46:28 -0700 Subject: [PATCH 25/91] wip: inlcuding DirichletFluxKernel in CompositionalMultiphaseHybridFVMKernels Update CompositionalMultiphaseHybridFVM.cpp wip: generated Dirichlet kernels wip: remove fluid type dependency wip: remove fluid type dependency wip: compiling solution wip: remove separated kernel file wip: update constitutive on face data wip: Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVM.cpp Update CompositionalMultiphaseBaseFields.hpp Update CompositionalMultiphaseHybridFVM.cpp Update CompositionalMultiphaseBaseFields.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template wip: Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVM.cpp Update CompositionalMultiphaseHybridFVM.cpp wip: Update CompositionalMultiphaseHybridFVM.cpp wip: wip: compiling solution Update CompositionalMultiphaseHybridFVMKernels_impl.hpp Update CompositionalMultiphaseHybridFVM.cpp Update CompositionalMultiphaseHybridFVMKernels_impl.hpp wip: --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 2 +- .../CompositionalMultiphaseBaseFields.hpp | 34 + .../CompositionalMultiphaseHybridFVM.cpp | 428 ++++++++++--- ...ompositionalMultiphaseHybridFVM.cpp.backup | 380 ++++++++++++ ...aseHybridFVMKernels_dirichlet.cpp.template | 65 ++ ...activeCompositionalMultiphaseOBLFields.hpp | 8 - .../physicsSolvers/fluidFlow/kernelSpecs.json | 33 + ...ompositionalMultiphaseHybridFVMKernels.hpp | 140 +++++ ...itionalMultiphaseHybridFVMKernels_impl.hpp | 531 +++++++++++++++- .../DirichletMFDFluxComputeKernel.hpp | 587 ------------------ 10 files changed, 1514 insertions(+), 694 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 2f813514d29..3dcef5bca76 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -75,7 +75,6 @@ set( fluidFlowSolvers_headers kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp kernels/compositional/DiffusionDispersionFluxComputeKernel.hpp kernels/compositional/DirichletFluxComputeKernel.hpp - kernels/compositional/DirichletMFDFluxComputeKernel.hpp kernels/compositional/DissipationFluxComputeKernel.hpp kernels/compositional/FluidUpdateKernel.hpp kernels/compositional/FluidUpdateKernel.hpp @@ -170,6 +169,7 @@ list( APPEND kernelTemplateFileList CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template CompositionalMultiphaseHybridFVMKernels_flux.cpp.template + CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template ReactiveCompositionalMultiphaseOBLKernels.cpp.template ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp index 3f520747ae8..31120bcbd40 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp @@ -89,6 +89,14 @@ DECLARE_FIELD( globalCompFraction_n, // NO_WRITE, // "Global component fraction updates at the previous sequential iteration" ); +DECLARE_FIELD( bcGlobalCompFraction, + "bcGlobalCompFraction", + array2dLayoutComp, + 0, + NOPLOT, + WRITE_AND_READ, + "Boundary condition global component fraction" ); + DECLARE_FIELD( faceGlobalCompFraction, "faceGlobalCompFraction", array2dLayoutComp, @@ -137,6 +145,32 @@ DECLARE_FIELD( dPhaseMobility, NO_WRITE, "Derivative of phase volume fraction with respect to pressure, temperature, global component density" ); +// Face-based properties for boundary conditions +// These store constitutive properties evaluated at BC face conditions +DECLARE_FIELD( facePhaseMobility, + "facePhaseMobility", + array2dLayoutPhase, + 0, + NOPLOT, + NO_WRITE, + "Phase mobility at boundary faces evaluated at BC conditions" ); + +DECLARE_FIELD( facePhaseMassDensity, + "facePhaseMassDensity", + array2dLayoutPhase, + 0, + NOPLOT, + NO_WRITE, + "Phase mass density at boundary faces evaluated at BC conditions" ); + +DECLARE_FIELD( facePhaseCompFraction, + "facePhaseCompFraction", + array3dLayoutPhaseComp, + 0, + NOPLOT, + NO_WRITE, + "Phase component fraction at boundary faces evaluated at BC conditions" ); + // this is needed for time step selector DECLARE_FIELD( phaseVolumeFraction_n, "phaseVolumeFraction_n", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 1fc19fdfe95..ec141d010b6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -22,6 +22,7 @@ #include "mesh/DomainPartition.hpp" #include "constitutive/ConstitutivePassThru.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "constitutive/fluid/multifluid/MultiFluidSelector.hpp" #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" @@ -37,7 +38,6 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/SolutionScalingKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/SolutionCheckKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/ResidualNormKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp" #include "mesh/CellElementSubRegion.hpp" /** @@ -77,9 +77,34 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) faceManager.registerField< flow::facePressure_n >( getName() ); - // Register the bc face data + // Register the face data for global component fraction + faceManager.registerField< flow::faceGlobalCompFraction >( getName() ); + + // Register the face data for temperature + faceManager.registerField< flow::faceTemperature >( getName() ); + + + + // Register the bc face data for pressure faceManager.registerField< flow::bcPressure >( getName() ); + // Register the bc face data for global component fraction + faceManager.registerField< flow::bcGlobalCompFraction >( getName() ); + + // Register the bc face data for temperature + faceManager.registerField< flow::bcTemperature >( getName() ); + + // Register face-based constitutive properties for BC faces + // These will store fluid properties evaluated at BC conditions + faceManager.registerField< flow::facePhaseMobility >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + faceManager.registerField< flow::facePhaseMassDensity >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + faceManager.registerField< flow::facePhaseCompFraction >( getName() ). + reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents ); + // auxiliary data for the buoyancy coefficient faceManager.registerField< flow::mimGravityCoefficient >( getName() ); } ); @@ -577,10 +602,8 @@ void CompositionalMultiphaseHybridFVM::applyBoundaryConditions( real64 const tim CompositionalMultiphaseBase::applyBoundaryConditions( time_n, dt, domain, dofManager, localMatrix, localRhs ); - if( !m_keepVariablesConstantDuringInitStep ) - { - applyFaceDirichletBC( time_n, dt, dofManager, domain, localMatrix, localRhs ); - } + // Apply face-based Dirichlet boundary conditions + applyFaceDirichletBC( time_n, dt, dofManager, domain, localMatrix, localRhs ); } void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n, @@ -592,23 +615,21 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n { GEOS_MARK_FUNCTION; - using namespace isothermalCompositionalMultiphaseFVMKernels; + using namespace compositionalMultiphaseHybridFVMKernels; using namespace mimeticInnerProduct; - // Build kernel flags (capillary pressure not supported here) - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; - if( m_useTotalMassEquation ) - { - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); - } - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - + + // Get the inner product type from the discretization NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); + string const & innerProductType = hmDiscretization.getReference< string >( HybridMimeticDiscretization::viewKeyStruct::innerProductTypeString() ); + + string const elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + globalIndex const rankOffset = dofManager.rankOffset(); - // Log message similar to the cell-centered FVM version + // Log message for Dirichlet BC application static char const faceBcLogMessage[] = "CompositionalMultiphaseHybridFVM {}: at time {}s, " "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " @@ -616,90 +637,16 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n "\nThe total number of target faces (including ghost faces) is {}." "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; - // For each mesh target, first apply face fields and assemble MFD Dirichlet fluxes, then keep strong enforcement of face bcPressure + // Apply Dirichlet BC by computing boundary fluxes this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, - string_array const & ) + string_array const & regionNames ) { - ElementRegionManager & elemManager = mesh.getElemManager(); - NodeManager const & nodeManager = mesh.getNodeManager(); FaceManager & faceManager = mesh.getFaceManager(); + NodeManager const & nodeManager = mesh.getNodeManager(); + ElementRegionManager & elemManager = mesh.getElemManager(); - // 1) Apply boundary field values to face-centered fields (pressure, composition, temperature) - applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, - flow::pressure::key(), flow::facePressure::key() ); - applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, - flow::globalCompFraction::key(), flow::faceGlobalCompFraction::key() ); - // NOTE: current MFD compositional implementation is isothermal; thermal support will be added later. - applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, - flow::temperature::key(), flow::faceTemperature::key() ); - - // 2) Launch MFD Dirichlet flux kernel per BC face set using the selected inner product - fsManager.apply< FaceManager >( time_n + dt, - mesh, - flow::pressure::key(), - [&] ( FieldSpecificationBase const &, - string const & setName, - SortedArrayView< localIndex const > const &, - FaceManager &, - string const & ) - { - BoundaryStencil const & stencil = fluxApprox.getStencil< BoundaryStencil >( mesh, setName ); - if( stencil.size() == 0 ) - { - return; - } - - // Select fluid model from first cell adjacent to this face set (same approach as in FVM Dirichlet) - localIndex const er = stencil.getElementRegionIndices()( 0, BoundaryStencil::Order::ELEM ); - localIndex const esr = stencil.getElementSubRegionIndices()( 0, BoundaryStencil::Order::ELEM ); - ElementSubRegionBase & subRegion = elemManager.getRegion( er ).getSubRegion( esr ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & multiFluidBase = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - - BoundaryStencilWrapper const stencilWrapper = stencil.createKernelWrapper(); - string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // Inner product selection and NF dispatch - HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); - MimeticInnerProductBase const & mimIP = - hmDiscretization.getReference< MimeticInnerProductBase >( HybridMimeticDiscretization::viewKeyStruct::innerProductString() ); - - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition = nodeManager.referencePosition(); - integer const numFacesInElem = elemManager.getRegion( er ).getSubRegion< CellElementSubRegion >( esr ).numFacesPerElement(); - - mimeticInnerProductReducedDispatch( mimIP, [&] ( auto const ipType ) - { - using IP_T = std::remove_const_t< TYPEOFREF( ipType ) >; - if( numFacesInElem == 4 ) - { - DirichletMFDFluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<>, IP_T, 4 >( - m_numComponents, m_numPhases, dofManager.rankOffset(), kernelFlags, - elemDofKey, getName(), nodePosition, faceManager, elemManager, stencilWrapper, - multiFluidBase, m_lengthTolerance, dt, localMatrix, localRhs ); - } - else if( numFacesInElem == 5 ) - { - DirichletMFDFluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<>, IP_T, 5 >( - m_numComponents, m_numPhases, dofManager.rankOffset(), kernelFlags, - elemDofKey, getName(), nodePosition, faceManager, elemManager, stencilWrapper, - multiFluidBase, m_lengthTolerance, dt, localMatrix, localRhs ); - } - else if( numFacesInElem == 6 ) - { - DirichletMFDFluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<>, IP_T, 6 >( - m_numComponents, m_numPhases, dofManager.rankOffset(), kernelFlags, - elemDofKey, getName(), nodePosition, faceManager, elemManager, stencilWrapper, - multiFluidBase, m_lengthTolerance, dt, localMatrix, localRhs ); - } - else - { - GEOS_ERROR( GEOS_FMT( "Unsupported number of faces per element: {}", numFacesInElem ) ); - } - } ); - } ); - - // 3) Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) + // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) arrayView1d< real64 const > const presFace = faceManager.getField< flow::facePressure >(); arrayView1d< real64 const > const presFaceBC = @@ -753,8 +700,297 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } ); + + + + + // Get node positions + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); + + // Get face data + ArrayOfArraysView< localIndex const > const faceToNodes = faceManager.nodeList().toViewConst(); + arrayView2d< localIndex const > const elemRegionList = faceManager.elementRegionList(); + arrayView2d< localIndex const > const elemSubRegionList = faceManager.elementSubRegionList(); + arrayView2d< localIndex const > const elemList = faceManager.elementList(); + + arrayView1d< real64 const > const transMultiplier = faceManager.getReference< array1d< real64 > >( fields::flow::transMultiplier::key() ); + + // Apply boundary values to face fields first + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::bcPressure::key(), flow::facePressure::key() ); + + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::bcGlobalCompFraction::key(), flow::faceGlobalCompFraction::key() ); + + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::bcTemperature::key(), flow::faceTemperature::key() ); + + // Get face boundary values + arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); + arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); + arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); + arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); + +// // Print all entries in faceCompFrac +// std::cout << "faceCompFrac array size: " << faceCompFrac.size(0) << " x " << faceCompFrac.size(1) << std::endl; +// for( localIndex iface = 0; iface < faceCompFrac.size(0); ++iface ) +// { +//// std::ostringstream oss; +// std::cout << "Face " << iface << ": ["; +// for( localIndex ic = 0; ic < faceCompFrac.size(1); ++ic ) +// { +// std::cout << faceCompFrac[iface][ic]; +// if( ic < faceCompFrac.size(1) - 1 ) +// { +// std::cout << ", "; +// } +// } +// std::cout << "]"; +// std::cout << std::endl; +//// GEOS_LOG_RANK_0( oss.str() ); +// } + + // Loop over regions and apply Dirichlet flux kernel + elemManager.forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const erIndex, + CellElementSubRegion & subRegion ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + + string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityModel = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + + string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relperm = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); + + real64 const lengthTolerance = m_lengthTolerance; + + // Get all face sets that have Dirichlet BCs + std::set< string > bcFaceSets; + fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) + { + string const & fieldName = fs.getFieldName(); + if( fieldName == flow::bcPressure::key() || + fieldName == flow::bcGlobalCompFraction::key() || + fieldName == flow::bcTemperature::key() ) + { + for( string const & setName : fs.getSetNames() ) + { + bcFaceSets.insert( setName ); + } + } + } ); + + // Get writable face arrays for storing BC face properties + arrayView2d< real64, compflow::USD_PHASE > facePhaseMob = + faceManager.getField< flow::facePhaseMobility >(); + arrayView2d< real64, compflow::USD_PHASE > facePhaseMassDens = + faceManager.getField< flow::facePhaseMassDensity >(); + arrayView3d< real64, compflow::USD_PHASE_COMP > facePhaseCompFrac = + faceManager.getField< flow::facePhaseCompFraction >(); + + // Evaluate constitutive properties at BC face conditions for each face set + for( string const & setName : bcFaceSets ) + { + SortedArrayView< localIndex const > const targetSet = faceManager.getSet( setName ).toViewConst(); + if( targetSet.size() == 0 ) + continue; + + // Call evaluateBCFaceProperties to compute face properties at BC conditions + constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) + { + integer constexpr NUM_COMP = NC(); + + auto evaluateWithPhases = [&]( auto NP_VALUE ) + { + integer constexpr NUM_PHASES = decltype( NP_VALUE )::value; + + compositionalMultiphaseHybridFVMKernels::evaluateBCFaceProperties< NUM_COMP, NUM_PHASES > + ( m_numPhases, + targetSet, + facePres, + faceTemp, + faceCompFrac, + elemRegionList, + elemSubRegionList, + elemList, + erIndex, + subRegion.getIndexInParent(), + fluid, + relperm, + facePhaseMob, + facePhaseMassDens, + facePhaseCompFrac ); + }; + + if( m_numPhases == 2 ) + { + evaluateWithPhases( std::integral_constant< integer, 2 >() ); + } + else if( m_numPhases == 3 ) + { + evaluateWithPhases( std::integral_constant< integer, 3 >() ); + } + } ); + } + + // Get element-based fields for flux computation + arrayView1d< real64 const > const elemPres = subRegion.getField< flow::pressure >(); + arrayView2d< real64 const, compflow::USD_COMP > const elemCompDens = subRegion.getField< flow::globalCompDensity >(); + arrayView1d< real64 const > const elemGravCoef = subRegion.getField< flow::gravityCoefficient >(); + arrayView2d< localIndex const > const elemToFaces = subRegion.faceList(); + + // Get fluid properties at element centers + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const elemPhaseDens = + fluid.phaseDensity(); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const elemPhaseMassDens = + fluid.phaseMassDensity(); + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > const elemPhaseCompFrac = + fluid.phaseCompFraction(); + + // Get mobility from flow solver + arrayView2d< real64 const, compflow::USD_PHASE > const elemPhaseMob = + subRegion.getField< flow::phaseMobility >(); + + // Get DOF numbers + arrayView1d< globalIndex const > const elemDofNumber = + subRegion.getReference< array1d< globalIndex > >( elemDofKey ); + + // Get pre-computed fluid properties at BC faces + arrayView2d< real64 const, compflow::USD_PHASE > const facePhaseMobField = + faceManager.getField< flow::facePhaseMobility >(); + arrayView2d< real64 const, compflow::USD_PHASE > const facePhaseMassDensField = + faceManager.getField< flow::facePhaseMassDensity >(); + arrayView3d< real64 const, compflow::USD_PHASE_COMP > const facePhaseCompFracField = + faceManager.getField< flow::facePhaseCompFraction >(); + +// // After facePhaseMob is defined (around line 615) +// std::cout << "facePhaseMob array size: " << facePhaseMob.size(0) << " x " << facePhaseMob.size(1) << std::endl; +// for( localIndex iface = 0; iface < facePhaseMob.size(0); ++iface ) +// { +// std::cout << "Face " << iface << " facePhaseMob: ["; +// for( localIndex ip = 0; ip < facePhaseMob.size(1); ++ip ) +// { +// std::cout << facePhaseMob[iface][ip]; +// if( ip < facePhaseMob.size(1) - 1 ) +// { +// std::cout << ", "; +// } +// } +// std::cout << "]" << std::endl; +// } +// +// // After facePhaseMobField is defined (around line 728) +// std::cout << "facePhaseMobField array size: " << facePhaseMobField.size(0) << " x " << facePhaseMobField.size(1) << std::endl; +// for( localIndex iface = 0; iface < facePhaseMobField.size(0); ++iface ) +// { +// std::cout << "Face " << iface << " facePhaseMobField: ["; +// for( localIndex ip = 0; ip < facePhaseMobField.size(1); ++ip ) +// { +// std::cout << facePhaseMobField[iface][ip]; +// if( ip < facePhaseMobField.size(1) - 1 ) +// { +// std::cout << ", "; +// } +// } +// std::cout << "]" << std::endl; +// } + + // Apply Dirichlet boundary fluxes for each face set using DirichletFluxKernel + for( string const & setName : bcFaceSets ) + { + SortedArrayView< localIndex const > const targetSet = faceManager.getSet( setName ).toViewConst(); + if( targetSet.size() == 0 ) + continue; + + GEOS_LOG_RANK_0( "Applying Dirichlet BC to face set '" << setName << "' with " << targetSet.size() << " faces" ); + + // Launch the Dirichlet flux kernel with compile-time dispatch + constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) + { + integer constexpr NUM_COMP = NC(); + + typename DirichletFluxKernel::CompFlowAccessors compFlowAccessors( elemManager, getName() ); + typename DirichletFluxKernel::MultiFluidAccessors multiFluidAccessors( elemManager, getName() ); + ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > elemDofNumberAccessor = + elemManager.constructArrayViewAccessor< globalIndex, 1 >( elemDofKey ); + + localIndex const numFacesPerElement = subRegion.numFacesPerElement(); + + auto launchWithPhases = [&]( auto NP_VALUE ) + { + integer constexpr NP = decltype( NP_VALUE )::value; + + auto launchKernel = [&]( auto IP_TYPE_WRAPPER, auto NF_VALUE ) + { + using IP_TYPE = decltype( IP_TYPE_WRAPPER ); + integer constexpr NF = decltype( NF_VALUE )::value; + + DirichletFluxKernel::launch< NF, NUM_COMP, NP, IP_TYPE > + ( m_numPhases, + erIndex, + subRegion.getIndexInParent(), + subRegion, + permeabilityModel, + faceManager, + targetSet, + facePres, + faceTemp, + faceCompFrac, + facePhaseMobField, + facePhaseMassDensField, + facePhaseCompFracField, + nodePosition, + faceToNodes, + elemRegionList, + elemSubRegionList, + elemList, + faceDofNumber, + faceGravCoef, + transMultiplier, + lengthTolerance, + dt, + rankOffset, + m_useTotalMassEquation, + compFlowAccessors, + multiFluidAccessors, + elemDofNumberAccessor.toNestedViewConst(), + localMatrix, + localRhs ); + }; + + if( innerProductType == "TPFA" ) + { + if( numFacesPerElement == 4 ) + launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 4 >{} ); + else if( numFacesPerElement == 5 ) + launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 5 >{} ); + else if( numFacesPerElement == 6 ) + launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 6 >{} ); + } + else if( innerProductType == "BDVLM" || innerProductType == "BdVLM" ) + { + if( numFacesPerElement == 4 ) + launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 4 >{} ); + else if( numFacesPerElement == 5 ) + launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 5 >{} ); + else if( numFacesPerElement == 6 ) + launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 6 >{} ); + } + }; + + if( m_numPhases == 2 ) + launchWithPhases( std::integral_constant< integer, 2 >{} ); + else if( m_numPhases == 3 ) + launchWithPhases( std::integral_constant< integer, 3 >{} ); + else + GEOS_ERROR( "Unsupported number of phases: " << m_numPhases ); + } ); + } + } ); } ); } + void CompositionalMultiphaseHybridFVM::applyAquiferBC( real64 const time, real64 const dt, DofManager const & dofManager, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup new file mode 100644 index 00000000000..6aabb50eaed --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup @@ -0,0 +1,380 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file CompositionalMultiphaseHybridFVM.cpp + */ + +#include "CompositionalMultiphaseHybridFVM.hpp" + +#include "mesh/DomainPartition.hpp" +#include "constitutive/ConstitutivePassThru.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" +#include "fieldSpecification/AquiferBoundaryCondition.hpp" +#include "fieldSpecification/FieldSpecificationManager.hpp" +#include "finiteVolume/HybridMimeticDiscretization.hpp" +#include "finiteVolume/MimeticInnerProductDispatch.hpp" +#include "finiteVolume/FluxApproximationBase.hpp" +#include "finiteVolume/BoundaryStencil.hpp" +#include "mesh/mpiCommunications/CommunicationTools.hpp" +#include "physicsSolvers/LogLevelsInfo.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/SolutionScalingKernel.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/SolutionCheckKernel.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/ResidualNormKernel.hpp" +#include "mesh/CellElementSubRegion.hpp" + +/** + * @namespace the geos namespace that encapsulates the majority of the code + */ +namespace geos +{ + +using namespace dataRepository; +using namespace constitutive; +using namespace fields; +using namespace isothermalCompositionalMultiphaseBaseKernels; +using namespace compositionalMultiphaseHybridFVMKernels; +using namespace mimeticInnerProduct; + +CompositionalMultiphaseHybridFVM::CompositionalMultiphaseHybridFVM( const std::string & name, + Group * const parent ): + CompositionalMultiphaseBase( name, parent ), + m_lengthTolerance( 0 ) +{ + m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::compositionalMultiphaseHybridFVM; +} + +void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) +{ + // 1) Register the elem-centered data + CompositionalMultiphaseBase::registerDataOnMesh( meshBodies ); + + // 2) Register the face data + meshBodies.forSubGroups< MeshBody >( [&]( MeshBody & meshBody ) + { + MeshLevel & meshLevel = meshBody.getBaseDiscretization(); + + FaceManager & faceManager = meshLevel.getFaceManager(); + + // primary variables: face pressure changes + faceManager.registerField< flow::facePressure_n >( getName() ); + + // Register the bc face data + faceManager.registerField< flow::bcPressure >( getName() ); + + // auxiliary data for the buoyancy coefficient + faceManager.registerField< flow::mimGravityCoefficient >( getName() ); + } ); +} + +void CompositionalMultiphaseHybridFVM::initializePreSubGroups() +{ + CompositionalMultiphaseBase::initializePreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + + GEOS_THROW_IF( !fvManager.hasGroup< HybridMimeticDiscretization >( m_discretizationName ), + getCatalogName() << " " << getDataContext() << + ": the HybridMimeticDiscretization must be selected with CompositionalMultiphaseHybridFVM", + InputError ); + + GEOS_THROW_IF( m_hasCapPressure, + getCatalogName() << " " << getDataContext() << + ": capillary pressure is not yet supported by CompositionalMultiphaseHybridFVM", + InputError ); + + HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); + MimeticInnerProductBase const & mimeticInnerProductBase = + hmDiscretization.getReference< MimeticInnerProductBase >( HybridMimeticDiscretization::viewKeyStruct::innerProductString() ); + if( dynamicCast< QuasiRTInnerProduct const * >( &mimeticInnerProductBase ) || + dynamicCast< QuasiTPFAInnerProduct const * >( &mimeticInnerProductBase ) || + dynamicCast< SimpleInnerProduct const * >( &mimeticInnerProductBase ) ) + { + GEOS_ERROR( getCatalogName() << " " << getDataContext() << + "The QuasiRT, QuasiTPFA, and Simple inner products are only available in SinglePhaseHybridFVM" ); + } + + m_lengthTolerance = domain.getMeshBody( 0 ).getGlobalLengthScale() * 1e-8; +} + +void CompositionalMultiphaseHybridFVM::applyBoundaryConditions( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + // Apply face-based Dirichlet boundary conditions + if( m_keepFlowVariablesConstantDuringInitStep ) + { + applyFaceDirichletBC( time_n, dt, dofManager, domain, localMatrix, localRhs ); + } +} + +void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + using namespace compositionalMultiphaseHybridFVMKernels; + using namespace mimeticInnerProduct; + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + // Get the inner product type from the discretization + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); + string const & innerProductType = hmDiscretization.getReference< string >( HybridMimeticDiscretization::viewKeyStruct::innerProductTypeString() ); + + string const elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + globalIndex const rankOffset = dofManager.rankOffset(); + + // Log message for Dirichlet BC application + static char const faceBcLogMessage[] = + "CompositionalMultiphaseHybridFVM {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " + "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " + "\nThe total number of target faces (including ghost faces) is {}." + "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; + + // Apply Dirichlet BC by computing boundary fluxes + this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + FaceManager & faceManager = mesh.getFaceManager(); + NodeManager const & nodeManager = mesh.getNodeManager(); + ElementRegionManager & elemManager = mesh.getElemManager(); + + // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) + arrayView1d< real64 const > const presFace = + faceManager.getField< flow::facePressure >(); + arrayView1d< real64 const > const presFaceBC = + faceManager.getField< flow::bcPressure >(); + string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); + arrayView1d< globalIndex const > const faceDofNumber = + faceManager.getReference< array1d< globalIndex > >( faceDofKey ); + arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); + + globalIndex const rankOffset = dofManager.rankOffset(); + + fsManager.apply< FaceManager >( time_n + dt, + mesh, + flow::bcPressure::key(), + [&] ( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + FaceManager & targetGroup, + string const & ) + { + // Using the field specification functions to apply the boundary conditions to the system + fs.applyFieldValue< FieldSpecificationEqual, + parallelDevicePolicy<> >( targetSet, + time_n + dt, + targetGroup, + flow::bcPressure::key() ); + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + + localIndex const kf = targetSet[a]; + if( faceGhostRank[kf] >= 0 ) + { + return; + } + + // Get the dof number of this face + globalIndex const dofIndex = faceDofNumber[kf]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // Apply field value to the lhs and rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + presFaceBC[kf], + presFace[kf] ); + localRhs[localRow] = rhsValue; + } ); + + } ); + + // Get node positions + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); + + // Get face data + ArrayOfArraysView< localIndex const > const faceToNodes = faceManager.nodeList().toViewConst(); + arrayView2d< localIndex const > const elemRegionList = faceManager.elementRegionList(); + arrayView2d< localIndex const > const elemSubRegionList = faceManager.elementSubRegionList(); + arrayView2d< localIndex const > const elemList = faceManager.elementList(); + + arrayView1d< real64 const > const transMultiplier = faceManager.getReference< array1d< real64 > >( fields::flow::transMultiplier::key() ); + + // Apply boundary values to face fields first + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::pressure::key(), flow::facePressure::key() ); + + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::globalCompFraction::key(), flow::faceGlobalCompFraction::key() ); + + applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, + flow::temperature::key(), flow::faceTemperature::key() ); + + // Get face boundary values + arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); + arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); + arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); + arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); + + // Loop over regions and apply Dirichlet flux kernel + elemManager.forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const er, + CellElementSubRegion & subRegion ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + + string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityModel = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + + real64 const lengthTolerance = m_lengthTolerance; + + // Get all face sets that have Dirichlet BCs + std::set< string > bcFaceSets; + fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) + { + if( fs.getCatalogName() == catalogName() ) + { + string const & fieldName = fs.getFieldName(); + if( fieldName == flow::pressure::key() || + fieldName == flow::globalCompFraction::key() || + fieldName == flow::temperature::key() ) + { + for( string const & setName : fs.getSetNames() ) + { + bcFaceSets.insert( setName ); + } + } + } + } ); + + // Apply Dirichlet flux kernel for each face set + for( string const & setName : bcFaceSets ) + { + SortedArrayView< localIndex const > targetSet = faceManager.getSet( setName ).toViewConst(); + if( targetSet.size() == 0 ) + continue; + + // Launch the Dirichlet flux kernel + constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) + { + integer constexpr NUM_COMP = NC(); + + typename DirichletFluxKernel::CompFlowAccessors compFlowAccessors( elemManager, getName() ); + typename DirichletFluxKernel::MultiFluidAccessors multiFluidAccessors( elemManager, getName() ); + ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > elemDofNumberAccessor = + elemManager.constructArrayViewAccessor< globalIndex, 1 >( elemDofKey ); + + // Determine number of faces per element from subregion type + localIndex const numFacesPerElement = subRegion.numFacesPerElement(); + + // Dispatch based on number of phases (runtime -> compile-time) + auto launchWithPhases = [&]( auto NP_VALUE ) + { + integer constexpr NP = decltype( NP_VALUE )::value; + + auto launchKernel = [&]( auto IP_TYPE_WRAPPER, auto NF_VALUE ) + { + using IP_TYPE = decltype( IP_TYPE_WRAPPER ); + integer constexpr NF = decltype( NF_VALUE )::value; + + DirichletFluxKernel::launch< NF, NUM_COMP, NP, IP_TYPE > + ( m_numPhases, + er, + subRegion.getIndexInParent(), + subRegion, + permeabilityModel, + faceManager, + targetSet, + facePres, + faceTemp, + faceCompFrac, + nodePosition, + faceToNodes, + elemRegionList, + elemSubRegionList, + elemList, + faceDofNumber, + faceGravCoef, + transMultiplier, + lengthTolerance, + dt, + rankOffset, + m_useTotalMassEquation, + compFlowAccessors, + multiFluidAccessors, + elemDofNumberAccessor.toNestedViewConst(), + localMatrix, + localRhs ); + }; + + // Dispatch based on inner product type and number of faces + if( innerProductType == "TPFA" ) + { + if( numFacesPerElement == 4 ) + launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 4 >{} ); + else if( numFacesPerElement == 5 ) + launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 5 >{} ); + else if( numFacesPerElement == 6 ) + launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 6 >{} ); + } + else if( innerProductType == "BDVLM" || innerProductType == "BdVLM" ) + { + if( numFacesPerElement == 4 ) + launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 4 >{} ); + else if( numFacesPerElement == 5 ) + launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 5 >{} ); + else if( numFacesPerElement == 6 ) + launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 6 >{} ); + } + }; + + // Dispatch number of phases + if( m_numPhases == 2 ) + launchWithPhases( std::integral_constant< integer, 2 >{} ); + else if( m_numPhases == 3 ) + launchWithPhases( std::integral_constant< integer, 3 >{} ); + else + GEOS_ERROR( "Unsupported number of phases: " << m_numPhases ); + } ); + } + } ); + } ); +} + +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template new file mode 100644 index 00000000000..494fadcc796 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template @@ -0,0 +1,65 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp" + +namespace geos +{ +namespace compositionalMultiphaseHybridFVMKernels +{ + constexpr int NF = @NFACES@; + constexpr int NC = @NCOMPS@; + constexpr int NP = @NPHASES@; + using IP_TYPE = @IP_TYPE@; + + @EXTERN@ + template + void + DirichletFluxKernel:: + launch< NF, NC, NP, IP_TYPE >( integer const numPhases, + localIndex const er, + localIndex const esr, + CellElementSubRegion const & subRegion, + constitutive::PermeabilityBase const & permeabilityModel, + FaceManager const & faceManager, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, + ArrayOfArraysView< localIndex const > const & faceToNodes, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + arrayView1d< globalIndex const > const & faceDofNumber, + arrayView1d< real64 const > const & faceGravCoef, + arrayView1d< real64 const > const & transMultiplier, + real64 const lengthTolerance, + real64 const dt, + globalIndex const rankOffset, + integer const useTotalMassEquation, + CompFlowAccessors const & compFlowAccessors, + MultiFluidAccessors const & multiFluidAccessors, + ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ); + +} +} + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBLFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBLFields.hpp index 531fd4054ec..9a50003023a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBLFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBLFields.hpp @@ -39,14 +39,6 @@ using array2dLayoutComp = array2d< real64, compflow::LAYOUT_COMP >; using array2dLayoutOBLOpVals = array2d< real64, compflow::LAYOUT_OBL_OPERATOR_VALUES >; using array3dLayoutOBLOpDers = array3d< real64, compflow::LAYOUT_OBL_OPERATOR_DERIVATIVES >; -DECLARE_FIELD( bcGlobalCompFraction, - "bcGlobalCompFraction", - array2dLayoutComp, - 0, - NOPLOT, - WRITE_AND_READ, - "Boundary condition global component fraction" ); - DECLARE_FIELD( referencePorosity, "referencePorosity", array1d< real64 >, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index c398a1e7bd9..a8602aab977 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -143,6 +143,39 @@ "explicit": [] }, + "CompositionalMultiphaseHybridFVMKernels_dirichlet": { + "vars": [ + "NFACES", + "NCOMPS", + "NPHASES", + "IP_TYPE" + ], + "constants": [], + "combinations": { + "NFACES": [ + 4, + 5, + 6 + ], + "NCOMPS": [ + 1, + 2, + 3, + 4, + 5 + ], + "NPHASES": [ + 2, + 3 + ], + "IP_TYPE": [ + "mimeticInnerProduct::TPFAInnerProduct", + "mimeticInnerProduct::BdVLMInnerProduct" + ] + }, + "explicit": [] + }, + "ReactiveCompositionalMultiphaseOBLKernels": { "vars": [ "NAME", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 2d7fcccc661..71ce58e458a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -544,6 +544,106 @@ struct AssemblerKernel }; +/******************************** DirichletFluxKernel ********************************/ + +struct DirichletFluxKernel +{ + + /** + * @brief The type for element-based non-constitutive data parameters. + * Consists entirely of ArrayView's. + * + * Can be converted from ElementRegionManager::ElementViewAccessor + * by calling .toView() or .toViewConst() on an accessor instance + */ + template< typename VIEWTYPE > + using ElementViewConst = ElementRegionManager::ElementViewConst< VIEWTYPE >; + + using CompFlowAccessors = + StencilAccessors< fields::flow::phaseMobility, + fields::flow::dPhaseMobility, + fields::flow::dGlobalCompFraction_dGlobalCompDensity >; + + using MultiFluidAccessors = + StencilMaterialAccessors< constitutive::MultiFluidBase, + fields::multifluid::phaseDensity, + fields::multifluid::dPhaseDensity, + fields::multifluid::phaseMassDensity, + fields::multifluid::dPhaseMassDensity, + fields::multifluid::phaseCompFraction, + fields::multifluid::dPhaseCompFraction >; + + /** + * @brief Compute the Dirichlet boundary fluxes for compositional multiphase flow + * @tparam NF number of faces per element + * @tparam NC number of components + * @tparam NP number of phases + * @tparam IP_TYPE mimetic inner product type + * @param[in] numPhases number of phases + * @param[in] er index of this element's region + * @param[in] esr index of this element's subregion + * @param[in] subRegion the subRegion + * @param[in] permeabilityModel the permeability model + * @param[in] faceManager the face manager + * @param[in] boundaryFaceSet set of faces on the Dirichlet boundary + * @param[in] facePres prescribed face pressures + * @param[in] faceTemp prescribed face temperatures + * @param[in] faceCompFrac prescribed face component fractions + * @param[in] facePhaseMob prescribed face phase mobilities + * @param[in] facePhaseMassDens prescribed face phase mass densities + * @param[in] facePhaseCompFrac prescribed face phase component fractions + * @param[in] nodePosition node positions + * @param[in] faceToNodes face to nodes map + * @param[in] elemRegionList face to element region map + * @param[in] elemSubRegionList face to element subregion map + * @param[in] elemList face to element index map + * @param[in] faceDofNumber face DOF numbers + * @param[in] transMultiplier transmissibility multipliers + * @param[in] lengthTolerance geometric tolerance + * @param[in] dt time step size + * @param[in] rankOffset MPI rank offset + * @param[in] useTotalMassEquation flag for total mass equation + * @param[in] compFlowAccessors accessor for comp flow fields + * @param[in] multiFluidAccessors accessor for fluid properties + * @param[in] elemDofNumber element DOF numbers + * @param[inout] localMatrix the local matrix + * @param[inout] localRhs the local RHS vector + */ + template< integer NF, integer NC, integer NP, typename IP_TYPE > + static void + launch( integer const numPhases, + localIndex const er, + localIndex const esr, + CellElementSubRegion const & subRegion, + constitutive::PermeabilityBase const & permeabilityModel, + FaceManager const & faceManager, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, + ArrayOfArraysView< localIndex const > const & faceToNodes, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + arrayView1d< globalIndex const > const & faceDofNumber, + arrayView1d< real64 const > const & faceGravCoef, + arrayView1d< real64 const > const & transMultiplier, + real64 const lengthTolerance, + real64 const dt, + globalIndex const rankOffset, + integer const useTotalMassEquation, + CompFlowAccessors const & compFlowAccessors, + MultiFluidAccessors const & multiFluidAccessors, + ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ); + +}; + /******************************** FluxKernel ********************************/ struct FluxKernel @@ -1223,6 +1323,46 @@ void kernelLaunchSelector( integer numFacesInElem, integer numComps, integer num } } +/******************************** EvaluateBCFacePropertiesKernel ********************************/ + +/** + * @brief Evaluate constitutive properties at BC face conditions + * @tparam NC number of components + * @tparam NP number of phases + * @param[in] numPhases number of phases + * @param[in] boundaryFaceSet set of boundary faces + * @param[in] facePres face pressures at BC + * @param[in] faceTemp face temperatures at BC + * @param[in] faceCompFrac face component fractions at BC + * @param[in] elemRegionList face to element region list + * @param[in] elemSubRegionList face to element subregion list + * @param[in] elemList face to element list + * @param[in] er target element region index + * @param[in] esr target element subregion index + * @param[in] fluid multifluid model + * @param[in] relperm relative permeability model + * @param[out] facePhaseMob output: face phase mobility at BC + * @param[out] facePhaseMassDens output: face phase mass density at BC + * @param[out] facePhaseCompFrac output: face phase component fraction at BC + */ +template< integer NC, integer NP > +void +evaluateBCFaceProperties( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + } // namespace compositionalMultiphaseHybridFVMKernels } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 91d6475b76d..6fd1ade12eb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -26,6 +26,8 @@ #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" #include "physicsSolvers/fluidFlow/kernels/HybridFVMHelperKernels.hpp" +#include "constitutive/fluid/multifluid/MultiFluidSelector.hpp" +#include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" namespace geos { @@ -446,7 +448,7 @@ UpwindingHelper:: localIndex ( & totalMobIds )[ NP ][ 3 ], localIndex ( & totalMobPos )[ NP ] ) { - if( NP == 2 ) + if constexpr( NP == 2 ) { if( gravTerm[0][0] > 0 ) { @@ -471,7 +473,7 @@ UpwindingHelper:: totalMobPos[1] = Pos::LOCAL; } } - else if( NP == 3 ) + else if constexpr( NP == 3 ) { // TODO Francois: this should be improved // currently this implements the algorithm proposed by SH Lee @@ -1287,6 +1289,531 @@ FluxKernel:: } ); } +/******************************** DirichletFluxKernel ********************************/ + +template< integer NF, integer NC, integer NP, typename IP_TYPE > +void +DirichletFluxKernel:: + launch( integer const numPhases, + localIndex const er, + localIndex const esr, + CellElementSubRegion const & subRegion, + constitutive::PermeabilityBase const & permeabilityModel, + FaceManager const & faceManager, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, + ArrayOfArraysView< localIndex const > const & faceToNodes, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + arrayView1d< globalIndex const > const & faceDofNumber, + arrayView1d< real64 const > const & faceGravCoef, + arrayView1d< real64 const > const & transMultiplier, + real64 const lengthTolerance, + real64 const dt, + globalIndex const rankOffset, + integer const useTotalMassEquation, + CompFlowAccessors const & compFlowAccessors, + MultiFluidAccessors const & multiFluidAccessors, + ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + using Deriv = multifluid::DerivativeOffset; + + // Get element data + arrayView2d< localIndex const > const & elemToFaces = subRegion.faceList(); + arrayView1d< real64 const > const & elemPres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 const > const & elemGravCoef = subRegion.getField< fields::flow::gravityCoefficient >(); + arrayView2d< real64 const > const & elemCenter = subRegion.getReference< array2d< real64 > >( CellElementSubRegion::viewKeyStruct::elementCenterString() ); + arrayView1d< real64 const > const & elemVolume = subRegion.getReference< array1d< real64 > >( CellElementSubRegion::viewKeyStruct::elementVolumeString() ); + arrayView3d< real64 const > const & elemPerm = permeabilityModel.permeability(); + arrayView1d< integer const > const & elemGhostRank = subRegion.ghostRank(); + + // Get compositional flow fields + auto phaseMob = compFlowAccessors.get( fields::flow::phaseMobility{} ); + auto dPhaseMob = compFlowAccessors.get( fields::flow::dPhaseMobility{} ); + auto dCompFrac_dCompDens = compFlowAccessors.get( fields::flow::dGlobalCompFraction_dGlobalCompDensity{} ); + + // Get multifluid fields + auto phaseMassDens = multiFluidAccessors.get( fields::multifluid::phaseMassDensity{} ); + auto dPhaseMassDens = multiFluidAccessors.get( fields::multifluid::dPhaseMassDensity{} ); + auto phaseCompFrac = multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} ); + auto dPhaseCompFrac = multiFluidAccessors.get( fields::multifluid::dPhaseCompFraction{} ); + + // Loop over boundary faces + forAll< parallelDevicePolicy<> >( boundaryFaceSet.size(), [=] GEOS_DEVICE ( localIndex const iset ) + { + localIndex const kf = boundaryFaceSet[iset]; + + // Find the element adjacent to this boundary face + localIndex erAdj = -1, esrAdj = -1, eiAdj = -1; + for( integer ke = 0; ke < elemRegionList.size( 1 ); ++ke ) + { + if( elemRegionList[kf][ke] == er && elemSubRegionList[kf][ke] == esr ) + { + erAdj = elemRegionList[kf][ke]; + esrAdj = elemSubRegionList[kf][ke]; + eiAdj = elemList[kf][ke]; + break; + } + } + + // Skip if no adjacent element in target region + if( eiAdj < 0 || elemGhostRank[eiAdj] >= 0 ) + { + return; + } + + // Compute one-sided transmissibility + stackArray2d< real64, NF * NF > transMatrix( NF, NF ); + real64 const perm[3] = { elemPerm[eiAdj][0][0], elemPerm[eiAdj][0][1], elemPerm[eiAdj][0][2] }; + + IP_TYPE::template compute< NF >( nodePosition, + transMultiplier, + faceToNodes, + elemToFaces[eiAdj], + elemCenter[eiAdj], + elemVolume[eiAdj], + perm, + lengthTolerance, + transMatrix ); + + // Find local face index + integer ifaceLoc = -1; + for( integer j = 0; j < NF; ++j ) + { + if( elemToFaces[eiAdj][j] == kf ) + { + ifaceLoc = j; + break; + } + } + if( ifaceLoc < 0 ) return; + + real64 const transmissibility = transMatrix[ifaceLoc][ifaceLoc]; + + // Component fluxes + real64 compFlux[NC]{}; + real64 dCompFlux_dP[NC]{}; + real64 dCompFlux_dC[NC][NC]{}; + + // Loop over phases to compute component fluxes + // Use face-based properties for boundary conditions (upwinding) + for( integer ip = 0; ip < numPhases; ++ip ) + { + real64 dDensMean_dC[NC]{}; + real64 dF_dC[NC]{}; + real64 dProp_dC[NC]{}; + + // Use average of element and face phase mass density for gravity term + real64 const elemDens = phaseMassDens[erAdj][esrAdj][eiAdj][0][ip]; + real64 const faceDens = facePhaseMassDens[kf][ip]; + real64 const densMean = 0.5 * (elemDens + faceDens); + + applyChainRule( NC, + dCompFrac_dCompDens[erAdj][esrAdj][eiAdj], + dPhaseMassDens[erAdj][esrAdj][eiAdj][0][ip], + dProp_dC, + Deriv::dC ); + + real64 const dDensMean_dP = 0.5 * dPhaseMassDens[erAdj][esrAdj][eiAdj][0][ip][Deriv::dP]; + for( integer jc = 0; jc < NC; ++jc ) + { + dDensMean_dC[jc] = 0.5 * dProp_dC[jc]; + } + + // Potential difference + real64 const gravTimesDz = elemGravCoef[eiAdj] - faceGravCoef[kf]; + real64 const potDif = elemPres[eiAdj] - facePres[kf] - densMean * gravTimesDz; + real64 const f = transmissibility * potDif; + real64 const dF_dP = transmissibility * ( 1.0 - dDensMean_dP * gravTimesDz ); + for( integer jc = 0; jc < NC; ++jc ) + { + dF_dC[jc] = -transmissibility * dDensMean_dC[jc] * gravTimesDz; + } + + // Use element mobility (simplified upwinding for Dirichlet BC) + // need to upwind the following: + // Upwind phase component fraction based on flow direction + real64 const beta = (potDif > 0.0) ? 1.0 : 0.0; + real64 const facePhaseMobility = facePhaseMob[kf][ip]; + real64 const phaseMobility = beta * phaseMob[erAdj][esrAdj][eiAdj][ip] + (1.0 - beta) * facePhaseMobility; + real64 const phaseFlux = phaseMobility * f; + real64 const dPhaseFlux_dP = phaseMobility * dF_dP + beta * dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dP] * f; + real64 dPhaseFlux_dC[NC]; + for( integer jc = 0; jc < NC; ++jc ) + { + dPhaseFlux_dC[jc] = phaseMob[erAdj][esrAdj][eiAdj][ip] * dF_dC[jc] + dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dC+jc] * f; + } + + // Use face-based phase composition for boundary conditions when flow is INTO the domain (potDif < 0) + // Use element phase composition when flow is OUT of the domain (potDif > 0) + for( integer ic = 0; ic < NC; ++ic ) + { + real64 const ycpElem = phaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic]; + real64 const ycpFace = facePhaseCompFrac[kf][ip][ic]; + + // Upwind phase component fraction based on flow direction + real64 const ycp = beta * ycpElem + (1.0 - beta) * ycpFace; + + compFlux[ic] += ycp * phaseFlux; + + // For derivatives, use element properties (simplified for boundary conditions) + dCompFlux_dP[ic] += dPhaseFlux_dP * ycp + beta * phaseFlux * dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic][Deriv::dP]; + + applyChainRule( NC, + dCompFrac_dCompDens[erAdj][esrAdj][eiAdj], + dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic], + dProp_dC, + Deriv::dC ); + for( integer jc = 0; jc < NC; ++jc ) + { + dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp + beta * phaseFlux * dProp_dC[jc]; + } + } + } + + // Assemble into residual and Jacobian + real64 localFlux[NC]; + real64 localFluxJacobian[NC][NC+1]; + + for( integer ic = 0; ic < NC; ++ic ) + { + localFlux[ic] = dt * compFlux[ic]; + localFluxJacobian[ic][0] = dt * dCompFlux_dP[ic]; + for( integer jc = 0; jc < NC; ++jc ) + { + localFluxJacobian[ic][jc+1] = dt * dCompFlux_dC[ic][jc]; + } + } + + // Apply total mass equation transformation if needed + if( useTotalMassEquation ) + { + real64 work[NC+1]{}; + compositionalMultiphaseUtilities::shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( NC, NC+1, localFluxJacobian, work ); + compositionalMultiphaseUtilities::shiftElementsAheadByOneAndReplaceFirstElementWithSum( NC, localFlux ); + } + + // Add to global system + globalIndex const elemDof = elemDofNumber[erAdj][esrAdj][eiAdj]; + localIndex const localRow = LvArray::integerConversion< localIndex >( elemDof - rankOffset ); + + for( integer ic = 0; ic < NC; ++ic ) + { + RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[localRow + ic], localFlux[ic] ); + + globalIndex dofColIndices[NC+1]; + dofColIndices[0] = elemDof; + for( integer jc = 0; jc < NC; ++jc ) + { + dofColIndices[jc+1] = elemDof + jc + 1; + } + + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic, + dofColIndices, + localFluxJacobian[ic], + NC+1 ); + } + } ); +} + +/******************************** EvaluateBCFacePropertiesKernel ********************************/ + +/** + * @brief Evaluate constitutive properties at BC face conditions + * @tparam NC number of components + * @tparam NP number of phases + * @param numPhases number of phases + * @param boundaryFaceSet set of boundary faces + * @param facePres face pressures at BC + * @param faceTemp face temperatures at BC + * @param faceCompFrac face component fractions at BC + * @param elemRegionList face to element region list + * @param elemSubRegionList face to element subregion list + * @param elemList face to element list + * @param er target element region index + * @param esr target element subregion index + * @param fluid multifluid model + * @param relperm relative permeability model + * @param facePhaseMob output: face phase mobility at BC + * @param facePhaseMassDens output: face phase mass density at BC + * @param facePhaseCompFrac output: face phase component fraction at BC + */ +template< integer NC, integer NP > +void +evaluateBCFaceProperties( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ) +{ + // Use constitutiveUpdatePassThru to dispatch to concrete fluid and relperm types + constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) + { + using FluidType = TYPEOFREF( castedFluid ); + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + constitutive::constitutiveUpdatePassThru( relperm, [&] ( auto & castedRelperm ) + { + using RelPermType = TYPEOFREF( castedRelperm ); + typename RelPermType::KernelWrapper relPermWrapper = castedRelperm.createKernelWrapper(); + + // Loop over BC faces and evaluate properties at BC conditions + forAll< serialPolicy >( boundaryFaceSet.size(), [=, &facePhaseMob, &facePhaseMassDens, &facePhaseCompFrac] ( localIndex const iset ) + { + localIndex const kf = boundaryFaceSet[iset]; + + // Find adjacent element in target region + localIndex eiAdj = -1; + for( integer ke = 0; ke < elemRegionList.size( 1 ); ++ke ) + { + if( elemRegionList[kf][ke] == er && elemSubRegionList[kf][ke] == esr ) + { + eiAdj = elemList[kf][ke]; + break; + } + } + if( eiAdj < 0 ) return; + + // Allocate temporary storage for face constitutive properties + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseFrac( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseDens( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseMassDensLocal( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseVisc( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseEnthalpy( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); + StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, + constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); + real64 faceTotalDens = 0.0; + + // Evaluate fluid properties at BC face conditions using flash calculation + constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper, + facePres[kf], + faceTemp[kf], + faceCompFrac[kf], + facePhaseFrac[0][0], + facePhaseDens[0][0], + facePhaseMassDensLocal[0][0], + facePhaseVisc[0][0], + facePhaseEnthalpy[0][0], + facePhaseInternalEnergy[0][0], + facePhaseCompFracLocal[0][0], + faceTotalDens ); + + // Evaluate relative permeability at face saturation from flash calculation +// relPermWrapper.compute( facePhaseFrac[0][0], 0, 0 ); + + // Store computed properties in output arrays + for( integer ip = 0; ip < numPhases; ++ip ) + { + // Store phase mass density from flash calculation + facePhaseMassDens[kf][ip] = facePhaseMassDensLocal[0][0][ip]; + + // Compute mobility from relative permeability evaluated at face conditions + real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; + real64 const mu = facePhaseVisc[0][0][ip]; + facePhaseMob[kf][ip] = (mu > 0) ? faceKr / mu : 0.0; + + // Store phase composition from flash calculation + for( integer ic = 0; ic < NC; ++ic ) + { + facePhaseCompFrac[kf][ip][ic] = facePhaseCompFracLocal[0][0][ip][ic]; + } + } + } ); + } ); // end nested constitutiveUpdatePassThru for relperm + } ); // end constitutiveUpdatePassThru for fluid +} + +// Explicit template instantiations +template void +evaluateBCFaceProperties< 1, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 2, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 3, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 4, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 5, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 1, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 2, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 3, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 4, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 5, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + } // namespace compositionalMultiphaseHybridFVMKernels } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp deleted file mode 100644 index bd3d03f56d2..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DirichletMFDFluxComputeKernel.hpp +++ /dev/null @@ -1,587 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file DirichletMFDFluxComputeKernel.hpp - */ - -#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DIRICHLETMFDFLUXCOMPUTEKERNEL_HPP -#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DIRICHLETMFDFLUXCOMPUTEKERNEL_HPP - -#include "codingUtilities/Utilities.hpp" -#include "common/DataLayouts.hpp" -#include "common/DataTypes.hpp" -#include "common/GEOS_RAJA_Interface.hpp" -#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" -#include "constitutive/fluid/multifluid/MultiFluidSelector.hpp" -#include "finiteVolume/BoundaryStencil.hpp" -#include "mesh/ElementRegionManager.hpp" -#include "mesh/ElementSubRegionBase.hpp" -#include "mesh/CellElementSubRegion.hpp" -#include "mesh/FaceManager.hpp" -#include "mesh/NodeManager.hpp" -#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" -#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp" -#include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" -#include "physicsSolvers/fluidFlow/StencilAccessors.hpp" -#include "finiteVolume/mimeticInnerProducts/MimeticInnerProductBase.hpp" - -#include "FluxComputeKernel.hpp" - -namespace geos -{ - -namespace isothermalCompositionalMultiphaseFVMKernels -{ - -/******************************** DirichletMFDFluxComputeKernel ********************************/ - -/** - * @class DirichletMFDFluxComputeKernel - * @tparam NUM_COMP number of fluid components - * @tparam NUM_DOF number of degrees of freedom - * @tparam FLUIDWRAPPER the type of the fluid wrapper - * @tparam IP_TYPE the mimetic inner product type (e.g., TPFAInnerProduct, BdVLMInnerProduct) - * @tparam NF number of faces per element in the targeted subregion - * @brief Define the interface for the assembly kernel in charge of Dirichlet face flux terms using an MFD inner product - */ -template< integer NUM_COMP, integer NUM_DOF, typename FLUIDWRAPPER, typename IP_TYPE, integer NF > -class DirichletMFDFluxComputeKernel : public FluxComputeKernel< NUM_COMP, - NUM_DOF, - BoundaryStencilWrapper > -{ -public: - - /** - * @brief The type for element-based data. Consists entirely of ArrayView's. - * - * Can be converted from ElementRegionManager::ElementViewConstAccessor - * by calling .toView() or .toViewConst() on an accessor instance - */ - template< typename VIEWTYPE > - using ElementViewConst = ElementRegionManager::ElementViewConst< VIEWTYPE >; - - using AbstractBase = isothermalCompositionalMultiphaseFVMKernels::FluxComputeKernelBase; - using DofNumberAccessor = AbstractBase::DofNumberAccessor; - using CompFlowAccessors = AbstractBase::CompFlowAccessors; - using MultiFluidAccessors = AbstractBase::MultiFluidAccessors; - using CapPressureAccessors = AbstractBase::CapPressureAccessors; - using PermeabilityAccessors = AbstractBase::PermeabilityAccessors; - - using AbstractBase::m_dt; - using AbstractBase::m_numPhases; - using AbstractBase::m_rankOffset; - using AbstractBase::m_dofNumber; - using AbstractBase::m_ghostRank; - using AbstractBase::m_gravCoef; - using AbstractBase::m_pres; - using AbstractBase::m_phaseCompFrac; - using AbstractBase::m_dPhaseCompFrac; - using AbstractBase::m_dCompFrac_dCompDens; - using AbstractBase::m_localMatrix; - using AbstractBase::m_localRhs; - using AbstractBase::m_kernelFlags; - - using Base = isothermalCompositionalMultiphaseFVMKernels::FluxComputeKernel< NUM_COMP, NUM_DOF, BoundaryStencilWrapper >; - using Base::numComp; - using Base::numDof; - using Base::numEqn; - using Base::m_stencilWrapper; - using Base::m_phaseMob; - using Base::m_dPhaseMob; - using Base::m_phaseMassDens; - using Base::m_dPhaseMassDens; - using Base::m_permeability; - using Base::m_dPerm_dPres; - using Base::m_seri; - using Base::m_sesri; - using Base::m_sei; - - /** - * @brief Constructor for the kernel interface - * @param[in] numPhases the number of fluid phases - * @param[in] rankOffset the offset of my MPI rank - * @param[in] faceManager the face manager - * @param[in] stencilWrapper reference to the stencil wrapper - * @param[in] fluidWrapper reference to the fluid wrapper - * @param[in] dofNumberAccessor - * @param[in] compFlowAccessors - * @param[in] multiFluidAccessors - * @param[in] capPressureAccessors - * @param[in] permeabilityAccessors - * @param[in] nodePosition reference positions of nodes - * @param[in] faceToNodes face-to-nodes connectivity - * @param[in] elemCenter element centers (in the targeted subregion) - * @param[in] elemVolume element volumes (in the targeted subregion) - * @param[in] elemToFaces element-to-faces connectivity (in the targeted subregion) - * @param[in] transMultiplier transmissibility multipliers per face - * @param[in] lengthTolerance geometric tolerance for IP computation - * @param[in] dt time step size - * @param[inout] localMatrix the local CRS matrix - * @param[inout] localRhs the local right-hand side vector - * @param[in] kernelFlags flags packed together - */ - DirichletMFDFluxComputeKernel( integer const numPhases, - globalIndex const rankOffset, - FaceManager const & faceManager, - BoundaryStencilWrapper const & stencilWrapper, - FLUIDWRAPPER const & fluidWrapper, - DofNumberAccessor const & dofNumberAccessor, - CompFlowAccessors const & compFlowAccessors, - MultiFluidAccessors const & multiFluidAccessors, - CapPressureAccessors const & capPressureAccessors, - PermeabilityAccessors const & permeabilityAccessors, - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, - ArrayOfArraysView< localIndex const > const & faceToNodes, - ElementViewConst< arrayView2d< real64 const > > const & elemCenter, - ElementViewConst< arrayView1d< real64 const > > const & elemVolume, - ElementViewConst< arrayView2d< localIndex const > > const & elemToFaces, - arrayView1d< real64 const > const & transMultiplier, - real64 const lengthTolerance, - real64 const dt, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs, - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags ) - : Base( numPhases, - rankOffset, - stencilWrapper, - dofNumberAccessor, - compFlowAccessors, - multiFluidAccessors, - capPressureAccessors, - permeabilityAccessors, - dt, - localMatrix, - localRhs, - kernelFlags ), - m_facePres( faceManager.getField< fields::flow::facePressure >() ), - m_faceTemp( faceManager.getField< fields::flow::faceTemperature >() ), - m_faceCompFrac( faceManager.getField< fields::flow::faceGlobalCompFraction >() ), - m_faceGravCoef( faceManager.getField< fields::flow::gravityCoefficient >() ), - m_nodePosition( nodePosition ), - m_faceToNodes( faceToNodes ), - m_elemCenter( elemCenter ), - m_elemVolume( elemVolume ), - m_elemToFaces( elemToFaces ), - m_transMultiplier( transMultiplier ), - m_lengthTolerance( lengthTolerance ), - m_fluidWrapper( fluidWrapper ) - {} - - /** - * @struct StackVariables - * @brief Kernel variables (dof numbers, jacobian and residual) located on the stack - */ - struct StackVariables - { - public: - - GEOS_HOST_DEVICE - StackVariables( localIndex const GEOS_UNUSED_PARAM( size ), - localIndex GEOS_UNUSED_PARAM( numElems )) {} - - // Transmissibility - real64 transmissibility = 0.0; - - // Component fluxes and derivatives - - /// Component fluxes - real64 compFlux[numComp]{}; - /// Derivatives of component fluxes wrt pressure - real64 dCompFlux_dP[numComp]{}; - /// Derivatives of component fluxes wrt component densities - real64 dCompFlux_dC[numComp][numComp]{}; - - // Local degrees of freedom and local residual/jacobian - - /// Indices of the matrix rows/columns corresponding to the dofs in this face - globalIndex dofColIndices[numDof]{}; - - /// Storage for the face local residual vector - real64 localFlux[numEqn]{}; - /// Storage for the face local Jacobian matrix - real64 localFluxJacobian[numEqn][numDof]{}; - }; - - /** - * @brief Performs the setup phase for the kernel. - * @param[in] iconn the connection index - * @param[in] stack the stack variables - */ - GEOS_HOST_DEVICE - void setup( localIndex const iconn, - StackVariables & stack ) const - { - globalIndex const offset = - m_dofNumber[m_seri( iconn, BoundaryStencil::Order::ELEM )][m_sesri( iconn, BoundaryStencil::Order::ELEM )][m_sei( iconn, BoundaryStencil::Order::ELEM )]; - - for( integer jdof = 0; jdof < numDof; ++jdof ) - { - stack.dofColIndices[jdof] = offset + jdof; - } - } - - /** - * @brief Compute the local Dirichlet face flux contributions to the residual and Jacobian (MFD version) - */ - template< typename FUNC = NoOpFunc > - GEOS_HOST_DEVICE - void computeFlux( localIndex const iconn, - StackVariables & stack, - FUNC && compFluxKernelOp = NoOpFunc{} ) const - { - using Deriv = constitutive::multifluid::DerivativeOffset; - using Order = BoundaryStencil::Order; - - localIndex const er = m_seri( iconn, Order::ELEM ); - localIndex const esr = m_sesri( iconn, Order::ELEM ); - localIndex const ei = m_sei( iconn, Order::ELEM ); - localIndex const kf = m_sei( iconn, Order::FACE ); - - // Step 1: compute the one-sided MFD transmissibility at the boundary face - { - stackArray2d< real64, NF * NF > transMatrix( NF, NF ); - - // principal permeabilities (assumed stored in first comp index) - real64 const perm[3] = { m_permeability[er][esr][ei][0][0], - m_permeability[er][esr][ei][0][1], - m_permeability[er][esr][ei][0][2] }; - - IP_TYPE::template compute< NF >( m_nodePosition, - m_transMultiplier, - m_faceToNodes, - m_elemToFaces[er][esr][ei], - m_elemCenter[er][esr][ei], - m_elemVolume[er][esr][ei], - perm, - m_lengthTolerance, - transMatrix ); - - // find local face index corresponding to global face kf - integer ifaceLoc = 0; - for( integer j = 0; j < NF; ++j ) - { - if( m_elemToFaces[er][esr][ei][j] == kf ) - { - ifaceLoc = j; - break; - } - } - stack.transmissibility = transMatrix[ifaceLoc][ifaceLoc]; - } - - // Step 2: compute the fluid properties on the face - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseFrac( 1, 1, m_numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseDens( 1, 1, m_numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseMassDens( 1, 1, m_numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseVisc( 1, 1, m_numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseEnthalpy( 1, 1, m_numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, m_numPhases ); - StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NUM_COMP, - constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFrac( 1, 1, m_numPhases, NUM_COMP ); - real64 faceTotalDens = 0.0; - - constitutive::MultiFluidBase::KernelWrapper::computeValues( m_fluidWrapper, - m_facePres[kf], - m_faceTemp[kf], - m_faceCompFrac[kf], - facePhaseFrac[0][0], - facePhaseDens[0][0], - facePhaseMassDens[0][0], - facePhaseVisc[0][0], - facePhaseEnthalpy[0][0], - facePhaseInternalEnergy[0][0], - facePhaseCompFrac[0][0], - faceTotalDens ); - - // Step 3: loop over phases, compute and upwind phase flux and sum contributions to each component's flux - for( integer ip = 0; ip < m_numPhases; ++ip ) - { - // working variables - real64 dDensMean_dC[numComp]{}; - real64 dF_dC[numComp]{}; - real64 dProp_dC[numComp]{}; - - real64 phaseFlux = 0.0; // for the lambda - real64 dPhaseFlux_dP = 0.0; - real64 dPhaseFlux_dC[numComp]{}; - - // Step 3.1: compute the average phase mass density at the face - applyChainRule( numComp, - m_dCompFrac_dCompDens[er][esr][ei], - m_dPhaseMassDens[er][esr][ei][0][ip], - dProp_dC, - Deriv::dC ); - - real64 const densMean = 0.5 * ( m_phaseMassDens[er][esr][ei][0][ip] + facePhaseMassDens[0][0][ip] ); - real64 const dDensMean_dP = 0.5 * m_dPhaseMassDens[er][esr][ei][0][ip][Deriv::dP]; - for( integer jc = 0; jc < numComp; ++jc ) - { - dDensMean_dC[jc] = 0.5 * dProp_dC[jc]; - } - - // Step 3.2: compute the MFD potential difference at the face (same expression; only T differs) - real64 const gravTimesDz = m_gravCoef[er][esr][ei] - m_faceGravCoef[kf]; - real64 const potDif = m_pres[er][esr][ei] - m_facePres[kf] - densMean * gravTimesDz; - - // Derivative of T wrt pressure unknown for general IP: set to 0 (approximation) - real64 const dTrans_dPres = 0.0; - real64 const f = stack.transmissibility * potDif; - real64 const dF_dP = stack.transmissibility * ( 1.0 - dDensMean_dP * gravTimesDz ) + dTrans_dPres * potDif; - for( integer jc = 0; jc < numComp; ++jc ) - { - dF_dC[jc] = -stack.transmissibility * dDensMean_dC[jc] * gravTimesDz; - } - - // Step 3.3: approximation for face mobility using total element mobility - real64 const facePhaseMob = ( facePhaseFrac[0][0][ip] > 0.0 ) - ? facePhaseFrac[0][0][ip] * faceTotalDens / facePhaseVisc[0][0][ip] - : 0.0; - - // Step 3.4: upwinding - if( potDif >= 0 ) // the element is upstream - { - phaseFlux = m_phaseMob[er][esr][ei][ip] * f; - dPhaseFlux_dP = m_phaseMob[er][esr][ei][ip] * dF_dP + m_dPhaseMob[er][esr][ei][ip][Deriv::dP] * f; - for( integer jc = 0; jc < numComp; ++jc ) - { - dPhaseFlux_dC[jc] = m_phaseMob[er][esr][ei][ip] * dF_dC[jc] + m_dPhaseMob[er][esr][ei][ip][Deriv::dC+jc] * f; - } - - arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE_COMP-3 > phaseCompFracSub = - m_phaseCompFrac[er][esr][ei][0][ip]; - arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC-3 > dPhaseCompFracSub = - m_dPhaseCompFrac[er][esr][ei][0][ip]; - - for( integer ic = 0; ic < numComp; ++ic ) - { - real64 const ycp = phaseCompFracSub[ic]; - stack.compFlux[ic] += phaseFlux * ycp; - stack.dCompFlux_dP[ic] += dPhaseFlux_dP * ycp + phaseFlux * dPhaseCompFracSub[ic][Deriv::dP]; - - applyChainRule( numComp, - m_dCompFrac_dCompDens[er][esr][ei], - dPhaseCompFracSub[ic], - dProp_dC, - Deriv::dC ); - for( integer jc = 0; jc < numComp; ++jc ) - { - stack.dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp + phaseFlux * dProp_dC[jc]; - } - } - } - else // the face is upstream - { - phaseFlux = facePhaseMob * f; - dPhaseFlux_dP = facePhaseMob * dF_dP; - for( integer jc = 0; jc < numComp; ++jc ) - { - dPhaseFlux_dC[jc] = facePhaseMob * dF_dC[jc]; - } - - for( integer ic = 0; ic < numComp; ++ic ) - { - real64 const ycp = facePhaseCompFrac[0][0][ip][ic]; - stack.compFlux[ic] += phaseFlux * ycp; - stack.dCompFlux_dP[ic] += dPhaseFlux_dP * ycp; - for( integer jc = 0; jc < numComp; ++jc ) - { - stack.dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp; - } - } - } - - // reuse hook - compFluxKernelOp( ip, er, esr, ei, kf, f, - facePhaseMob, facePhaseEnthalpy[0][0], facePhaseCompFrac[0][0], - phaseFlux, dPhaseFlux_dP, dPhaseFlux_dC ); - } - - // Step 4: populate local flux vector and derivatives - for( integer ic = 0; ic < numComp; ++ic ) - { - stack.localFlux[ic] = m_dt * stack.compFlux[ic]; - stack.localFluxJacobian[ic][0] = m_dt * stack.dCompFlux_dP[ic]; - for( integer jc = 0; jc < numComp; ++jc ) - { - stack.localFluxJacobian[ic][jc+1] = m_dt * stack.dCompFlux_dC[ic][jc]; - } - } - } - - /** - * @brief Performs the complete phase for the kernel. - */ - template< typename FUNC = NoOpFunc > - GEOS_HOST_DEVICE - void complete( localIndex const iconn, - StackVariables & stack, - FUNC && assemblyKernelOp = NoOpFunc{} ) const - { - using namespace compositionalMultiphaseUtilities; - using Order = BoundaryStencil::Order; - - if( AbstractBase::m_kernelFlags.isSet( KernelFlags::TotalMassEquation ) ) - { - // Apply equation/variable change transformation(s) - real64 work[numDof]{}; - shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numComp, numDof, stack.localFluxJacobian, work ); - shiftElementsAheadByOneAndReplaceFirstElementWithSum( numComp, stack.localFlux ); - } - - if( m_ghostRank[m_seri( iconn, Order::ELEM )][m_sesri( iconn, Order::ELEM )][m_sei( iconn, Order::ELEM )] < 0 ) - { - globalIndex const globalRow = m_dofNumber[m_seri( iconn, Order::ELEM )][m_sesri( iconn, Order::ELEM )][m_sei( iconn, Order::ELEM )]; - localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset ); - GEOS_ASSERT_GE( localRow, 0 ); - GEOS_ASSERT_GT( AbstractBase::m_localMatrix.numRows(), localRow + numComp ); - - for( integer ic = 0; ic < numComp; ++ic ) - { - RAJA::atomicAdd( parallelDeviceAtomic{}, &AbstractBase::m_localRhs[localRow + ic], stack.localFlux[ic] ); - AbstractBase::m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic > - ( localRow + ic, - stack.dofColIndices, - stack.localFluxJacobian[ic], - numDof ); - } - - assemblyKernelOp( localRow ); - } - } - -protected: - - /// Views on face pressure, temperature, and composition - arrayView1d< real64 const > const m_facePres; - arrayView1d< real64 const > const m_faceTemp; - arrayView2d< real64 const, compflow::USD_COMP > const m_faceCompFrac; - - /// View on the face gravity coefficient - arrayView1d< real64 const > const m_faceGravCoef; - - // Geometry/connectivity for IP computation - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const m_nodePosition; - ArrayOfArraysView< localIndex const > const m_faceToNodes; - ElementViewConst< arrayView2d< real64 const > > const m_elemCenter; - ElementViewConst< arrayView1d< real64 const > > const m_elemVolume; - ElementViewConst< arrayView2d< localIndex const > > const m_elemToFaces; - arrayView1d< real64 const > const m_transMultiplier; - real64 const m_lengthTolerance; - - /// Reference to the fluid wrapper - FLUIDWRAPPER const m_fluidWrapper; -}; - - -/** - * @class DirichletMFDFluxComputeKernelFactory - */ -class DirichletMFDFluxComputeKernelFactory -{ -public: - - /** - * @brief Create a new MFD Dirichlet kernel and launch - * @tparam POLICY the policy used in the RAJA kernel - * @tparam IP_TYPE mimetic inner product type - * @tparam NF number of faces per element in the targeted subregion - */ - template< typename POLICY, typename IP_TYPE, integer NF > - static void - createAndLaunch( integer const numComps, - integer const numPhases, - globalIndex const rankOffset, - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, - string const & dofKey, - string const & solverName, - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, - FaceManager const & faceManager, - ElementRegionManager const & elemManager, - BoundaryStencilWrapper const & stencilWrapper, - constitutive::MultiFluidBase & fluidBase, - real64 const lengthTolerance, - real64 const dt, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) - { - // Select fluid wrapper based on number of components - constitutive::constitutiveComponentUpdatePassThru( fluidBase, numComps, [&]( auto & fluid, auto NC ) - { - using FluidType = TYPEOFREF( fluid ); - typename FluidType::KernelWrapper const fluidWrapper = fluid.createKernelWrapper(); - - integer constexpr NUM_COMP = NC(); - integer constexpr NUM_DOF = NC() + 1; - - // Identify a representative subregion from the stencil (same assumption as TPFA Dirichlet) - localIndex const er = stencilWrapper.getElementRegionIndices()( 0, BoundaryStencil::Order::ELEM ); - localIndex const esr = stencilWrapper.getElementSubRegionIndices()( 0, BoundaryStencil::Order::ELEM ); - ElementSubRegionBase const & subRegionBase = elemManager.getRegion( er ).getSubRegion( esr ); - - // Element geometry/connectivity arrays - ElementRegionManager::ElementViewAccessor< arrayView2d< real64 const > > elemCenter = - elemManager.constructArrayViewAccessor< real64, 2 >( CellElementSubRegion::viewKeyStruct::elementCenterString() ); - ElementRegionManager::ElementViewAccessor< arrayView1d< real64 const > > elemVolume = - elemManager.constructArrayViewAccessor< real64, 1 >( CellElementSubRegion::viewKeyStruct::elementVolumeString() ); - ElementRegionManager::ElementViewAccessor< arrayView2d< localIndex const > > elemToFaces = - elemManager.constructArrayViewAccessor< localIndex, 2 >( CellElementSubRegion::viewKeyStruct::faceListString() ); - - // Face connectivity and multipliers - ArrayOfArraysView< localIndex const > faceToNodes = faceManager.nodeList().toViewConst(); - arrayView1d< real64 const > const & transMultiplier = faceManager.getField< fields::flow::transMultiplier >(); - - using kernelType = DirichletMFDFluxComputeKernel< NUM_COMP, NUM_DOF, typename FluidType::KernelWrapper, IP_TYPE, NF >; - typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); - typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); - typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); - typename kernelType::PermeabilityAccessors permeabilityAccessors( elemManager, solverName ); - - typename kernelType::DofNumberAccessor dofNumberAccessor = - elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); - - kernelType kernel( numPhases, - rankOffset, - faceManager, - stencilWrapper, - fluidWrapper, - dofNumberAccessor, - compFlowAccessors, - multiFluidAccessors, - capPressureAccessors, - permeabilityAccessors, - nodePosition, - faceToNodes, - elemCenter.toNestedViewConst(), - elemVolume.toNestedViewConst(), - elemToFaces.toNestedViewConst(), - transMultiplier, - lengthTolerance, - dt, - localMatrix, - localRhs, - kernelFlags ); - kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); - GEOS_UNUSED_VAR( subRegionBase ); - } ); - } -}; - -} // namespace isothermalCompositionalMultiphaseFVMKernels - -} // namespace geos - - -#endif // GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONAL_DIRICHLETMFDFLUXCOMPUTEKERNEL_HPP From 55f5898ebfe5fd03cdf96157269a3c3a299087ae Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 24 Oct 2025 17:42:52 -0700 Subject: [PATCH 26/91] wip: number of iterations should be exactly 2 --- .../CompositionalMultiphaseHybridFVM.cpp | 157 ++++++------------ ...itionalMultiphaseHybridFVMKernels_impl.hpp | 2 +- 2 files changed, 51 insertions(+), 108 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index ec141d010b6..fc7f1253eda 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -645,65 +645,12 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FaceManager & faceManager = mesh.getFaceManager(); NodeManager const & nodeManager = mesh.getNodeManager(); ElementRegionManager & elemManager = mesh.getElemManager(); - - // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) - arrayView1d< real64 const > const presFace = - faceManager.getField< flow::facePressure >(); - arrayView1d< real64 const > const presFaceBC = - faceManager.getField< flow::bcPressure >(); string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); arrayView1d< globalIndex const > const faceDofNumber = faceManager.getReference< array1d< globalIndex > >( faceDofKey ); arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); - globalIndex const rankOffset = dofManager.rankOffset(); - fsManager.apply< FaceManager >( time_n + dt, - mesh, - flow::bcPressure::key(), - [&] ( FieldSpecificationBase const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - FaceManager & targetGroup, - string const & ) - { - // Using the field specification functions to apply the boundary conditions to the system - fs.applyFieldValue< FieldSpecificationEqual, - parallelDevicePolicy<> >( targetSet, - time_n + dt, - targetGroup, - flow::bcPressure::key() ); - - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - - localIndex const kf = targetSet[a]; - if( faceGhostRank[kf] >= 0 ) - { - return; - } - - // Get the dof number of this face - globalIndex const dofIndex = faceDofNumber[kf]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // Apply field value to the lhs and rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - presFaceBC[kf], - presFace[kf] ); - localRhs[localRow] = rhsValue; - } ); - - } ); - - - - - // Get node positions arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); @@ -726,30 +673,11 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n flow::bcTemperature::key(), flow::faceTemperature::key() ); // Get face boundary values - arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); + arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::bcPressure >(); arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); -// // Print all entries in faceCompFrac -// std::cout << "faceCompFrac array size: " << faceCompFrac.size(0) << " x " << faceCompFrac.size(1) << std::endl; -// for( localIndex iface = 0; iface < faceCompFrac.size(0); ++iface ) -// { -//// std::ostringstream oss; -// std::cout << "Face " << iface << ": ["; -// for( localIndex ic = 0; ic < faceCompFrac.size(1); ++ic ) -// { -// std::cout << faceCompFrac[iface][ic]; -// if( ic < faceCompFrac.size(1) - 1 ) -// { -// std::cout << ", "; -// } -// } -// std::cout << "]"; -// std::cout << std::endl; -//// GEOS_LOG_RANK_0( oss.str() ); -// } - // Loop over regions and apply Dirichlet flux kernel elemManager.forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const erIndex, CellElementSubRegion & subRegion ) @@ -863,38 +791,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n faceManager.getField< flow::facePhaseMassDensity >(); arrayView3d< real64 const, compflow::USD_PHASE_COMP > const facePhaseCompFracField = faceManager.getField< flow::facePhaseCompFraction >(); - -// // After facePhaseMob is defined (around line 615) -// std::cout << "facePhaseMob array size: " << facePhaseMob.size(0) << " x " << facePhaseMob.size(1) << std::endl; -// for( localIndex iface = 0; iface < facePhaseMob.size(0); ++iface ) -// { -// std::cout << "Face " << iface << " facePhaseMob: ["; -// for( localIndex ip = 0; ip < facePhaseMob.size(1); ++ip ) -// { -// std::cout << facePhaseMob[iface][ip]; -// if( ip < facePhaseMob.size(1) - 1 ) -// { -// std::cout << ", "; -// } -// } -// std::cout << "]" << std::endl; -// } -// -// // After facePhaseMobField is defined (around line 728) -// std::cout << "facePhaseMobField array size: " << facePhaseMobField.size(0) << " x " << facePhaseMobField.size(1) << std::endl; -// for( localIndex iface = 0; iface < facePhaseMobField.size(0); ++iface ) -// { -// std::cout << "Face " << iface << " facePhaseMobField: ["; -// for( localIndex ip = 0; ip < facePhaseMobField.size(1); ++ip ) -// { -// std::cout << facePhaseMobField[iface][ip]; -// if( ip < facePhaseMobField.size(1) - 1 ) -// { -// std::cout << ", "; -// } -// } -// std::cout << "]" << std::endl; -// } // Apply Dirichlet boundary fluxes for each face set using DirichletFluxKernel for( string const & setName : bcFaceSets ) @@ -903,8 +799,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n if( targetSet.size() == 0 ) continue; - GEOS_LOG_RANK_0( "Applying Dirichlet BC to face set '" << setName << "' with " << targetSet.size() << " faces" ); - // Launch the Dirichlet flux kernel with compile-time dispatch constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) { @@ -988,6 +882,55 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } ); } } ); + + // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) + arrayView1d< real64 const > const presFace = + faceManager.getField< flow::facePressure >(); + arrayView1d< real64 const > const presFaceBC = + faceManager.getField< flow::bcPressure >(); + + fsManager.apply< FaceManager >( time_n + dt, + mesh, + flow::bcPressure::key(), + [&] ( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + FaceManager & targetGroup, + string const & ) + { + // Using the field specification functions to apply the boundary conditions to the system + fs.applyFieldValue< FieldSpecificationEqual, + parallelDevicePolicy<> >( targetSet, + time_n + dt, + targetGroup, + flow::bcPressure::key() ); + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + + localIndex const kf = targetSet[a]; + if( faceGhostRank[kf] >= 0 ) + { + return; + } + + // Get the dof number of this face + globalIndex const dofIndex = faceDofNumber[kf]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // Apply field value to the lhs and rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + presFaceBC[kf], + presFace[kf] ); + localRhs[localRow] = rhsValue; + } ); + + } ); + } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 6fd1ade12eb..cda90a0ad3a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1630,7 +1630,7 @@ evaluateBCFaceProperties( integer const numPhases, // Compute mobility from relative permeability evaluated at face conditions real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; real64 const mu = facePhaseVisc[0][0][ip]; - facePhaseMob[kf][ip] = (mu > 0) ? faceKr / mu : 0.0; + facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; // Store phase composition from flash calculation for( integer ic = 0; ic < NC; ++ic ) From 854eaea0b4304b6e292288618f0beb90bf9fd910 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 24 Oct 2025 18:26:57 -0700 Subject: [PATCH 27/91] wip: exact linear pressure field --- .../CompositionalMultiphaseHybridFVM.cpp | 96 +++++++++---------- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 3 +- 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index fc7f1253eda..028515c97b3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -673,7 +673,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n flow::bcTemperature::key(), flow::faceTemperature::key() ); // Get face boundary values - arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::bcPressure >(); + arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); @@ -883,53 +883,53 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } } ); - // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) - arrayView1d< real64 const > const presFace = - faceManager.getField< flow::facePressure >(); - arrayView1d< real64 const > const presFaceBC = - faceManager.getField< flow::bcPressure >(); - - fsManager.apply< FaceManager >( time_n + dt, - mesh, - flow::bcPressure::key(), - [&] ( FieldSpecificationBase const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - FaceManager & targetGroup, - string const & ) - { - // Using the field specification functions to apply the boundary conditions to the system - fs.applyFieldValue< FieldSpecificationEqual, - parallelDevicePolicy<> >( targetSet, - time_n + dt, - targetGroup, - flow::bcPressure::key() ); - - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - - localIndex const kf = targetSet[a]; - if( faceGhostRank[kf] >= 0 ) - { - return; - } - - // Get the dof number of this face - globalIndex const dofIndex = faceDofNumber[kf]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // Apply field value to the lhs and rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - presFaceBC[kf], - presFace[kf] ); - localRhs[localRow] = rhsValue; - } ); - - } ); +// // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) +// arrayView1d< real64 const > const presFace = +// faceManager.getField< flow::facePressure >(); +// arrayView1d< real64 const > const presFaceBC = +// faceManager.getField< flow::bcPressure >(); +// +// fsManager.apply< FaceManager >( time_n + dt, +// mesh, +// flow::bcPressure::key(), +// [&] ( FieldSpecificationBase const & fs, +// string const & setName, +// SortedArrayView< localIndex const > const & targetSet, +// FaceManager & targetGroup, +// string const & ) +// { +// // Using the field specification functions to apply the boundary conditions to the system +// fs.applyFieldValue< FieldSpecificationEqual, +// parallelDevicePolicy<> >( targetSet, +// time_n + dt, +// targetGroup, +// flow::bcPressure::key() ); +// +// forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) +// { +// +// localIndex const kf = targetSet[a]; +// if( faceGhostRank[kf] >= 0 ) +// { +// return; +// } +// +// // Get the dof number of this face +// globalIndex const dofIndex = faceDofNumber[kf]; +// localIndex const localRow = dofIndex - rankOffset; +// real64 rhsValue; +// +// // Apply field value to the lhs and rhs +// FieldSpecificationEqual::SpecifyFieldValue( dofIndex, +// rankOffset, +// localMatrix, +// rhsValue, +// presFaceBC[kf], +// presFace[kf] ); +// localRhs[localRow] = rhsValue; +// } ); +// +// } ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index cda90a0ad3a..ddded3f8be9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1630,7 +1630,8 @@ evaluateBCFaceProperties( integer const numPhases, // Compute mobility from relative permeability evaluated at face conditions real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; real64 const mu = facePhaseVisc[0][0][ip]; - facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; +// facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; + facePhaseMob[kf][ip] = (mu > 0) ? faceKr / mu : 0.0; // Store phase composition from flash calculation for( integer ic = 0; ic < NC; ++ic ) From 32a4a0b967c8f788458ccd6712e8858d56afa3d5 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 06:43:01 -0700 Subject: [PATCH 28/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 101 +++++++++++++++--- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index ddded3f8be9..be708b5312b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1395,14 +1395,24 @@ DirichletFluxKernel:: break; } } - if( ifaceLoc < 0 ) return; + if( ifaceLoc < 0 ){ + return; + } - real64 const transmissibility = transMatrix[ifaceLoc][ifaceLoc]; + // Get all global face indices of the cell touching the boundary + stackArray1d< localIndex, NF > cellFaces( NF ); + std::cout << "kf: " << kf << " ifaceLoc: " << ifaceLoc << "\n"; + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + cellFaces[jfaceLoc] = elemToFaces[eiAdj][jfaceLoc]; + std::cout << "cellFaces[jfaceLoc]: " << cellFaces[jfaceLoc] << " jfaceLoc: " << ifaceLoc << "\n"; + } // Component fluxes real64 compFlux[NC]{}; real64 dCompFlux_dP[NC]{}; real64 dCompFlux_dC[NC][NC]{}; + real64 dCompFlux_dFaceP[NC][NF]{}; // Derivatives w.r.t. face pressures // Loop over phases to compute component fluxes // Use face-based properties for boundary conditions (upwinding) @@ -1429,28 +1439,60 @@ DirichletFluxKernel:: dDensMean_dC[jc] = 0.5 * dProp_dC[jc]; } - // Potential difference - real64 const gravTimesDz = elemGravCoef[eiAdj] - faceGravCoef[kf]; - real64 const potDif = elemPres[eiAdj] - facePres[kf] - densMean * gravTimesDz; - real64 const f = transmissibility * potDif; - real64 const dF_dP = transmissibility * ( 1.0 - dDensMean_dP * gravTimesDz ); + // Compute flux by looping over all connected faces with consistent transmissibility + real64 f = 0.0; + real64 dF_dP = 0.0; + real64 dF_dFaceP[NF]{}; // Derivatives of flux w.r.t. face pressures for( integer jc = 0; jc < NC; ++jc ) { - dF_dC[jc] = -transmissibility * dDensMean_dC[jc] * gravTimesDz; + dF_dC[jc] = 0.0; + } + + // Sum contributions from all connected faces + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + // Potential difference for each face + real64 const gravTimesDz_j = elemGravCoef[eiAdj] - faceGravCoef[cellFaces[jfaceLoc]]; + real64 const potDif_j = elemPres[eiAdj] - facePres[kf] - densMean * gravTimesDz_j; + real64 const transmissibility_j = transMatrix[ifaceLoc][jfaceLoc]; + + // Accumulate flux and derivatives + f += transmissibility_j * potDif_j; + dF_dP += transmissibility_j * ( 1.0 - dDensMean_dP * gravTimesDz_j ); + + // Derivative w.r.t. face pressure at this face (only kf contributes since potDif uses facePres[kf]) + if( jfaceLoc != ifaceLoc ) + { + dF_dFaceP[jfaceLoc] = -transmissibility_j; // d(potDif)/d(facePres[kf]) = -1 + } + else + { + dF_dFaceP[jfaceLoc] = 0.0; + } + + for( integer jc = 0; jc < NC; ++jc ) + { + dF_dC[jc] += -transmissibility_j * dDensMean_dC[jc] * gravTimesDz_j; + } } // Use element mobility (simplified upwinding for Dirichlet BC) - // need to upwind the following: // Upwind phase component fraction based on flow direction - real64 const beta = (potDif > 0.0) ? 1.0 : 0.0; + // Use the total flux f for upwinding decision + real64 const beta = (f > 0.0) ? 1.0 : 0.0; real64 const facePhaseMobility = facePhaseMob[kf][ip]; real64 const phaseMobility = beta * phaseMob[erAdj][esrAdj][eiAdj][ip] + (1.0 - beta) * facePhaseMobility; real64 const phaseFlux = phaseMobility * f; real64 const dPhaseFlux_dP = phaseMobility * dF_dP + beta * dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dP] * f; real64 dPhaseFlux_dC[NC]; + real64 dPhaseFlux_dFaceP[NF]; for( integer jc = 0; jc < NC; ++jc ) { - dPhaseFlux_dC[jc] = phaseMob[erAdj][esrAdj][eiAdj][ip] * dF_dC[jc] + dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dC+jc] * f; + dPhaseFlux_dC[jc] = phaseMobility * dF_dC[jc] + beta * dPhaseMob[erAdj][esrAdj][eiAdj][ip][Deriv::dC+jc] * f; + } + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + dPhaseFlux_dFaceP[jfaceLoc] = phaseMobility * dF_dFaceP[jfaceLoc]; } // Use face-based phase composition for boundary conditions when flow is INTO the domain (potDif < 0) @@ -1477,6 +1519,12 @@ DirichletFluxKernel:: { dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp + beta * phaseFlux * dProp_dC[jc]; } + + // Add derivatives w.r.t. face pressures + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + dCompFlux_dFaceP[ic][jfaceLoc] += dPhaseFlux_dFaceP[jfaceLoc] * ycp; + } } } @@ -1521,6 +1569,34 @@ DirichletFluxKernel:: dofColIndices, localFluxJacobian[ic], NC+1 ); + + // Add contributions from face pressure derivatives + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + localIndex const kfj = cellFaces[jfaceLoc]; + globalIndex const faceDof = faceDofNumber[kfj]; + + real64 facePressureJacobian = dt * dCompFlux_dFaceP[ic][jfaceLoc]; + + // Apply total mass equation transformation if needed + if( useTotalMassEquation && ic == 0 ) + { + // For total mass equation, sum all component derivatives + facePressureJacobian = 0.0; + for( integer icc = 0; icc < NC; ++icc ) + { + facePressureJacobian += dt * dCompFlux_dFaceP[icc][jfaceLoc]; + } + } + + if( LvArray::math::abs( facePressureJacobian ) > 0.0 ) + { + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic, + &faceDof, + &facePressureJacobian, + 1 ); + } + } } } ); } @@ -1630,8 +1706,7 @@ evaluateBCFaceProperties( integer const numPhases, // Compute mobility from relative permeability evaluated at face conditions real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; real64 const mu = facePhaseVisc[0][0][ip]; -// facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; - facePhaseMob[kf][ip] = (mu > 0) ? faceKr / mu : 0.0; + facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; // Store phase composition from flash calculation for( integer ic = 0; ic < NC; ++ic ) From 88cea378054731332cd24a166be081112581290d Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 13:48:20 -0700 Subject: [PATCH 29/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index be708b5312b..fb39f992e35 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1401,11 +1401,9 @@ DirichletFluxKernel:: // Get all global face indices of the cell touching the boundary stackArray1d< localIndex, NF > cellFaces( NF ); - std::cout << "kf: " << kf << " ifaceLoc: " << ifaceLoc << "\n"; for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { cellFaces[jfaceLoc] = elemToFaces[eiAdj][jfaceLoc]; - std::cout << "cellFaces[jfaceLoc]: " << cellFaces[jfaceLoc] << " jfaceLoc: " << ifaceLoc << "\n"; } // Component fluxes @@ -1442,6 +1440,7 @@ DirichletFluxKernel:: // Compute flux by looping over all connected faces with consistent transmissibility real64 f = 0.0; real64 dF_dP = 0.0; +// real64 dF_dfacePres = 0.0; real64 dF_dFaceP[NF]{}; // Derivatives of flux w.r.t. face pressures for( integer jc = 0; jc < NC; ++jc ) { @@ -1459,22 +1458,36 @@ DirichletFluxKernel:: // Accumulate flux and derivatives f += transmissibility_j * potDif_j; dF_dP += transmissibility_j * ( 1.0 - dDensMean_dP * gravTimesDz_j ); - +// dF_dfacePres += transmissibility_j * ( -1.0 ); // d(potDif)/d(facePres[kf]) = -1 // Derivative w.r.t. face pressure at this face (only kf contributes since potDif uses facePres[kf]) - if( jfaceLoc != ifaceLoc ) + if( jfaceLoc == ifaceLoc ) { - dF_dFaceP[jfaceLoc] = -transmissibility_j; // d(potDif)/d(facePres[kf]) = -1 + dF_dFaceP[jfaceLoc] = transmissibility_j * ( -1.0 ); // d(potDif)/d(facePres[kf]) = -1 } else { - dF_dFaceP[jfaceLoc] = 0.0; + dF_dFaceP[jfaceLoc] = transmissibility_j * ( -1.0 ); } - + for( integer jc = 0; jc < NC; ++jc ) { dF_dC[jc] += -transmissibility_j * dDensMean_dC[jc] * gravTimesDz_j; } } + +// for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ){ +// // Derivative w.r.t. face pressure at this face (only kf contributes since potDif uses facePres[kf]) +// if( jfaceLoc == ifaceLoc ) +// { +// dF_dFaceP[jfaceLoc] = dF_dfacePres; +// } +// else +// { +// dF_dFaceP[jfaceLoc] = 0.0; +// } +// } + + // Use element mobility (simplified upwinding for Dirichlet BC) // Upwind phase component fraction based on flow direction @@ -1589,13 +1602,10 @@ DirichletFluxKernel:: } } - if( LvArray::math::abs( facePressureJacobian ) > 0.0 ) - { - localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic, - &faceDof, - &facePressureJacobian, - 1 ); - } + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic, + &faceDof, + &facePressureJacobian, + 1 ); } } } ); From 160da955aa0ece344c2feb62fd5e8f268e021780 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 15:05:57 -0700 Subject: [PATCH 30/91] wip: --- .../CompositionalMultiphaseHybridFVM.cpp | 3 +- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 32 ++++--------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 028515c97b3..8dac5466c1b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -928,9 +928,10 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // presFace[kf] ); // localRhs[localRow] = rhsValue; // } ); -// // } ); + + } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index fb39f992e35..e02413e97a0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1440,7 +1440,6 @@ DirichletFluxKernel:: // Compute flux by looping over all connected faces with consistent transmissibility real64 f = 0.0; real64 dF_dP = 0.0; -// real64 dF_dfacePres = 0.0; real64 dF_dFaceP[NF]{}; // Derivatives of flux w.r.t. face pressures for( integer jc = 0; jc < NC; ++jc ) { @@ -1451,22 +1450,19 @@ DirichletFluxKernel:: for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { // Potential difference for each face - real64 const gravTimesDz_j = elemGravCoef[eiAdj] - faceGravCoef[cellFaces[jfaceLoc]]; - real64 const potDif_j = elemPres[eiAdj] - facePres[kf] - densMean * gravTimesDz_j; + localIndex const kfj = cellFaces[jfaceLoc]; + real64 const gravTimesDz_j = elemGravCoef[eiAdj] - faceGravCoef[kfj]; + real64 const potDif_j = elemPres[eiAdj] - facePres[kfj] - densMean * gravTimesDz_j; real64 const transmissibility_j = transMatrix[ifaceLoc][jfaceLoc]; // Accumulate flux and derivatives f += transmissibility_j * potDif_j; dF_dP += transmissibility_j * ( 1.0 - dDensMean_dP * gravTimesDz_j ); -// dF_dfacePres += transmissibility_j * ( -1.0 ); // d(potDif)/d(facePres[kf]) = -1 + // Derivative w.r.t. face pressure at this face (only kf contributes since potDif uses facePres[kf]) - if( jfaceLoc == ifaceLoc ) - { - dF_dFaceP[jfaceLoc] = transmissibility_j * ( -1.0 ); // d(potDif)/d(facePres[kf]) = -1 - } - else + if ( jfaceLoc != ifaceLoc ) { - dF_dFaceP[jfaceLoc] = transmissibility_j * ( -1.0 ); + dF_dFaceP[jfaceLoc] = -transmissibility_j; } for( integer jc = 0; jc < NC; ++jc ) @@ -1474,21 +1470,7 @@ DirichletFluxKernel:: dF_dC[jc] += -transmissibility_j * dDensMean_dC[jc] * gravTimesDz_j; } } - -// for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ){ -// // Derivative w.r.t. face pressure at this face (only kf contributes since potDif uses facePres[kf]) -// if( jfaceLoc == ifaceLoc ) -// { -// dF_dFaceP[jfaceLoc] = dF_dfacePres; -// } -// else -// { -// dF_dFaceP[jfaceLoc] = 0.0; -// } -// } - - - + // Use element mobility (simplified upwinding for Dirichlet BC) // Upwind phase component fraction based on flow direction // Use the total flux f for upwinding decision From 28cb9c7b811adac00aeac12ee2e6c2a4bfebc32c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 17:18:06 -0700 Subject: [PATCH 31/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 96 ++++++++++--------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 8dac5466c1b..1486ba6fb6a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -651,6 +651,55 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); globalIndex const rankOffset = dofManager.rankOffset(); + +// // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) +// arrayView1d< real64 const > const presFace = +// faceManager.getField< flow::facePressure >(); +// arrayView1d< real64 const > const presFaceBC = +// faceManager.getField< flow::bcPressure >(); +// +// fsManager.apply< FaceManager >( time_n + dt, +// mesh, +// flow::bcPressure::key(), +// [&] ( FieldSpecificationBase const & fs, +// string const & setName, +// SortedArrayView< localIndex const > const & targetSet, +// FaceManager & targetGroup, +// string const & ) +// { +// // Using the field specification functions to apply the boundary conditions to the system +// fs.applyFieldValue< FieldSpecificationEqual, +// parallelDevicePolicy<> >( targetSet, +// time_n + dt, +// targetGroup, +// flow::bcPressure::key() ); +// +// forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) +// { +// +// localIndex const kf = targetSet[a]; +// if( faceGhostRank[kf] >= 0 ) +// { +// return; +// } +// +// // Get the dof number of this face +// globalIndex const dofIndex = faceDofNumber[kf]; +// localIndex const localRow = dofIndex - rankOffset; +// real64 rhsValue; +// +// // Apply field value to the lhs and rhs +// FieldSpecificationEqual::SpecifyFieldValue( dofIndex, +// rankOffset, +// localMatrix, +// rhsValue, +// presFaceBC[kf], +// presFace[kf] ); +// localRhs[localRow] = rhsValue; +// } ); +// } ); + + // Get node positions arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); @@ -883,52 +932,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } } ); -// // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) -// arrayView1d< real64 const > const presFace = -// faceManager.getField< flow::facePressure >(); -// arrayView1d< real64 const > const presFaceBC = -// faceManager.getField< flow::bcPressure >(); -// -// fsManager.apply< FaceManager >( time_n + dt, -// mesh, -// flow::bcPressure::key(), -// [&] ( FieldSpecificationBase const & fs, -// string const & setName, -// SortedArrayView< localIndex const > const & targetSet, -// FaceManager & targetGroup, -// string const & ) -// { -// // Using the field specification functions to apply the boundary conditions to the system -// fs.applyFieldValue< FieldSpecificationEqual, -// parallelDevicePolicy<> >( targetSet, -// time_n + dt, -// targetGroup, -// flow::bcPressure::key() ); -// -// forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) -// { -// -// localIndex const kf = targetSet[a]; -// if( faceGhostRank[kf] >= 0 ) -// { -// return; -// } -// -// // Get the dof number of this face -// globalIndex const dofIndex = faceDofNumber[kf]; -// localIndex const localRow = dofIndex - rankOffset; -// real64 rhsValue; -// -// // Apply field value to the lhs and rhs -// FieldSpecificationEqual::SpecifyFieldValue( dofIndex, -// rankOffset, -// localMatrix, -// rhsValue, -// presFaceBC[kf], -// presFace[kf] ); -// localRhs[localRow] = rhsValue; -// } ); -// } ); + From 6dfa7ec3e2fcf512d4c8a614bc3bdfcacfbc0af2 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 18:23:45 -0700 Subject: [PATCH 32/91] wip --- .../CompositionalMultiphaseHybridFVM.cpp | 14 +++--- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 45 +++++++++++++------ 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 1486ba6fb6a..24ee9503054 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -651,7 +651,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); globalIndex const rankOffset = dofManager.rankOffset(); - // // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) // arrayView1d< real64 const > const presFace = // faceManager.getField< flow::facePressure >(); @@ -695,11 +694,16 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // rhsValue, // presFaceBC[kf], // presFace[kf] ); -// localRhs[localRow] = rhsValue; +// // ADD THESE 3 LINES: +// // 1) Ensure Jacobian has dR/dPface = 1.0 on the face row +// real64 const one = 1.0; +// localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow, &dofIndex, &one, 1 ); +// +// // 2) Set RHS = Pface - Pbc (consistent with constraint R = Pface - Pbc = 0) +// localRhs[localRow] = presFace[kf] - presFaceBC[kf]; // } ); // } ); - // Get node positions arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); @@ -931,9 +935,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } ); } } ); - - - + } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index e02413e97a0..a2c1162c8ea 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1406,6 +1406,18 @@ DirichletFluxKernel:: cellFaces[jfaceLoc] = elemToFaces[eiAdj][jfaceLoc]; } + // Enforce strong Dirichlet constraint on the boundary face: R = Pface - Pbc = 0 + // Add unit Jacobian (dR/dPface = 1.0) on the diagonal + // The RHS is handled by the BC application that runs before/after this kernel + { + globalIndex const faceDof = faceDofNumber[kf]; + localIndex const faceRow = LvArray::integerConversion< localIndex >( faceDof - rankOffset ); + + // Add unit Jacobian: dR/dPface = 1.0 on the diagonal + real64 const one = -1.0; + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( faceRow, &faceDof, &one, 1 ); + } + // Component fluxes real64 compFlux[NC]{}; real64 dCompFlux_dP[NC]{}; @@ -1449,25 +1461,22 @@ DirichletFluxKernel:: // Sum contributions from all connected faces for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { - // Potential difference for each face + // Each stencil face j uses its own face pressure localIndex const kfj = cellFaces[jfaceLoc]; real64 const gravTimesDz_j = elemGravCoef[eiAdj] - faceGravCoef[kfj]; + real64 const Tij = transMatrix[ifaceLoc][jfaceLoc]; real64 const potDif_j = elemPres[eiAdj] - facePres[kfj] - densMean * gravTimesDz_j; - real64 const transmissibility_j = transMatrix[ifaceLoc][jfaceLoc]; - + // Accumulate flux and derivatives - f += transmissibility_j * potDif_j; - dF_dP += transmissibility_j * ( 1.0 - dDensMean_dP * gravTimesDz_j ); + f += Tij * potDif_j; + dF_dP += Tij * ( 1.0 - dDensMean_dP * gravTimesDz_j ); + + // Correct Jacobian: d(potDif_j)/d(facePres[kfj]) = -1, so dF/d(facePres_j) = -T_ij + dF_dFaceP[jfaceLoc] = -Tij; - // Derivative w.r.t. face pressure at this face (only kf contributes since potDif uses facePres[kf]) - if ( jfaceLoc != ifaceLoc ) - { - dF_dFaceP[jfaceLoc] = -transmissibility_j; - } - for( integer jc = 0; jc < NC; ++jc ) { - dF_dC[jc] += -transmissibility_j * dDensMean_dC[jc] * gravTimesDz_j; + dF_dC[jc] += -Tij * dDensMean_dC[jc] * gravTimesDz_j; } } @@ -1505,14 +1514,18 @@ DirichletFluxKernel:: // For derivatives, use element properties (simplified for boundary conditions) dCompFlux_dP[ic] += dPhaseFlux_dP * ycp + beta * phaseFlux * dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic][Deriv::dP]; + // Compute dycpElem/dC for this component ic + real64 dycpElem_dC[NC]; applyChainRule( NC, dCompFrac_dCompDens[erAdj][esrAdj][eiAdj], dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic], - dProp_dC, + dycpElem_dC, Deriv::dC ); for( integer jc = 0; jc < NC; ++jc ) { - dCompFlux_dC[ic][jc] += dPhaseFlux_dC[jc] * ycp + beta * phaseFlux * dProp_dC[jc]; + // d(ycp * phaseFlux)/dC = dycp/dC * phaseFlux + ycp * dPhaseFlux/dC + // dycp/dC = beta * dycpElem/dC (ycpFace is BC, independent of C) + dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * phaseFlux * dycpElem_dC[jc]; } // Add derivatives w.r.t. face pressures @@ -1569,6 +1582,10 @@ DirichletFluxKernel:: for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { localIndex const kfj = cellFaces[jfaceLoc]; + // Skip coupling the cell rows to the same boundary face DOF we strongly constrain + if( kfj == kf ) + continue; + globalIndex const faceDof = faceDofNumber[kfj]; real64 facePressureJacobian = dt * dCompFlux_dFaceP[ic][jfaceLoc]; From e0d64e398241037261e14f988902c239b592067d Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 18:34:14 -0700 Subject: [PATCH 33/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index a2c1162c8ea..443d0b01a3e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1406,18 +1406,6 @@ DirichletFluxKernel:: cellFaces[jfaceLoc] = elemToFaces[eiAdj][jfaceLoc]; } - // Enforce strong Dirichlet constraint on the boundary face: R = Pface - Pbc = 0 - // Add unit Jacobian (dR/dPface = 1.0) on the diagonal - // The RHS is handled by the BC application that runs before/after this kernel - { - globalIndex const faceDof = faceDofNumber[kf]; - localIndex const faceRow = LvArray::integerConversion< localIndex >( faceDof - rankOffset ); - - // Add unit Jacobian: dR/dPface = 1.0 on the diagonal - real64 const one = -1.0; - localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( faceRow, &faceDof, &one, 1 ); - } - // Component fluxes real64 compFlux[NC]{}; real64 dCompFlux_dP[NC]{}; @@ -1578,6 +1566,19 @@ DirichletFluxKernel:: localFluxJacobian[ic], NC+1 ); + + // Enforce strong Dirichlet constraint on the boundary face: R = Pface - Pbc = 0 + // Add unit Jacobian (dR/dPface = 1.0) on the diagonal + // The RHS is handled by the BC application that runs before/after this kernel + { + globalIndex const faceDof = faceDofNumber[kf]; + localIndex const faceRow = LvArray::integerConversion< localIndex >( faceDof - rankOffset ); + + // Add unit Jacobian: dR/dPface = 1.0 on the diagonal + real64 const one = 1.0; + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( faceRow, &faceDof, &one, 1 ); + } + // Add contributions from face pressure derivatives for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { From c441dbd6747606150ec283472c0b7b519e315d79 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 18:42:08 -0700 Subject: [PATCH 34/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 443d0b01a3e..66b822ccbda 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1566,19 +1566,6 @@ DirichletFluxKernel:: localFluxJacobian[ic], NC+1 ); - - // Enforce strong Dirichlet constraint on the boundary face: R = Pface - Pbc = 0 - // Add unit Jacobian (dR/dPface = 1.0) on the diagonal - // The RHS is handled by the BC application that runs before/after this kernel - { - globalIndex const faceDof = faceDofNumber[kf]; - localIndex const faceRow = LvArray::integerConversion< localIndex >( faceDof - rankOffset ); - - // Add unit Jacobian: dR/dPface = 1.0 on the diagonal - real64 const one = 1.0; - localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( faceRow, &faceDof, &one, 1 ); - } - // Add contributions from face pressure derivatives for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { @@ -1608,6 +1595,18 @@ DirichletFluxKernel:: 1 ); } } + + // Enforce strong Dirichlet constraint on the boundary face: R = Pface - Pbc = 0 + // Add unit Jacobian (dR/dPface = 1.0) on the diagonal - ONCE per boundary face + // The RHS is handled by the BC application that runs before/after this kernel + { + globalIndex const faceDof = faceDofNumber[kf]; + localIndex const faceRow = LvArray::integerConversion< localIndex >( faceDof - rankOffset ); + + // Add unit Jacobian: dR/dPface = 1.0 on the diagonal + real64 const one = 1.0; + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( faceRow, &faceDof, &one, 1 ); + } } ); } From a209bc88a1d159f9664268d656e3c6c6bce5ac54 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 18:53:01 -0700 Subject: [PATCH 35/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...CompositionalMultiphaseHybridFVMKernels_impl.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 66b822ccbda..c92b470d0da 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1594,18 +1594,7 @@ DirichletFluxKernel:: &facePressureJacobian, 1 ); } - } - - // Enforce strong Dirichlet constraint on the boundary face: R = Pface - Pbc = 0 - // Add unit Jacobian (dR/dPface = 1.0) on the diagonal - ONCE per boundary face - // The RHS is handled by the BC application that runs before/after this kernel - { - globalIndex const faceDof = faceDofNumber[kf]; - localIndex const faceRow = LvArray::integerConversion< localIndex >( faceDof - rankOffset ); - - // Add unit Jacobian: dR/dPface = 1.0 on the diagonal - real64 const one = 1.0; - localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( faceRow, &faceDof, &one, 1 ); + } } ); } From cb8667bb091f6e65f08c668fb4962093f744af4a Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 19:53:43 -0700 Subject: [PATCH 36/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index c92b470d0da..d0e686fe6d0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1570,10 +1570,6 @@ DirichletFluxKernel:: for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { localIndex const kfj = cellFaces[jfaceLoc]; - // Skip coupling the cell rows to the same boundary face DOF we strongly constrain - if( kfj == kf ) - continue; - globalIndex const faceDof = faceDofNumber[kfj]; real64 facePressureJacobian = dt * dCompFlux_dFaceP[ic][jfaceLoc]; @@ -1596,6 +1592,7 @@ DirichletFluxKernel:: } } + } ); } From b1106032f64a36433f4008c200149c8e85a304b7 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 20:05:57 -0700 Subject: [PATCH 37/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 127 ++++++++++-------- 1 file changed, 74 insertions(+), 53 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 24ee9503054..d8b58563469 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -651,58 +651,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); globalIndex const rankOffset = dofManager.rankOffset(); -// // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) -// arrayView1d< real64 const > const presFace = -// faceManager.getField< flow::facePressure >(); -// arrayView1d< real64 const > const presFaceBC = -// faceManager.getField< flow::bcPressure >(); -// -// fsManager.apply< FaceManager >( time_n + dt, -// mesh, -// flow::bcPressure::key(), -// [&] ( FieldSpecificationBase const & fs, -// string const & setName, -// SortedArrayView< localIndex const > const & targetSet, -// FaceManager & targetGroup, -// string const & ) -// { -// // Using the field specification functions to apply the boundary conditions to the system -// fs.applyFieldValue< FieldSpecificationEqual, -// parallelDevicePolicy<> >( targetSet, -// time_n + dt, -// targetGroup, -// flow::bcPressure::key() ); -// -// forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) -// { -// -// localIndex const kf = targetSet[a]; -// if( faceGhostRank[kf] >= 0 ) -// { -// return; -// } -// -// // Get the dof number of this face -// globalIndex const dofIndex = faceDofNumber[kf]; -// localIndex const localRow = dofIndex - rankOffset; -// real64 rhsValue; -// -// // Apply field value to the lhs and rhs -// FieldSpecificationEqual::SpecifyFieldValue( dofIndex, -// rankOffset, -// localMatrix, -// rhsValue, -// presFaceBC[kf], -// presFace[kf] ); -// // ADD THESE 3 LINES: -// // 1) Ensure Jacobian has dR/dPface = 1.0 on the face row -// real64 const one = 1.0; -// localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow, &dofIndex, &one, 1 ); -// -// // 2) Set RHS = Pface - Pbc (consistent with constraint R = Pface - Pbc = 0) -// localRhs[localRow] = presFace[kf] - presFaceBC[kf]; -// } ); -// } ); + // Get node positions arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); @@ -727,6 +676,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Get face boundary values arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); +// std::cout << "facePres: " << facePres << std::endl; arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); @@ -936,7 +886,78 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } } ); - + // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) + arrayView1d< real64 const > const presFace = + faceManager.getField< flow::facePressure >(); + arrayView1d< real64 const > const presFaceBC = + faceManager.getField< flow::bcPressure >(); + + fsManager.apply< FaceManager >( time_n + dt, + mesh, + flow::bcPressure::key(), + [&] ( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + FaceManager & targetGroup, + string const & ) + { + // Using the field specification functions to apply the boundary conditions to the system + fs.applyFieldValue< FieldSpecificationEqual, + parallelDevicePolicy<> >( targetSet, + time_n + dt, + targetGroup, + flow::bcPressure::key() ); + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + + localIndex const kf = targetSet[a]; + if( faceGhostRank[kf] >= 0 ) + { + return; + } + + // Get the dof number of this face + globalIndex const dofIndex = faceDofNumber[kf]; + localIndex const localRow = dofIndex - rankOffset; + + // ENFORCE DIRICHLET CONSTRAINT: x_i = x_spec + // 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() ) + { + arraySlice1d< globalIndex const > const columns = localMatrix.getColumns( localRow ); + arraySlice1d< real64 > const entries = localMatrix.getEntries( localRow ); + localIndex const numEntries = localMatrix.numNonZeros( localRow ); + + // Step 1: Zero out all row entries and set diagonal to 1 + for( localIndex j = 0; j < numEntries; ++j ) + { + if( columns[j] == dofIndex ) + { + entries[j] = 1.0; // Set diagonal to 1 + } + else + { + entries[j] = 0.0; // Zero out off-diagonal entries + } + } + + // Set RHS to the prescribed boundary value (absolute value) + // This directly enforces: 1.0 * facePressure = prescribed_value + localRhs[localRow] = presFace[kf] - presFaceBC[kf]; + } + + } ); + } ); } ); } From 496bd4f31eab70c6996245f922b0831c60abea62 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 22:21:43 -0700 Subject: [PATCH 38/91] wip --- .../CompositionalMultiphaseHybridFVMKernels.hpp | 1 + ...positionalMultiphaseHybridFVMKernels_impl.hpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 71ce58e458a..4446ea3ca34 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -721,6 +721,7 @@ struct FluxKernel ArrayOfArraysView< localIndex const > const & faceToNodes, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceGravCoef, arrayView1d< real64 const > const & mimFaceGravCoef, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index d0e686fe6d0..f6f9726ccc5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -958,6 +958,7 @@ void AssemblerKernelHelper:: assembleFaceConstraints( arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arraySlice1d< localIndex const > const & elemToFaces, globalIndex const elemDofNumber, globalIndex const rankOffset, @@ -985,7 +986,16 @@ AssemblerKernelHelper:: // for each element, loop over the local (one-sided) faces for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc ) { - if( faceGhostRank[elemToFaces[ifaceLoc]] >= 0 ) + localIndex const kf = elemToFaces[ifaceLoc]; + + // Skip ghost faces + if( faceGhostRank[kf] >= 0 ) + { + continue; + } + + // Skip boundary faces - they have Dirichlet constraints, not flux continuity + if( isBoundaryFace[kf] > 0 ) { continue; } @@ -1041,6 +1051,7 @@ AssemblerKernel:: arrayView2d< localIndex const > const & elemList, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceGravCoef, arrayView1d< real64 const > const & mimFaceGravCoef, @@ -1146,6 +1157,7 @@ AssemblerKernel:: // enforcing flux continuity at this element's faces AssemblerKernelHelper::assembleFaceConstraints< NF, NC >( faceDofNumber, faceGhostRank, + isBoundaryFace, elemToFaces, elemDofNumber[er][esr][ei], rankOffset, @@ -1173,6 +1185,7 @@ FluxKernel:: ArrayOfArraysView< localIndex const > const & faceToNodes, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceGravCoef, arrayView1d< real64 const > const & mimFaceGravCoef, @@ -1262,6 +1275,7 @@ FluxKernel:: elemList, faceDofNumber, faceGhostRank, + isBoundaryFace, facePres, faceGravCoef, mimFaceGravCoef, From bb8e128330bd92326a86cbf2fffde6ab85b32558 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 22:23:36 -0700 Subject: [PATCH 39/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index d8b58563469..975df55e043 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -363,6 +363,32 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, faceManager.getReference< array1d< globalIndex > >( faceDofKey ); arrayView1d< integer const > const & faceGhostRank = faceManager.ghostRank(); + // Mark boundary faces (faces with Dirichlet BCs) to skip flux continuity constraint + // Initialize all faces as interior (0), then mark boundary faces (1) + array1d< integer > isBoundaryFace( faceManager.size() ); + isBoundaryFace.setValues< serialPolicy >( 0 ); + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) + { + string const & fieldName = fs.getFieldName(); + if( fieldName == flow::bcPressure::key() || + fieldName == flow::bcGlobalCompFraction::key() || + fieldName == flow::bcTemperature::key() ) + { + for( string const & setName : fs.getSetNames() ) + { + SortedArrayView< localIndex const > const targetSet = faceManager.getSet( setName ).toViewConst(); + forAll< serialPolicy >( targetSet.size(), [&]( localIndex const i ) + { + isBoundaryFace[targetSet[i]] = 1; + } ); + } + } + } ); + + arrayView1d< integer const > const isBoundaryFaceView = isBoundaryFace.toViewConst(); + // get the element dof numbers for the assembly string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > elemDofNumber = @@ -424,6 +450,7 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, faceToNodes, faceDofNumber, faceGhostRank, + isBoundaryFaceView, facePres, faceGravCoef, mimFaceGravCoef, @@ -651,8 +678,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); globalIndex const rankOffset = dofManager.rankOffset(); - - // Get node positions arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); From b66560a8803a552c76f3636dcb6ee3783944de2f Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 22:56:46 -0700 Subject: [PATCH 40/91] wip: adding Boundary identifiers --- ...ompositionalMultiphaseHybridFVMKernels_assembly.cpp.template | 2 ++ .../CompositionalMultiphaseHybridFVMKernels_flux.cpp.template | 1 + 2 files changed, 3 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template index d06fd73408c..42865aae6c2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template @@ -110,6 +110,7 @@ namespace compositionalMultiphaseHybridFVMKernels AssemblerKernelHelper:: assembleFaceConstraints< NF, NC >( arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arraySlice1d< localIndex const > const & elemToFaces, globalIndex const elemDofNumber, globalIndex const rankOffset, @@ -132,6 +133,7 @@ namespace compositionalMultiphaseHybridFVMKernels arrayView2d< localIndex const > const & elemList, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceGravCoef, arrayView1d< real64 const > const & mimFaceGravCoef, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template index 76c8fef1aac..ccc0cce069d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template @@ -25,6 +25,7 @@ namespace compositionalMultiphaseHybridFVMKernels ArrayOfArraysView< localIndex const > const & faceToNodes, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceGravCoef, arrayView1d< real64 const > const & mimFaceGravCoef, From 9a492300ded05c3e133e062e8ee1ddc44b0fb6b8 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 23:09:11 -0700 Subject: [PATCH 41/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- .../compositional/CompositionalMultiphaseHybridFVMKernels.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 4446ea3ca34..6f2dd5586e6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -445,6 +445,7 @@ struct AssemblerKernelHelper static void assembleFaceConstraints( arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arraySlice1d< localIndex const > const & elemToFaces, globalIndex const elemDofNumber, globalIndex const rankOffset, @@ -517,6 +518,7 @@ struct AssemblerKernel arrayView2d< localIndex const > const & elemList, arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & faceGhostRank, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceGravCoef, arrayView1d< real64 const > const & mimFaceGravCoef, From 9026ca433cbea17a450e07cc509e6c979b1cc00a Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 23:23:45 -0700 Subject: [PATCH 42/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 975df55e043..2df2cde63ba 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -105,6 +105,10 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) faceManager.registerField< flow::facePhaseCompFraction >( getName() ). 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() ); } ); @@ -181,7 +185,30 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou ": the transmissibility multipliers used in SinglePhaseHybridFVM must strictly larger than 0.0", std::runtime_error ); + // Mark boundary faces (faces with Dirichlet BCs) to skip flux continuity constraint + // Initialize all faces as interior (0), then mark boundary faces (1) + arrayView1d< integer > isBoundaryFaceView = faceManager.getField< flow::isBoundaryFace >(); + isBoundaryFaceView.setValues< serialPolicy >( 0 ); + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) + { + string const & fieldName = fs.getFieldName(); + if( fieldName == flow::bcPressure::key() || + fieldName == flow::bcGlobalCompFraction::key() || + fieldName == flow::bcTemperature::key() ) + { + for( string const & setName : fs.getSetNames() ) + { + SortedArrayView< localIndex const > const targetSet = faceManager.getSet( setName ).toViewConst(); + forAll< serialPolicy >( targetSet.size(), [=]( localIndex const i ) + { + isBoundaryFaceView[targetSet[i]] = 1; + } ); + } + } + } ); + fsManager.forSubGroups< AquiferBoundaryCondition >( [&] ( AquiferBoundaryCondition const & bc ) { GEOS_LOG_RANK_0( getCatalogName() << " " << getDataContext() << ": An aquifer boundary condition named " << @@ -363,31 +390,9 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, faceManager.getReference< array1d< globalIndex > >( faceDofKey ); arrayView1d< integer const > const & faceGhostRank = faceManager.ghostRank(); - // Mark boundary faces (faces with Dirichlet BCs) to skip flux continuity constraint - // Initialize all faces as interior (0), then mark boundary faces (1) - array1d< integer > isBoundaryFace( faceManager.size() ); - isBoundaryFace.setValues< serialPolicy >( 0 ); - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) - { - string const & fieldName = fs.getFieldName(); - if( fieldName == flow::bcPressure::key() || - fieldName == flow::bcGlobalCompFraction::key() || - fieldName == flow::bcTemperature::key() ) - { - for( string const & setName : fs.getSetNames() ) - { - SortedArrayView< localIndex const > const targetSet = faceManager.getSet( setName ).toViewConst(); - forAll< serialPolicy >( targetSet.size(), [&]( localIndex const i ) - { - isBoundaryFace[targetSet[i]] = 1; - } ); - } - } - } ); - - arrayView1d< integer const > const isBoundaryFaceView = isBoundaryFace.toViewConst(); + // Get boundary face indicator (initialized during initializePostInitialConditionsPreSubGroups) + arrayView1d< integer const > const isBoundaryFaceView = + faceManager.getField< flow::isBoundaryFace >(); // get the element dof numbers for the assembly string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); From e2fd31738d644a6b682c5aa7c8c13006747925a4 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 23:34:32 -0700 Subject: [PATCH 43/91] wip: --- ...MultiphaseHybridFVMKernels_assembly.cpp.template | 1 + .../fluidFlow/FlowSolverBaseFields.hpp | 8 ++++++++ ...CompositionalMultiphaseHybridFVMKernels_impl.hpp | 13 ++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template index 42865aae6c2..60644fe8958 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template @@ -42,6 +42,7 @@ namespace compositionalMultiphaseHybridFVMKernels arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & mimFaceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp index 50e79137a4b..0a9b8e10c29 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp @@ -89,6 +89,14 @@ DECLARE_FIELD( facePressure_n, NO_WRITE, "Face pressure at the previous converged time step" ); +DECLARE_FIELD( isBoundaryFace, + "isBoundaryFace", + array1d< integer >, + 0, + NOPLOT, + NO_WRITE, + "Boundary face indicator: 1 for faces with Dirichlet BCs, 0 for interior faces" ); + DECLARE_FIELD( pressureGradient, "pressureGradient", array2d< real64 >, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index f6f9726ccc5..6911f1d9024 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -617,6 +617,7 @@ AssemblerKernelHelper:: arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & mimFaceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, @@ -677,6 +678,13 @@ AssemblerKernelHelper:: // for each element, loop over the one-sided faces for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc ) { + localIndex const kf = elemToFaces[ifaceLoc]; + + // Skip boundary faces - their fluxes are handled by DirichletFluxKernel + if( isBoundaryFace[kf] > 0 ) + { + continue; + } // 1) Find if there is a neighbor, and if there is, grab the indices of the neighbor element @@ -1129,6 +1137,7 @@ AssemblerKernel:: elemList, regionFilter, faceDofNumber, + isBoundaryFace, mimFaceGravCoef, elemToFaces, elemGravCoef, @@ -1485,7 +1494,8 @@ DirichletFluxKernel:: // Use element mobility (simplified upwinding for Dirichlet BC) // Upwind phase component fraction based on flow direction // Use the total flux f for upwinding decision - real64 const beta = (f > 0.0) ? 1.0 : 0.0; +// real64 const beta = (f > 0.0) ? 1.0 : 0.0; + real64 const beta = 0.0;//(f > 0.0) ? 1.0 : 0.0; real64 const facePhaseMobility = facePhaseMob[kf][ip]; real64 const phaseMobility = beta * phaseMob[erAdj][esrAdj][eiAdj][ip] + (1.0 - beta) * facePhaseMobility; real64 const phaseFlux = phaseMobility * f; @@ -1567,6 +1577,7 @@ DirichletFluxKernel:: for( integer ic = 0; ic < NC; ++ic ) { RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[localRow + ic], localFlux[ic] ); + continue; globalIndex dofColIndices[NC+1]; dofColIndices[0] = elemDof; From 97029a50a7ba879f92c4710f2b7c718638007a05 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 27 Oct 2025 23:47:59 -0700 Subject: [PATCH 44/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- .../compositional/CompositionalMultiphaseHybridFVMKernels.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 6f2dd5586e6..74e4edfed86 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -332,6 +332,7 @@ struct AssemblerKernelHelper arrayView2d< localIndex const > const & elemList, SortedArrayView< localIndex const > const & regionFilter, arrayView1d< globalIndex const > const & faceDofNumber, + arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & mimFaceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, From 393bf064e81d87e375f8c2b23d9e69b68eacd132 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 00:07:56 -0700 Subject: [PATCH 45/91] wip: --- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 6911f1d9024..2d00a4263f3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -622,15 +622,15 @@ AssemblerKernelHelper:: arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, - ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const & phaseDens, - ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const & dPhaseDens, - ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const & phaseMassDens, - ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const & dPhaseMassDens, + ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseDens, + ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseDens, + ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseMassDens, + ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseMassDens, ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, - ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, + 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, real64 const (&oneSidedVolFlux)[ NF ], From 97ab88a04a4490975a3b8309742039627686c678 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 08:02:08 -0700 Subject: [PATCH 46/91] wip: --- .../CompositionalMultiphaseHybridFVM.cpp | 6 +-- .../fluidFlow/FlowSolverBaseFields.hpp | 2 +- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 38 ++++++++++--------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 2df2cde63ba..53ac9fd89f5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -159,7 +159,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou string_array const & regionNames ) { ElementRegionManager const & elemManager = mesh.getElemManager(); - FaceManager const & faceManager = mesh.getFaceManager(); + FaceManager & faceManager = mesh.getFaceManager(); CompositionalMultiphaseBase::initializePostInitialConditionsPreSubGroups(); @@ -187,8 +187,8 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou // Mark boundary faces (faces with Dirichlet BCs) to skip flux continuity constraint // Initialize all faces as interior (0), then mark boundary faces (1) - arrayView1d< integer > isBoundaryFaceView = faceManager.getField< flow::isBoundaryFace >(); - isBoundaryFaceView.setValues< serialPolicy >( 0 ); + arrayView1d< integer > const isBoundaryFaceView = faceManager.getReference< array1d< integer > >( flow::isBoundaryFace::key() ); +// isBoundaryFaceView.setValues< serialPolicy >( 0 ); // default is zero FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp index 0a9b8e10c29..22f363f2c22 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp @@ -94,7 +94,7 @@ DECLARE_FIELD( isBoundaryFace, array1d< integer >, 0, NOPLOT, - NO_WRITE, + WRITE_AND_READ, "Boundary face indicator: 1 for faces with Dirichlet BCs, 0 for interior faces" ); DECLARE_FIELD( pressureGradient, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 2d00a4263f3..d48e69aed7a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -647,6 +647,7 @@ AssemblerKernelHelper:: // dof numbers globalIndex dofColIndicesElemVars[ NDOF*(NF+1) ]{}; globalIndex dofColIndicesFaceVars[ NF ]{}; + integer numNonBoundaryFaces = 0; for( integer idof = 0; idof < NDOF; ++idof ) { dofColIndicesElemVars[idof] = elemDofNumber[localIds[0]][localIds[1]][localIds[2]] + idof; @@ -678,16 +679,8 @@ AssemblerKernelHelper:: // for each element, loop over the one-sided faces for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc ) { - localIndex const kf = elemToFaces[ifaceLoc]; - - // Skip boundary faces - their fluxes are handled by DirichletFluxKernel - if( isBoundaryFace[kf] > 0 ) - { - continue; - } // 1) Find if there is a neighbor, and if there is, grab the indices of the neighbor element - localIndex neighborIds[ 3 ] = { localIds[0], localIds[1], localIds[2] }; hybridFVMKernels::CellConnectivity::isNeighborFound( localIds, ifaceLoc, @@ -738,6 +731,13 @@ AssemblerKernelHelper:: dofColIndicesElemVars, dofColIndicesFaceVars ); + // Collect face DOF number only if this is not a boundary face + if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) + { + dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; + numNonBoundaryFaces++; + } + // 3) *************** Assemble buoyancy terms ****************** real64 const transGravCoef = (localIds[0] != neighborIds[0] || localIds[1] != neighborIds[1] || localIds[2] != neighborIds[2]) @@ -807,11 +807,14 @@ AssemblerKernelHelper:: &dDivMassFluxes_dElemVars[0][0] + ic * NDOF * (NF+1), NDOF * (NF+1) ); - // jacobian -- derivatives wrt face centered vars - localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex, - &dofColIndicesFaceVars[0], - &dDivMassFluxes_dFaceVars[0][0] + ic * NF, - NF ); + // jacobian -- derivatives wrt face centered vars (only non-boundary faces) + if( numNonBoundaryFaces > 0 ) + { + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex, + &dofColIndicesFaceVars[0], + &dDivMassFluxes_dFaceVars[0][0] + ic * NF, + numNonBoundaryFaces ); + } } } @@ -894,7 +897,8 @@ AssemblerKernelHelper:: { dofColIndicesElemVars[elemVarsOffset+idof] = neighborDofNumber + idof; } - dofColIndicesFaceVars[ifaceLoc] = faceDofNumber; + // Note: dofColIndicesFaceVars[ifaceLoc] is now set in assembleFluxDivergence + // after checking if the face is a boundary face } template< integer NF, integer NC, integer NP > @@ -1494,8 +1498,7 @@ DirichletFluxKernel:: // Use element mobility (simplified upwinding for Dirichlet BC) // Upwind phase component fraction based on flow direction // Use the total flux f for upwinding decision -// real64 const beta = (f > 0.0) ? 1.0 : 0.0; - real64 const beta = 0.0;//(f > 0.0) ? 1.0 : 0.0; + real64 const beta = (f > 0.0) ? 1.0 : 0.0; real64 const facePhaseMobility = facePhaseMob[kf][ip]; real64 const phaseMobility = beta * phaseMob[erAdj][esrAdj][eiAdj][ip] + (1.0 - beta) * facePhaseMobility; real64 const phaseFlux = phaseMobility * f; @@ -1537,7 +1540,7 @@ DirichletFluxKernel:: { // d(ycp * phaseFlux)/dC = dycp/dC * phaseFlux + ycp * dPhaseFlux/dC // dycp/dC = beta * dycpElem/dC (ycpFace is BC, independent of C) - dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * phaseFlux * dycpElem_dC[jc]; + dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * dycpElem_dC[jc] * phaseFlux; } // Add derivatives w.r.t. face pressures @@ -1577,7 +1580,6 @@ DirichletFluxKernel:: for( integer ic = 0; ic < NC; ++ic ) { RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[localRow + ic], localFlux[ic] ); - continue; globalIndex dofColIndices[NC+1]; dofColIndices[0] = elemDof; From e7edc2307e43959dd6bb1d45965ef96bef42ae1b Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 09:23:38 -0700 Subject: [PATCH 47/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index d48e69aed7a..ed4325811f2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -647,6 +647,7 @@ AssemblerKernelHelper:: // dof numbers globalIndex dofColIndicesElemVars[ NDOF*(NF+1) ]{}; globalIndex dofColIndicesFaceVars[ NF ]{}; + integer faceIndexMap[ NF ]{}; // Maps local face index to position in compact DOF array integer numNonBoundaryFaces = 0; for( integer idof = 0; idof < NDOF; ++idof ) { @@ -734,9 +735,14 @@ AssemblerKernelHelper:: // Collect face DOF number only if this is not a boundary face if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) { + faceIndexMap[ifaceLoc] = numNonBoundaryFaces; dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; numNonBoundaryFaces++; } + else + { + faceIndexMap[ifaceLoc] = -1; // Mark boundary faces + } // 3) *************** Assemble buoyancy terms ****************** @@ -808,11 +814,21 @@ AssemblerKernelHelper:: NDOF * (NF+1) ); // jacobian -- derivatives wrt face centered vars (only non-boundary faces) + // Need to compact the derivatives array to only include non-boundary faces if( numNonBoundaryFaces > 0 ) { + real64 compactFaceDerivs[ NF ]{}; + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + if( faceIndexMap[jfaceLoc] >= 0 ) + { + compactFaceDerivs[faceIndexMap[jfaceLoc]] = dDivMassFluxes_dFaceVars[ic][jfaceLoc]; + } + } + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex, &dofColIndicesFaceVars[0], - &dDivMassFluxes_dFaceVars[0][0] + ic * NF, + compactFaceDerivs, numNonBoundaryFaces ); } } @@ -1540,7 +1556,7 @@ DirichletFluxKernel:: { // d(ycp * phaseFlux)/dC = dycp/dC * phaseFlux + ycp * dPhaseFlux/dC // dycp/dC = beta * dycpElem/dC (ycpFace is BC, independent of C) - dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * dycpElem_dC[jc] * phaseFlux; + dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * phaseFlux * dycpElem_dC[jc]; } // Add derivatives w.r.t. face pressures From cc63407f42a1cdb8b2ae575228cd9ccda039467a Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 21:08:00 -0700 Subject: [PATCH 48/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index ed4325811f2..5985ecc119a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -733,16 +733,16 @@ AssemblerKernelHelper:: dofColIndicesFaceVars ); // Collect face DOF number only if this is not a boundary face - if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) - { - faceIndexMap[ifaceLoc] = numNonBoundaryFaces; - dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; - numNonBoundaryFaces++; - } - else - { - faceIndexMap[ifaceLoc] = -1; // Mark boundary faces - } +// if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) +// { + faceIndexMap[ifaceLoc] = numNonBoundaryFaces; + dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; + numNonBoundaryFaces++; +// } +// else +// { +// faceIndexMap[ifaceLoc] = -1; // Mark boundary faces +// } // 3) *************** Assemble buoyancy terms ****************** From b7b7308685c819061b4ec12cf372619eb5797c80 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 22:08:52 -0700 Subject: [PATCH 49/91] wip: consistent pressure solution --- .../CompositionalMultiphaseHybridFVM.cpp | 17 +- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 238 ++++++++++-------- 2 files changed, 150 insertions(+), 105 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 53ac9fd89f5..1ac573a991b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -208,7 +208,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou } } } ); - + fsManager.forSubGroups< AquiferBoundaryCondition >( [&] ( AquiferBoundaryCondition const & bc ) { GEOS_LOG_RANK_0( getCatalogName() << " " << getDataContext() << ": An aquifer boundary condition named " << @@ -393,6 +393,21 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, // Get boundary face indicator (initialized during initializePostInitialConditionsPreSubGroups) arrayView1d< integer const > const isBoundaryFaceView = faceManager.getField< flow::isBoundaryFace >(); + +// // Print isBoundaryFaceView for debugging +// std::cout << "=== isBoundaryFaceView Debug Info ===" << std::endl; +// std::cout << "Total number of faces: " << faceManager.size() << std::endl; +// integer numBoundaryFaces = 0; +// for( localIndex iface = 0; iface < faceManager.size(); ++iface ) +// { +// if( isBoundaryFaceView[iface] == 1 ) +// { +// std::cout << "Face " << iface << " is a boundary face" << std::endl; +// numBoundaryFaces++; +// } +// } +// std::cout << "Total boundary faces: " << numBoundaryFaces << std::endl; +// std::cout << "=====================================" << std::endl; // get the element dof numbers for the assembly string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 5985ecc119a..3c7cd743371 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -680,107 +680,110 @@ AssemblerKernelHelper:: // for each element, loop over the one-sided faces for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc ) { - - // 1) Find if there is a neighbor, and if there is, grab the indices of the neighbor element - localIndex neighborIds[ 3 ] = { localIds[0], localIds[1], localIds[2] }; - hybridFVMKernels::CellConnectivity::isNeighborFound( localIds, - ifaceLoc, - elemRegionList, - elemSubRegionList, - elemList, - regionFilter, - elemToFaces, - neighborIds ); - 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, - phaseDens, - dPhaseDens, - phaseMob, - dPhaseMob, - dCompFrac_dCompDens, - phaseCompFrac, - dPhaseCompFrac, - elemDofNumber, - oneSidedVolFlux[ifaceLoc], - upwPhaseViscCoef, - dUpwPhaseViscCoef_dPres, - dUpwPhaseViscCoef_dCompDens, - upwViscDofNumber ); - - // 2.b) Add the \x_{c,\ell} \rho_{\ell} \frac{\lambda_{\ell}}{\lambda_T} q_T of this face to the divergence of the flux in this cell - assembleViscousFlux< NF, NC, NP >( ifaceLoc, - oneSidedVolFlux, - dOneSidedVolFlux_dPres, - dOneSidedVolFlux_dFacePres, - dOneSidedVolFlux_dCompDens, - upwPhaseViscCoef, - dUpwPhaseViscCoef_dPres, - dUpwPhaseViscCoef_dCompDens, - elemDofNumber[localIds[0]][localIds[1]][localIds[2]], - neighborDofNumber, - upwViscDofNumber, - faceDofNumber[elemToFaces[ifaceLoc]], - dt, - divMassFluxes, - dDivMassFluxes_dElemVars, - dDivMassFluxes_dFaceVars, - dofColIndicesElemVars, - dofColIndicesFaceVars ); - - // Collect face DOF number only if this is not a boundary face -// if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) -// { - faceIndexMap[ifaceLoc] = numNonBoundaryFaces; - dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; - numNonBoundaryFaces++; -// } -// else -// { -// faceIndexMap[ifaceLoc] = -1; // Mark boundary faces -// } - - // 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]]); - - // 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 - UpwindingHelper::upwindBuoyancyCoefficient< NC, NP >( localIds, - neighborIds, - transGravCoef, - phaseDens, - dPhaseDens, - phaseMassDens, - dPhaseMassDens, - phaseMob, - dPhaseMob, - dCompFrac_dCompDens, - phaseCompFrac, - dPhaseCompFrac, - phaseGravTerm, - dPhaseGravTerm_dPres, - dPhaseGravTerm_dCompDens, - upwPhaseGravCoef, - dUpwPhaseGravCoef_dPres, - dUpwPhaseGravCoef_dCompDens ); - - // 3.b) Add the buoyancy term of this face to the divergence of the flux in this cell - assembleBuoyancyFlux< NF, NC, NP >( ifaceLoc, - phaseGravTerm, - dPhaseGravTerm_dPres, - dPhaseGravTerm_dCompDens, - upwPhaseGravCoef, - dUpwPhaseGravCoef_dPres, - dUpwPhaseGravCoef_dCompDens, - dt, - divMassFluxes, - dDivMassFluxes_dElemVars ); + + // Contribute and Collect face DOF number only if this is not a boundary face + if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) + { + // 1) Find if there is a neighbor, and if there is, grab the indices of the neighbor element + localIndex neighborIds[ 3 ] = { localIds[0], localIds[1], localIds[2] }; + hybridFVMKernels::CellConnectivity::isNeighborFound( localIds, + ifaceLoc, + elemRegionList, + elemSubRegionList, + elemList, + regionFilter, + elemToFaces, + neighborIds ); + 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, + phaseDens, + dPhaseDens, + phaseMob, + dPhaseMob, + dCompFrac_dCompDens, + phaseCompFrac, + dPhaseCompFrac, + elemDofNumber, + oneSidedVolFlux[ifaceLoc], + upwPhaseViscCoef, + dUpwPhaseViscCoef_dPres, + dUpwPhaseViscCoef_dCompDens, + upwViscDofNumber ); + + // 2.b) Add the \x_{c,\ell} \rho_{\ell} \frac{\lambda_{\ell}}{\lambda_T} q_T of this face to the divergence of the flux in this cell + assembleViscousFlux< NF, NC, NP >( ifaceLoc, + oneSidedVolFlux, + dOneSidedVolFlux_dPres, + dOneSidedVolFlux_dFacePres, + dOneSidedVolFlux_dCompDens, + upwPhaseViscCoef, + dUpwPhaseViscCoef_dPres, + dUpwPhaseViscCoef_dCompDens, + elemDofNumber[localIds[0]][localIds[1]][localIds[2]], + neighborDofNumber, + upwViscDofNumber, + faceDofNumber[elemToFaces[ifaceLoc]], + dt, + divMassFluxes, + dDivMassFluxes_dElemVars, + dDivMassFluxes_dFaceVars, + dofColIndicesElemVars, + dofColIndicesFaceVars ); + + + faceIndexMap[ifaceLoc] = numNonBoundaryFaces; + dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; + numNonBoundaryFaces++; + + + // 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]]); + + // 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 + UpwindingHelper::upwindBuoyancyCoefficient< NC, NP >( localIds, + neighborIds, + transGravCoef, + phaseDens, + dPhaseDens, + phaseMassDens, + dPhaseMassDens, + phaseMob, + dPhaseMob, + dCompFrac_dCompDens, + phaseCompFrac, + dPhaseCompFrac, + phaseGravTerm, + dPhaseGravTerm_dPres, + dPhaseGravTerm_dCompDens, + upwPhaseGravCoef, + dUpwPhaseGravCoef_dPres, + dUpwPhaseGravCoef_dCompDens ); + + // 3.b) Add the buoyancy term of this face to the divergence of the flux in this cell + assembleBuoyancyFlux< NF, NC, NP >( ifaceLoc, + phaseGravTerm, + dPhaseGravTerm_dPres, + dPhaseGravTerm_dCompDens, + upwPhaseGravCoef, + dUpwPhaseGravCoef_dPres, + dUpwPhaseGravCoef_dCompDens, + dt, + divMassFluxes, + dDivMassFluxes_dElemVars ); + + } + else + { + faceIndexMap[ifaceLoc] = -1; // Mark boundary faces + } } @@ -808,10 +811,37 @@ AssemblerKernelHelper:: localRhs[eqnRowLocalIndex] = localRhs[eqnRowLocalIndex] + divMassFluxes[ic]; // jacobian -- derivative wrt elem centered vars + // Need to compact both DOF indices and derivatives to only include non-boundary neighbors + globalIndex compactElemDofs[ NDOF*(NF+1) ]; + real64 compactElemDerivs[ NDOF*(NF+1) ]; + + // Copy current element DOFs and derivatives + for( integer idof = 0; idof < NDOF; ++idof ) + { + compactElemDofs[idof] = dofColIndicesElemVars[idof]; + compactElemDerivs[idof] = dDivMassFluxes_dElemVars[ic][idof]; + } + + // Copy neighbor DOFs and derivatives only for non-boundary faces + integer compactIdx = NDOF; + for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) + { + if( faceIndexMap[jfaceLoc] >= 0 ) // non-boundary face + { + integer const neighborOffset = NDOF * (jfaceLoc + 1); + for( integer idof = 0; idof < NDOF; ++idof ) + { + compactElemDofs[compactIdx] = dofColIndicesElemVars[neighborOffset + idof]; + compactElemDerivs[compactIdx] = dDivMassFluxes_dElemVars[ic][neighborOffset + idof]; + compactIdx++; + } + } + } + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex, - &dofColIndicesElemVars[0], - &dDivMassFluxes_dElemVars[0][0] + ic * NDOF * (NF+1), - NDOF * (NF+1) ); + compactElemDofs, + compactElemDerivs, + compactIdx ); // jacobian -- derivatives wrt face centered vars (only non-boundary faces) // Need to compact the derivatives array to only include non-boundary faces From 84275e199d0640e504c2002afeb260005aad1555 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 22:26:42 -0700 Subject: [PATCH 50/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 1ac573a991b..56e7f3ba872 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -997,7 +997,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } // Set RHS to the prescribed boundary value (absolute value) - // This directly enforces: 1.0 * facePressure = prescribed_value localRhs[localRow] = presFace[kf] - presFaceBC[kf]; } From 0dfc988660382cf0d5e54c02d300f845fdefe7e9 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 23:11:43 -0700 Subject: [PATCH 51/91] wip: adding integration test --- .../fluidFlowTests/CMakeLists.txt | 3 +- ...stCompositionalMultiPhaseMFDPolyhedral.cpp | 560 ++++++++++++++++++ 2 files changed, 562 insertions(+), 1 deletion(-) create mode 100644 src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp diff --git a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt index 129b10676c6..eede401fa14 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt @@ -10,7 +10,8 @@ if( ENABLE_PVTPackage ) list( APPEND gtest_geosx_tests testCompMultiphaseFlow.cpp testCompMultiphaseFlowHybrid.cpp - testReactiveCompositionalMultiphaseOBL.cpp ) + testReactiveCompositionalMultiphaseOBL.cpp + testCompositionalMultiPhaseMFDPolyhedral.cpp ) endif() set( tplDependencyList ${parallelDeps} gtest ) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp new file mode 100644 index 00000000000..b4449e85823 --- /dev/null +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -0,0 +1,560 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * ------------------------------------------------------------------------------------------------------------ + */ + +#include + +#include "integrationTests/fluidFlowTests/testCompFlowUtils.hpp" +#include "mainInterface/initialization.hpp" +#include "mainInterface/ProblemManager.hpp" +#include "mainInterface/GeosxState.hpp" +#include "mesh/DomainPartition.hpp" +#include "physicsSolvers/PhysicsSolverManager.hpp" + +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp" + +using namespace geos; +using namespace geos::dataRepository; +using namespace geos::testing; + +CommandLineOptions g_commandLineOptions; + +// Pressure L2 error tolerance +static constexpr real64 PRESSURE_L2_TOLERANCE = 1.0e-10; +static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-10; + +// Single time step +static constexpr real64 TIME_STEP = 1.0e-2; // 0.01 + +static constexpr auto INNER_TPFA = "TPFA"; + +// Generate XML for compositional multiphase FV-TPFA (simplified from user-provided template) +static std::string generateXmlInputCompTPFA( std::string const & meshFile ) +{ + std::ostringstream oss; + oss << R"xml( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + return oss.str(); +} + +// Generate XML for compositional multiphase Hybrid MFD with configurable inner product (default TPFA) +static std::string generateXmlInputCompMFD( std::string const & innerProductType, + std::string const & meshFile ) +{ + std::ostringstream oss; + oss << R"xml( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + return oss.str(); +} + +// Helper: copy arrayView1d to std::vector +static inline std::vector< real64 > arrayViewToVector( arrayView1d< real64 const > & arr, localIndex n ) +{ + arr.move( hostMemorySpace, false ); + return std::vector< real64 >( arr.data(), arr.data() + n ); +} + +// Helper: copy a 2D view to flat vector (row-major by phase index), accept any 2D view type +template< typename View2D > +static inline std::vector< real64 > arrayView2dToVector( View2D & arr, localIndex nCells, localIndex nCols ) +{ + arr.move( hostMemorySpace, false ); + std::vector< real64 > out; + out.reserve( static_cast< size_t >( nCells ) * static_cast< size_t >( nCols ) ); + for( localIndex i = 0; i < nCells; ++i ) + { + for( localIndex j = 0; j < nCols; ++j ) + { + out.push_back( static_cast< real64 >( arr( i, j ) ) ); + } + } + return out; +} + +// TPFA test: check linear pressure profile on regular polyhedral mesh +class CompositionalTPFAIntegrationTest : public ::testing::Test +{ +public: + CompositionalTPFAIntegrationTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + +protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + std::string meshFile = testBinaryDir + "/polyhedral_voronoi_regular.vtu"; + std::string xmlInput = generateXmlInputCompTPFA( meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; +}; + +TEST_F( CompositionalTPFAIntegrationTest, PressureFieldL2Error ) +{ + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); +} + +// MFD-TPFA test: check linear pressure profile on regular polyhedral mesh +class CompositionalMFDTPFAIntegrationTest : public ::testing::Test +{ +public: + CompositionalMFDTPFAIntegrationTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + +protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + std::string meshFile = testBinaryDir + "/polyhedral_voronoi_regular.vtu"; + std::string xmlInput = generateXmlInputCompMFD( INNER_TPFA, meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; +}; + +TEST_F( CompositionalMFDTPFAIntegrationTest, PressureFieldL2Error ) +{ + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); +} + +// Cross-check: TPFA vs MFD(TPFA): pressure and saturation profiles must match exactly +TEST( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) +{ + std::string const testBinaryDir = TEST_BINARY_DIR; + std::string const meshFile = testBinaryDir + "/polyhedral_voronoi_regular.vtu"; + + std::vector< real64 > p_tpfa, p_mfd; + std::vector< real64 > sat_tpfa, sat_mfd; // phase volume fractions flattened [cell,phase] + localIndex n_cells_tpfa = 0, n_cells_mfd = 0; + localIndex n_phases_tpfa = 2, n_phases_mfd = 2; // From XML phaseNames + + // --- Run TPFA solver --- + { + GeosxState tpfaState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); + std::string xml = generateXmlInputCompTPFA( meshFile ); + setupProblemFromXML( tpfaState.getProblemManager(), xml.c_str() ); + + ProblemManager & pm = tpfaState.getProblemManager(); + DomainPartition & domain = pm.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseFVM & >( + pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); + + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); + n_cells_tpfa = subRegion.size(); + p_tpfa = arrayViewToVector( p_h, n_cells_tpfa ); + + auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); + sat_tpfa = arrayView2dToVector( sat, n_cells_tpfa, n_phases_tpfa ); + } + + // --- Run MFD solver (innerProductType = TPFA) --- + { + GeosxState mfdState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); + std::string xml = generateXmlInputCompMFD( INNER_TPFA, meshFile ); + setupProblemFromXML( mfdState.getProblemManager(), xml.c_str() ); + + ProblemManager & pm = mfdState.getProblemManager(); + DomainPartition & domain = pm.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); + n_cells_mfd = subRegion.size(); + p_mfd = arrayViewToVector( p_h, n_cells_mfd ); + + auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); + sat_mfd = arrayView2dToVector( sat, n_cells_mfd, n_phases_mfd ); + } + + ASSERT_EQ( n_cells_tpfa, n_cells_mfd ); + ASSERT_EQ( n_phases_tpfa, n_phases_mfd ); + + // Pressure profile equality + for( localIndex i = 0; i < n_cells_tpfa; ++i ) + { + real64 const diff = std::abs( p_tpfa[i] - p_mfd[i] ); + EXPECT_NEAR( diff, 0.0, PRESSURE_L2_TOLERANCE ); + } + + // Saturation profile (phase volume fraction) equality + size_t const nTot = static_cast< size_t >( n_cells_tpfa ) * static_cast< size_t >( n_phases_tpfa ); + for( size_t k = 0; k < nTot; ++k ) + { + real64 const diff = std::abs( sat_tpfa[k] - sat_mfd[k] ); + EXPECT_NEAR( diff, 0.0, SATURATION_L2_TOLERANCE ); + } +} + +int main( int argc, char * * argv ) +{ + ::testing::InitGoogleTest( &argc, argv ); + g_commandLineOptions = *geos::basicSetup( argc, argv ); + int result = RUN_ALL_TESTS(); + geos::basicCleanup(); + return result; +} From 7171e333586c7ab8b78afe6bcb654cd0a7b92a6c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 28 Oct 2025 23:36:37 -0700 Subject: [PATCH 52/91] Update testCompositionalMultiPhaseMFDPolyhedral.cpp --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index b4449e85823..a2682e243aa 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -56,7 +56,7 @@ static std::string generateXmlInputCompTPFA( std::string const & meshFile ) useMass="1" temperature="300"> + objectPath="ElementRegions/Domain" fieldName="globalCompFraction" component="0" scale="1.0"/> + objectPath="ElementRegions/Domain" fieldName="globalCompFraction" component="1" scale="0.0"/> + objectPath="ElementRegions/Domain" fieldName="globalCompFraction" component="0" scale="1.0"/> + objectPath="ElementRegions/Domain" fieldName="globalCompFraction" component="1" scale="0.0"/> Date: Wed, 29 Oct 2025 00:03:22 -0700 Subject: [PATCH 53/91] wip: adding support for full set of cells and inner products --- .../CompositionalMultiphaseHybridFVM.cpp | 56 +++++++++++++++---- .../physicsSolvers/fluidFlow/kernelSpecs.json | 24 +++++++- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 56e7f3ba872..08b681b26c5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -901,23 +901,57 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n localRhs ); }; - if( innerProductType == "TPFA" ) + // Helper lambda to dispatch on number of faces per element + auto launchForFaces = [&]( auto IP_TAG ) { if( numFacesPerElement == 4 ) - launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 4 >{} ); + launchKernel( IP_TAG, std::integral_constant< integer, 4 >{} ); else if( numFacesPerElement == 5 ) - launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 5 >{} ); + launchKernel( IP_TAG, std::integral_constant< integer, 5 >{} ); else if( numFacesPerElement == 6 ) - launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 6 >{} ); + launchKernel( IP_TAG, std::integral_constant< integer, 6 >{} ); + else if( numFacesPerElement == 7 ) + launchKernel( IP_TAG, std::integral_constant< integer, 7 >{} ); + else if( numFacesPerElement == 8 ) + launchKernel( IP_TAG, std::integral_constant< integer, 8 >{} ); + else if( numFacesPerElement == 9 ) + launchKernel( IP_TAG, std::integral_constant< integer, 9 >{} ); + else if( numFacesPerElement == 10 ) + launchKernel( IP_TAG, std::integral_constant< integer, 10 >{} ); + else if( numFacesPerElement == 11 ) + launchKernel( IP_TAG, std::integral_constant< integer, 11 >{} ); + else if( numFacesPerElement == 12 ) + launchKernel( IP_TAG, std::integral_constant< integer, 12 >{} ); + else if( numFacesPerElement == 13 ) + launchKernel( IP_TAG, std::integral_constant< integer, 13 >{} ); + else + GEOS_ERROR( "Unsupported number of faces per element: " << numFacesPerElement ); + }; + + // Inner-product selection + if( innerProductType == "TPFA" ) + { + launchForFaces( TPFAInnerProduct{} ); } - else if( innerProductType == "BDVLM" || innerProductType == "BdVLM" ) + else if( innerProductType == "quasiTPFA" ) { - if( numFacesPerElement == 4 ) - launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 4 >{} ); - else if( numFacesPerElement == 5 ) - launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 5 >{} ); - else if( numFacesPerElement == 6 ) - launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 6 >{} ); + launchForFaces( QuasiTPFAInnerProduct{} ); + } + else if( innerProductType == "quasiRT" ) + { + launchForFaces( QuasiRTInnerProduct{} ); + } + else if( innerProductType == "simple" ) + { + launchForFaces( SimpleInnerProduct{} ); + } + else if( innerProductType == "beiraoDaVeigaLipnikovManzini" ) + { + launchForFaces( BdVLMInnerProduct{} ); + } + else + { + GEOS_ERROR( "Unsupported inner product type: " << innerProductType ); } }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index a8602aab977..25cd1058ecc 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -122,7 +122,14 @@ "NFACES": [ 4, 5, - 6 + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13 ], "NCOMPS": [ 1, @@ -137,6 +144,9 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", + "mimeticInnerProduct::QuasiTPFAInnerProduct", + "mimeticInnerProduct::QuasiRTInnerProduct", + "mimeticInnerProduct::SimpleInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, @@ -155,7 +165,14 @@ "NFACES": [ 4, 5, - 6 + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13 ], "NCOMPS": [ 1, @@ -170,6 +187,9 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", + "mimeticInnerProduct::QuasiTPFAInnerProduct", + "mimeticInnerProduct::QuasiRTInnerProduct", + "mimeticInnerProduct::SimpleInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, From 1e88b3e84521a31f1a4f27c189d00d44614622c9 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 00:20:20 -0700 Subject: [PATCH 54/91] Update testCompositionalMultiPhaseMFDPolyhedral.cpp --- ...stCompositionalMultiPhaseMFDPolyhedral.cpp | 454 ++++++++++-------- 1 file changed, 248 insertions(+), 206 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index a2682e243aa..c1948ac543c 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -333,226 +333,268 @@ static inline std::vector< real64 > arrayView2dToVector( View2D & arr, localInde } // TPFA test: check linear pressure profile on regular polyhedral mesh -class CompositionalTPFAIntegrationTest : public ::testing::Test +class CompositionalTPFAIntegrationTest : public ::testing::TestWithParam< const char * > { -public: - CompositionalTPFAIntegrationTest() - : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} - -protected: - void SetUp() override + public: + CompositionalTPFAIntegrationTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + + protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + std::string meshFile = testBinaryDir + std::string("/") + GetParam(); + std::string xmlInput = generateXmlInputCompTPFA( meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; + }; + +INSTANTIATE_TEST_SUITE_P( + MeshFiles, + CompositionalTPFAIntegrationTest, + ::testing::Values( + "polyhedral_voronoi_regular.vtu", + "polyhedral_voronoi_complex.vtu", + "polyhedral_voronoi_lattice.vtu" + ) +); + +TEST_P( CompositionalTPFAIntegrationTest, PressureFieldL2Error ) +{ + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + // Expect exact solution only on the k-orthogonal regular mesh + std::string meshFile = GetParam(); + if( meshFile == std::string("polyhedral_voronoi_regular.vtu") ) { - testBinaryDir = TEST_BINARY_DIR; - std::string meshFile = testBinaryDir + "/polyhedral_voronoi_regular.vtu"; - std::string xmlInput = generateXmlInputCompTPFA( meshFile ); - setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); } - - GeosxState state; - std::string testBinaryDir; -}; - -TEST_F( CompositionalTPFAIntegrationTest, PressureFieldL2Error ) -{ - ProblemManager & problemManager = state.getProblemManager(); - DomainPartition & domain = problemManager.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseFVM & >( - problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); - - // One implicit step with dt = 0.01 - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + else { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; - } ); - - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; - - EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); + EXPECT_GT( l2Error, PRESSURE_L2_TOLERANCE ); + } } -// MFD-TPFA test: check linear pressure profile on regular polyhedral mesh -class CompositionalMFDTPFAIntegrationTest : public ::testing::Test +// MFD-TPFA test: check linear pressure profile on polyhedral meshes +class CompositionalMFDTPFAIntegrationTest : public ::testing::TestWithParam< const char * > { -public: - CompositionalMFDTPFAIntegrationTest() - : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} - -protected: - void SetUp() override - { - testBinaryDir = TEST_BINARY_DIR; - std::string meshFile = testBinaryDir + "/polyhedral_voronoi_regular.vtu"; - std::string xmlInput = generateXmlInputCompMFD( INNER_TPFA, meshFile ); - setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); - } - - GeosxState state; - std::string testBinaryDir; -}; - -TEST_F( CompositionalMFDTPFAIntegrationTest, PressureFieldL2Error ) + public: + CompositionalMFDTPFAIntegrationTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + + protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + std::string meshFile = testBinaryDir + std::string("/") + GetParam(); + std::string xmlInput = generateXmlInputCompMFD( INNER_TPFA, meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; + }; + +INSTANTIATE_TEST_SUITE_P( + MeshFiles, + CompositionalMFDTPFAIntegrationTest, + ::testing::Values( + "polyhedral_voronoi_regular.vtu", + "polyhedral_voronoi_complex.vtu", + "polyhedral_voronoi_lattice.vtu" + ) +); + +TEST_P( CompositionalMFDTPFAIntegrationTest, PressureFieldL2Error ) { - ProblemManager & problemManager = state.getProblemManager(); - DomainPartition & domain = problemManager.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseHybridFVM & >( - problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); - - // One implicit step with dt = 0.01 - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) - { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; - } ); - - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; - + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + // MFD(TPFA) is expected to be exact on these meshes EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); } // Cross-check: TPFA vs MFD(TPFA): pressure and saturation profiles must match exactly -TEST( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) +class CompositionalTPFAvsMFDTPFA : public ::testing::TestWithParam< const char * > {}; + +INSTANTIATE_TEST_SUITE_P( + MeshFiles, + CompositionalTPFAvsMFDTPFA, + ::testing::Values( + "polyhedral_voronoi_regular.vtu", + "polyhedral_voronoi_complex.vtu", + "polyhedral_voronoi_lattice.vtu" + ) +); + +TEST_P( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) { std::string const testBinaryDir = TEST_BINARY_DIR; - std::string const meshFile = testBinaryDir + "/polyhedral_voronoi_regular.vtu"; - - std::vector< real64 > p_tpfa, p_mfd; - std::vector< real64 > sat_tpfa, sat_mfd; // phase volume fractions flattened [cell,phase] - localIndex n_cells_tpfa = 0, n_cells_mfd = 0; - localIndex n_phases_tpfa = 2, n_phases_mfd = 2; // From XML phaseNames - - // --- Run TPFA solver --- - { - GeosxState tpfaState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); - std::string xml = generateXmlInputCompTPFA( meshFile ); - setupProblemFromXML( tpfaState.getProblemManager(), xml.c_str() ); - - ProblemManager & pm = tpfaState.getProblemManager(); - DomainPartition & domain = pm.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseFVM & >( - pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); - - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); - n_cells_tpfa = subRegion.size(); - p_tpfa = arrayViewToVector( p_h, n_cells_tpfa ); - - auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); - sat_tpfa = arrayView2dToVector( sat, n_cells_tpfa, n_phases_tpfa ); - } - - // --- Run MFD solver (innerProductType = TPFA) --- - { - GeosxState mfdState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); - std::string xml = generateXmlInputCompMFD( INNER_TPFA, meshFile ); - setupProblemFromXML( mfdState.getProblemManager(), xml.c_str() ); - - ProblemManager & pm = mfdState.getProblemManager(); - DomainPartition & domain = pm.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseHybridFVM & >( - pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); - - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); - n_cells_mfd = subRegion.size(); - p_mfd = arrayViewToVector( p_h, n_cells_mfd ); - - auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); - sat_mfd = arrayView2dToVector( sat, n_cells_mfd, n_phases_mfd ); - } - - ASSERT_EQ( n_cells_tpfa, n_cells_mfd ); - ASSERT_EQ( n_phases_tpfa, n_phases_mfd ); - - // Pressure profile equality - for( localIndex i = 0; i < n_cells_tpfa; ++i ) - { - real64 const diff = std::abs( p_tpfa[i] - p_mfd[i] ); - EXPECT_NEAR( diff, 0.0, PRESSURE_L2_TOLERANCE ); - } - - // Saturation profile (phase volume fraction) equality - size_t const nTot = static_cast< size_t >( n_cells_tpfa ) * static_cast< size_t >( n_phases_tpfa ); - for( size_t k = 0; k < nTot; ++k ) - { - real64 const diff = std::abs( sat_tpfa[k] - sat_mfd[k] ); - EXPECT_NEAR( diff, 0.0, SATURATION_L2_TOLERANCE ); - } -} + std::string const meshFile = testBinaryDir + std::string("/") + GetParam(); + + std::vector< real64 > p_tpfa, p_mfd; + std::vector< real64 > sat_tpfa, sat_mfd; // phase volume fractions flattened [cell,phase] + localIndex n_cells_tpfa = 0, n_cells_mfd = 0; + localIndex n_phases_tpfa = 2, n_phases_mfd = 2; // From XML phaseNames + + // --- Run TPFA solver --- + { + GeosxState tpfaState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); + std::string xml = generateXmlInputCompTPFA( meshFile ); + setupProblemFromXML( tpfaState.getProblemManager(), xml.c_str() ); + + ProblemManager & pm = tpfaState.getProblemManager(); + DomainPartition & domain = pm.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseFVM & >( + pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); + + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); + n_cells_tpfa = subRegion.size(); + p_tpfa = arrayViewToVector( p_h, n_cells_tpfa ); + + auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); + sat_tpfa = arrayView2dToVector( sat, n_cells_tpfa, n_phases_tpfa ); + } + + // --- Run MFD solver (innerProductType = TPFA) --- + { + GeosxState mfdState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); + std::string xml = generateXmlInputCompMFD( INNER_TPFA, meshFile ); + setupProblemFromXML( mfdState.getProblemManager(), xml.c_str() ); + + ProblemManager & pm = mfdState.getProblemManager(); + DomainPartition & domain = pm.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); + n_cells_mfd = subRegion.size(); + p_mfd = arrayViewToVector( p_h, n_cells_mfd ); + + auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); + sat_mfd = arrayView2dToVector( sat, n_cells_mfd, n_phases_mfd ); + } + + ASSERT_EQ( n_cells_tpfa, n_cells_mfd ); + ASSERT_EQ( n_phases_tpfa, n_phases_mfd ); + + // Pressure profile equality + for( localIndex i = 0; i < n_cells_tpfa; ++i ) + { + real64 const diff = std::abs( p_tpfa[i] - p_mfd[i] ); + EXPECT_NEAR( diff, 0.0, PRESSURE_L2_TOLERANCE ); + } + + // Saturation profile (phase volume fraction) equality + size_t const nTot = static_cast< size_t >( n_cells_tpfa ) * static_cast< size_t >( n_phases_tpfa ); + for( size_t k = 0; k < nTot; ++k ) + { + real64 const diff = std::abs( sat_tpfa[k] - sat_mfd[k] ); + EXPECT_NEAR( diff, 0.0, SATURATION_L2_TOLERANCE ); + } + } int main( int argc, char * * argv ) { From cbbc3b81d81c80a2858b65586b72e7a36668176e Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 01:43:24 -0700 Subject: [PATCH 55/91] wip: adding support for QuasiTPFA --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 11 +---------- .../physicsSolvers/fluidFlow/kernelSpecs.json | 4 ---- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 3 ++- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 08b681b26c5..3ad6f55e06c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -145,11 +145,10 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou MimeticInnerProductBase const & mimeticInnerProductBase = hmDiscretization.getReference< MimeticInnerProductBase >( HybridMimeticDiscretization::viewKeyStruct::innerProductString() ); if( dynamicCast< QuasiRTInnerProduct const * >( &mimeticInnerProductBase ) || - dynamicCast< QuasiTPFAInnerProduct const * >( &mimeticInnerProductBase ) || dynamicCast< SimpleInnerProduct const * >( &mimeticInnerProductBase ) ) { GEOS_ERROR( getCatalogName() << " " << getDataContext() << - "The QuasiRT, QuasiTPFA, and Simple inner products are only available in SinglePhaseHybridFVM" ); + "The QuasiRT, and Simple inner products are only available in SinglePhaseHybridFVM" ); } m_lengthTolerance = domain.getMeshBody( 0 ).getGlobalLengthScale() * 1e-8; @@ -937,14 +936,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n { launchForFaces( QuasiTPFAInnerProduct{} ); } - else if( innerProductType == "quasiRT" ) - { - launchForFaces( QuasiRTInnerProduct{} ); - } - else if( innerProductType == "simple" ) - { - launchForFaces( SimpleInnerProduct{} ); - } else if( innerProductType == "beiraoDaVeigaLipnikovManzini" ) { launchForFaces( BdVLMInnerProduct{} ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index 25cd1058ecc..e5fff0d5536 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -145,8 +145,6 @@ "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", "mimeticInnerProduct::QuasiTPFAInnerProduct", - "mimeticInnerProduct::QuasiRTInnerProduct", - "mimeticInnerProduct::SimpleInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, @@ -188,8 +186,6 @@ "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", "mimeticInnerProduct::QuasiTPFAInnerProduct", - "mimeticInnerProduct::QuasiRTInnerProduct", - "mimeticInnerProduct::SimpleInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 3c7cd743371..21b5738e836 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -20,8 +20,9 @@ #include "CompositionalMultiphaseHybridFVMKernels.hpp" #include "finiteVolume/mimeticInnerProducts/MimeticInnerProductBase.hpp" -#include "finiteVolume/mimeticInnerProducts/BdVLMInnerProduct.hpp" #include "finiteVolume/mimeticInnerProducts/TPFAInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/QuasiTPFAInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/BdVLMInnerProduct.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" From 982149d3f58b4f6d32f28d770e01df89583a6e1e Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 11:21:16 -0700 Subject: [PATCH 56/91] Update kernelSpecs.json --- .../physicsSolvers/fluidFlow/kernelSpecs.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index e5fff0d5536..6c3036ca033 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -93,7 +93,14 @@ "NFACES": [ 4, 5, - 6 + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13 ], "NCOMPS": [ 1, From d388d560a2add745e4486f2a484319e266ca3e32 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 12:31:56 -0700 Subject: [PATCH 57/91] Delete CompositionalMultiphaseHybridFVM.cpp.backup --- ...ompositionalMultiphaseHybridFVM.cpp.backup | 380 ------------------ 1 file changed, 380 deletions(-) delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup deleted file mode 100644 index 6aabb50eaed..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp.backup +++ /dev/null @@ -1,380 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file CompositionalMultiphaseHybridFVM.cpp - */ - -#include "CompositionalMultiphaseHybridFVM.hpp" - -#include "mesh/DomainPartition.hpp" -#include "constitutive/ConstitutivePassThru.hpp" -#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" -#include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" -#include "fieldSpecification/AquiferBoundaryCondition.hpp" -#include "fieldSpecification/FieldSpecificationManager.hpp" -#include "finiteVolume/HybridMimeticDiscretization.hpp" -#include "finiteVolume/MimeticInnerProductDispatch.hpp" -#include "finiteVolume/FluxApproximationBase.hpp" -#include "finiteVolume/BoundaryStencil.hpp" -#include "mesh/mpiCommunications/CommunicationTools.hpp" -#include "physicsSolvers/LogLevelsInfo.hpp" -#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" -#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/SolutionScalingKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/SolutionCheckKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/ResidualNormKernel.hpp" -#include "mesh/CellElementSubRegion.hpp" - -/** - * @namespace the geos namespace that encapsulates the majority of the code - */ -namespace geos -{ - -using namespace dataRepository; -using namespace constitutive; -using namespace fields; -using namespace isothermalCompositionalMultiphaseBaseKernels; -using namespace compositionalMultiphaseHybridFVMKernels; -using namespace mimeticInnerProduct; - -CompositionalMultiphaseHybridFVM::CompositionalMultiphaseHybridFVM( const std::string & name, - Group * const parent ): - CompositionalMultiphaseBase( name, parent ), - m_lengthTolerance( 0 ) -{ - m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::compositionalMultiphaseHybridFVM; -} - -void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) -{ - // 1) Register the elem-centered data - CompositionalMultiphaseBase::registerDataOnMesh( meshBodies ); - - // 2) Register the face data - meshBodies.forSubGroups< MeshBody >( [&]( MeshBody & meshBody ) - { - MeshLevel & meshLevel = meshBody.getBaseDiscretization(); - - FaceManager & faceManager = meshLevel.getFaceManager(); - - // primary variables: face pressure changes - faceManager.registerField< flow::facePressure_n >( getName() ); - - // Register the bc face data - faceManager.registerField< flow::bcPressure >( getName() ); - - // auxiliary data for the buoyancy coefficient - faceManager.registerField< flow::mimGravityCoefficient >( getName() ); - } ); -} - -void CompositionalMultiphaseHybridFVM::initializePreSubGroups() -{ - CompositionalMultiphaseBase::initializePreSubGroups(); - - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - - GEOS_THROW_IF( !fvManager.hasGroup< HybridMimeticDiscretization >( m_discretizationName ), - getCatalogName() << " " << getDataContext() << - ": the HybridMimeticDiscretization must be selected with CompositionalMultiphaseHybridFVM", - InputError ); - - GEOS_THROW_IF( m_hasCapPressure, - getCatalogName() << " " << getDataContext() << - ": capillary pressure is not yet supported by CompositionalMultiphaseHybridFVM", - InputError ); - - HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); - MimeticInnerProductBase const & mimeticInnerProductBase = - hmDiscretization.getReference< MimeticInnerProductBase >( HybridMimeticDiscretization::viewKeyStruct::innerProductString() ); - if( dynamicCast< QuasiRTInnerProduct const * >( &mimeticInnerProductBase ) || - dynamicCast< QuasiTPFAInnerProduct const * >( &mimeticInnerProductBase ) || - dynamicCast< SimpleInnerProduct const * >( &mimeticInnerProductBase ) ) - { - GEOS_ERROR( getCatalogName() << " " << getDataContext() << - "The QuasiRT, QuasiTPFA, and Simple inner products are only available in SinglePhaseHybridFVM" ); - } - - m_lengthTolerance = domain.getMeshBody( 0 ).getGlobalLengthScale() * 1e-8; -} - -void CompositionalMultiphaseHybridFVM::applyBoundaryConditions( real64 const time_n, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - - // Apply face-based Dirichlet boundary conditions - if( m_keepFlowVariablesConstantDuringInitStep ) - { - applyFaceDirichletBC( time_n, dt, dofManager, domain, localMatrix, localRhs ); - } -} - -void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - - using namespace compositionalMultiphaseHybridFVMKernels; - using namespace mimeticInnerProduct; - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - // Get the inner product type from the discretization - NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - HybridMimeticDiscretization const & hmDiscretization = fvManager.getHybridMimeticDiscretization( m_discretizationName ); - string const & innerProductType = hmDiscretization.getReference< string >( HybridMimeticDiscretization::viewKeyStruct::innerProductTypeString() ); - - string const elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - globalIndex const rankOffset = dofManager.rankOffset(); - - // Log message for Dirichlet BC application - static char const faceBcLogMessage[] = - "CompositionalMultiphaseHybridFVM {}: at time {}s, " - "the <{}> boundary condition '{}' is applied to the face set '{}' in '{}'. " - "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " - "\nThe total number of target faces (including ghost faces) is {}." - "\nNote that if this number is equal to zero, the boundary condition will not be applied on this face set."; - - // Apply Dirichlet BC by computing boundary fluxes - this->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - FaceManager & faceManager = mesh.getFaceManager(); - NodeManager const & nodeManager = mesh.getNodeManager(); - ElementRegionManager & elemManager = mesh.getElemManager(); - - // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) - arrayView1d< real64 const > const presFace = - faceManager.getField< flow::facePressure >(); - arrayView1d< real64 const > const presFaceBC = - faceManager.getField< flow::bcPressure >(); - string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); - arrayView1d< globalIndex const > const faceDofNumber = - faceManager.getReference< array1d< globalIndex > >( faceDofKey ); - arrayView1d< integer const > const faceGhostRank = faceManager.ghostRank(); - - globalIndex const rankOffset = dofManager.rankOffset(); - - fsManager.apply< FaceManager >( time_n + dt, - mesh, - flow::bcPressure::key(), - [&] ( FieldSpecificationBase const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - FaceManager & targetGroup, - string const & ) - { - // Using the field specification functions to apply the boundary conditions to the system - fs.applyFieldValue< FieldSpecificationEqual, - parallelDevicePolicy<> >( targetSet, - time_n + dt, - targetGroup, - flow::bcPressure::key() ); - - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - - localIndex const kf = targetSet[a]; - if( faceGhostRank[kf] >= 0 ) - { - return; - } - - // Get the dof number of this face - globalIndex const dofIndex = faceDofNumber[kf]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // Apply field value to the lhs and rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - presFaceBC[kf], - presFace[kf] ); - localRhs[localRow] = rhsValue; - } ); - - } ); - - // Get node positions - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const nodePosition = nodeManager.referencePosition(); - - // Get face data - ArrayOfArraysView< localIndex const > const faceToNodes = faceManager.nodeList().toViewConst(); - arrayView2d< localIndex const > const elemRegionList = faceManager.elementRegionList(); - arrayView2d< localIndex const > const elemSubRegionList = faceManager.elementSubRegionList(); - arrayView2d< localIndex const > const elemList = faceManager.elementList(); - - arrayView1d< real64 const > const transMultiplier = faceManager.getReference< array1d< real64 > >( fields::flow::transMultiplier::key() ); - - // Apply boundary values to face fields first - applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, - flow::pressure::key(), flow::facePressure::key() ); - - applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, - flow::globalCompFraction::key(), flow::faceGlobalCompFraction::key() ); - - applyFieldValue< FaceManager >( time_n, dt, mesh, faceBcLogMessage, - flow::temperature::key(), flow::faceTemperature::key() ); - - // Get face boundary values - arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); - arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); - arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); - arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); - - // Loop over regions and apply Dirichlet flux kernel - elemManager.forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const er, - CellElementSubRegion & subRegion ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - - string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityModel = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - - real64 const lengthTolerance = m_lengthTolerance; - - // Get all face sets that have Dirichlet BCs - std::set< string > bcFaceSets; - fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) - { - if( fs.getCatalogName() == catalogName() ) - { - string const & fieldName = fs.getFieldName(); - if( fieldName == flow::pressure::key() || - fieldName == flow::globalCompFraction::key() || - fieldName == flow::temperature::key() ) - { - for( string const & setName : fs.getSetNames() ) - { - bcFaceSets.insert( setName ); - } - } - } - } ); - - // Apply Dirichlet flux kernel for each face set - for( string const & setName : bcFaceSets ) - { - SortedArrayView< localIndex const > targetSet = faceManager.getSet( setName ).toViewConst(); - if( targetSet.size() == 0 ) - continue; - - // Launch the Dirichlet flux kernel - constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) - { - integer constexpr NUM_COMP = NC(); - - typename DirichletFluxKernel::CompFlowAccessors compFlowAccessors( elemManager, getName() ); - typename DirichletFluxKernel::MultiFluidAccessors multiFluidAccessors( elemManager, getName() ); - ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > elemDofNumberAccessor = - elemManager.constructArrayViewAccessor< globalIndex, 1 >( elemDofKey ); - - // Determine number of faces per element from subregion type - localIndex const numFacesPerElement = subRegion.numFacesPerElement(); - - // Dispatch based on number of phases (runtime -> compile-time) - auto launchWithPhases = [&]( auto NP_VALUE ) - { - integer constexpr NP = decltype( NP_VALUE )::value; - - auto launchKernel = [&]( auto IP_TYPE_WRAPPER, auto NF_VALUE ) - { - using IP_TYPE = decltype( IP_TYPE_WRAPPER ); - integer constexpr NF = decltype( NF_VALUE )::value; - - DirichletFluxKernel::launch< NF, NUM_COMP, NP, IP_TYPE > - ( m_numPhases, - er, - subRegion.getIndexInParent(), - subRegion, - permeabilityModel, - faceManager, - targetSet, - facePres, - faceTemp, - faceCompFrac, - nodePosition, - faceToNodes, - elemRegionList, - elemSubRegionList, - elemList, - faceDofNumber, - faceGravCoef, - transMultiplier, - lengthTolerance, - dt, - rankOffset, - m_useTotalMassEquation, - compFlowAccessors, - multiFluidAccessors, - elemDofNumberAccessor.toNestedViewConst(), - localMatrix, - localRhs ); - }; - - // Dispatch based on inner product type and number of faces - if( innerProductType == "TPFA" ) - { - if( numFacesPerElement == 4 ) - launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 4 >{} ); - else if( numFacesPerElement == 5 ) - launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 5 >{} ); - else if( numFacesPerElement == 6 ) - launchKernel( TPFAInnerProduct{}, std::integral_constant< integer, 6 >{} ); - } - else if( innerProductType == "BDVLM" || innerProductType == "BdVLM" ) - { - if( numFacesPerElement == 4 ) - launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 4 >{} ); - else if( numFacesPerElement == 5 ) - launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 5 >{} ); - else if( numFacesPerElement == 6 ) - launchKernel( BdVLMInnerProduct{}, std::integral_constant< integer, 6 >{} ); - } - }; - - // Dispatch number of phases - if( m_numPhases == 2 ) - launchWithPhases( std::integral_constant< integer, 2 >{} ); - else if( m_numPhases == 3 ) - launchWithPhases( std::integral_constant< integer, 3 >{} ); - else - GEOS_ERROR( "Unsupported number of phases: " << m_numPhases ); - } ); - } - } ); - } ); -} - -} // namespace geos From 4ffad8125cecc7fcbf754cb9ad52bd9953568b81 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 14:55:37 -0700 Subject: [PATCH 58/91] wip: apply code review and make code CI compliant --- .../CompositionalMultiphaseHybridFVM.cpp | 55 +------------------ ...haseHybridFVMKernels_assembly.cpp.template | 4 +- ...aseHybridFVMKernels_dirichlet.cpp.template | 2 - .../physicsSolvers/fluidFlow/kernelSpecs.json | 2 - ...ompositionalMultiphaseHybridFVMKernels.hpp | 49 +++++++++++------ ...itionalMultiphaseHybridFVMKernels_impl.hpp | 16 ++---- 6 files changed, 42 insertions(+), 86 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 3ad6f55e06c..9ec224a97d0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -328,10 +328,6 @@ void CompositionalMultiphaseHybridFVM::setupDofs( DomainPartition const & GEOS_U viewKeyStruct::elemDofFieldString(), DofManager::Connector::Face ); - // this call with instruct GEOS to reorder the dof numbers - //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), - // DofManager::LocalReorderingType::ReverseCutHillMcKee ); - // for the volume balance equation, disable global coupling // this equation is purely local (not coupled to neighbors or other physics) dofManager.disableGlobalCouplingForEquation( viewKeyStruct::elemDofFieldString(), @@ -376,12 +372,8 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, NodeManager const & nodeManager = mesh.getNodeManager(); FaceManager const & faceManager = mesh.getFaceManager(); - - // node data (for transmissibility computation) - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition = nodeManager.referencePosition(); - // face data // get the face-based DOF numbers for the assembly string const faceDofKey = dofManager.getKey( viewKeyStruct::faceDofFieldString() ); @@ -393,21 +385,6 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, arrayView1d< integer const > const isBoundaryFaceView = faceManager.getField< flow::isBoundaryFace >(); -// // Print isBoundaryFaceView for debugging -// std::cout << "=== isBoundaryFaceView Debug Info ===" << std::endl; -// std::cout << "Total number of faces: " << faceManager.size() << std::endl; -// integer numBoundaryFaces = 0; -// for( localIndex iface = 0; iface < faceManager.size(); ++iface ) -// { -// if( isBoundaryFaceView[iface] == 1 ) -// { -// std::cout << "Face " << iface << " is a boundary face" << std::endl; -// numBoundaryFaces++; -// } -// } -// std::cout << "Total boundary faces: " << numBoundaryFaces << std::endl; -// std::cout << "=====================================" << std::endl; - // get the element dof numbers for the assembly string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > elemDofNumber = @@ -673,7 +650,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n string const & innerProductType = hmDiscretization.getReference< string >( HybridMimeticDiscretization::viewKeyStruct::innerProductTypeString() ); string const elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - globalIndex const rankOffset = dofManager.rankOffset(); // Log message for Dirichlet BC application static char const faceBcLogMessage[] = @@ -774,6 +750,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Call evaluateBCFaceProperties to compute face properties at BC conditions constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) { + GEOS_UNUSED_VAR(fluidWrapper); integer constexpr NUM_COMP = NC(); auto evaluateWithPhases = [&]( auto NP_VALUE ) @@ -808,28 +785,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } } ); } - - // Get element-based fields for flux computation - arrayView1d< real64 const > const elemPres = subRegion.getField< flow::pressure >(); - arrayView2d< real64 const, compflow::USD_COMP > const elemCompDens = subRegion.getField< flow::globalCompDensity >(); - arrayView1d< real64 const > const elemGravCoef = subRegion.getField< flow::gravityCoefficient >(); - arrayView2d< localIndex const > const elemToFaces = subRegion.faceList(); - - // Get fluid properties at element centers - arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const elemPhaseDens = - fluid.phaseDensity(); - arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const elemPhaseMassDens = - fluid.phaseMassDensity(); - arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > const elemPhaseCompFrac = - fluid.phaseCompFraction(); - - // Get mobility from flow solver - arrayView2d< real64 const, compflow::USD_PHASE > const elemPhaseMob = - subRegion.getField< flow::phaseMobility >(); - - // Get DOF numbers - arrayView1d< globalIndex const > const elemDofNumber = - subRegion.getReference< array1d< globalIndex > >( elemDofKey ); // Get pre-computed fluid properties at BC faces arrayView2d< real64 const, compflow::USD_PHASE > const facePhaseMobField = @@ -849,6 +804,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Launch the Dirichlet flux kernel with compile-time dispatch constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) { + GEOS_UNUSED_VAR(fluidWrapper); integer constexpr NUM_COMP = NC(); typename DirichletFluxKernel::CompFlowAccessors compFlowAccessors( elemManager, getName() ); @@ -873,11 +829,9 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n subRegion.getIndexInParent(), subRegion, permeabilityModel, - faceManager, targetSet, facePres, faceTemp, - faceCompFrac, facePhaseMobField, facePhaseMassDensField, facePhaseCompFracField, @@ -932,10 +886,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n { launchForFaces( TPFAInnerProduct{} ); } - else if( innerProductType == "quasiTPFA" ) - { - launchForFaces( QuasiTPFAInnerProduct{} ); - } else if( innerProductType == "beiraoDaVeigaLipnikovManzini" ) { launchForFaces( BdVLMInnerProduct{} ); @@ -971,6 +921,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FaceManager & targetGroup, string const & ) { + GEOS_UNUSED_VAR(setName); // Using the field specification functions to apply the boundary conditions to the system fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template index 60644fe8958..6386db8345b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template @@ -82,13 +82,11 @@ namespace compositionalMultiphaseHybridFVMKernels globalIndex const elemDofNumber, globalIndex const neighborDofNumber, globalIndex const upwViscDofNumber, - globalIndex const faceDofNumber, real64 const & dt, real64 ( &divMassFluxes )[ NC ], real64 ( &dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ], real64 ( &dDivMassFluxes_dFaceVars )[ NC ][ NF ], - globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ], - globalIndex ( &dofColIndicesFaceVars )[ NF ] ); + globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ] ); @EXTERN@ template GEOS_HOST_DEVICE diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template index 494fadcc796..40be0e67241 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template @@ -34,11 +34,9 @@ namespace compositionalMultiphaseHybridFVMKernels localIndex const esr, CellElementSubRegion const & subRegion, constitutive::PermeabilityBase const & permeabilityModel, - FaceManager const & faceManager, SortedArrayView< localIndex const > const & boundaryFaceSet, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index 6c3036ca033..65a8f1ce8f1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -151,7 +151,6 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", - "mimeticInnerProduct::QuasiTPFAInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, @@ -192,7 +191,6 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", - "mimeticInnerProduct::QuasiTPFAInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 74e4edfed86..c97e4e0b864 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -367,13 +367,11 @@ struct AssemblerKernelHelper * @param[in] dUpwPhaseViscCoef_dPres the derivative of the upwinded viscous transport coefficient wrt pressure * @param[in] dUpwPhaseViscCoef_dCompDens the derivative of the upwinded viscous transport coefficient wrt component density * @param[in] upwViscDofNumber degree of freedom number of the upwind element - * @param[in] faceDofNumber degree of freedom number of the face * @param[in] dt the time step * @param[inout] divMassFluxes the divergence of the fluxes in the element * @param[inout] dDivMassFluxes_dElemVars the derivatives of the flux divergence wrt the element centered vars (pres and comp dens) * @param[inout] dDivMassFluxes_dFaceVars the derivatives of the flux divergence wrt the face centered vars * @param[inout] dofColIndicesElemVars degrees of freedom of the cells involved in the flux divergence - * @param[inout] dofColIndicesFaceVars degrees of freedom of the faces involved in the flux divergence */ template< integer NF, integer NC, integer NP > GEOS_HOST_DEVICE @@ -389,13 +387,11 @@ struct AssemblerKernelHelper globalIndex const elemDofNumber, globalIndex const neighborDofNumber, globalIndex const upwViscDofNumber, - globalIndex const faceDofNumber, real64 const & dt, real64 ( &divMassFluxes )[ NC ], real64 ( &dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ], real64 ( &dDivMassFluxes_dFaceVars )[ NC ][ NF ], - globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ], - globalIndex ( &dofColIndicesFaceVars )[ NF ] ); + globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ]); /** * @brief In a given element, compute the buoyancy flux divergence, i.e, sum the buoyancy fluxes at this element's faces @@ -587,11 +583,9 @@ struct DirichletFluxKernel * @param[in] esr index of this element's subregion * @param[in] subRegion the subRegion * @param[in] permeabilityModel the permeability model - * @param[in] faceManager the face manager * @param[in] boundaryFaceSet set of faces on the Dirichlet boundary * @param[in] facePres prescribed face pressures * @param[in] faceTemp prescribed face temperatures - * @param[in] faceCompFrac prescribed face component fractions * @param[in] facePhaseMob prescribed face phase mobilities * @param[in] facePhaseMassDens prescribed face phase mass densities * @param[in] facePhaseCompFrac prescribed face phase component fractions @@ -619,11 +613,9 @@ struct DirichletFluxKernel localIndex const esr, CellElementSubRegion const & subRegion, constitutive::PermeabilityBase const & permeabilityModel, - FaceManager const & faceManager, SortedArrayView< localIndex const > const & boundaryFaceSet, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, @@ -1241,13 +1233,38 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) switch( value ) { - case 4: - { lambda( std::integral_constant< T, 4 >() ); return;} - case 5: - { lambda( std::integral_constant< T, 5 >() ); return;} - case 6: - { lambda( std::integral_constant< T, 6 >() ); return;} - default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); + case 4: { + return lambda( std::integral_constant{} ); + } + case 5: { + return lambda( std::integral_constant{} ); + } + case 6: { + return lambda( std::integral_constant{} ); + } + case 7: { + return lambda( std::integral_constant{} ); + } + case 8: { + return lambda( std::integral_constant{} ); + } + case 9: { + return lambda( std::integral_constant{} ); + } + case 10: { + return lambda( std::integral_constant{} ); + } + case 11: { + return lambda( std::integral_constant{} ); + } + case 12: { + return lambda( std::integral_constant{} ); + } + case 13: { + return lambda( std::integral_constant{} ); + } + default: + GEOS_ERROR( "Unknown numFacesInElem value: " << value ); } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 21b5738e836..6390af0cd6f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -728,13 +728,11 @@ AssemblerKernelHelper:: elemDofNumber[localIds[0]][localIds[1]][localIds[2]], neighborDofNumber, upwViscDofNumber, - faceDofNumber[elemToFaces[ifaceLoc]], dt, divMassFluxes, dDivMassFluxes_dElemVars, dDivMassFluxes_dFaceVars, - dofColIndicesElemVars, - dofColIndicesFaceVars ); + dofColIndicesElemVars ); faceIndexMap[ifaceLoc] = numNonBoundaryFaces; @@ -881,13 +879,11 @@ AssemblerKernelHelper:: globalIndex const elemDofNumber, globalIndex const neighborDofNumber, globalIndex const upwViscDofNumber, - globalIndex const faceDofNumber, real64 const & dt, real64 ( & divMassFluxes )[ NC ], real64 ( & dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ], real64 ( & dDivMassFluxes_dFaceVars )[ NC ][ NF ], - globalIndex ( & dofColIndicesElemVars )[ (NC+1)*(NF+1) ], - globalIndex ( & dofColIndicesFaceVars )[ NF ] ) + globalIndex ( & dofColIndicesElemVars )[ (NC+1)*(NF+1) ]) { integer constexpr NDOF = NC+1; localIndex const elemVarsOffset = NDOF*(ifaceLoc+1); @@ -944,8 +940,6 @@ AssemblerKernelHelper:: { dofColIndicesElemVars[elemVarsOffset+idof] = neighborDofNumber + idof; } - // Note: dofColIndicesFaceVars[ifaceLoc] is now set in assembleFluxDivergence - // after checking if the face is a boundary face } template< integer NF, integer NC, integer NP > @@ -1373,11 +1367,9 @@ DirichletFluxKernel:: localIndex const esr, CellElementSubRegion const & subRegion, constitutive::PermeabilityBase const & permeabilityModel, - FaceManager const & faceManager, SortedArrayView< localIndex const > const & boundaryFaceSet, arrayView1d< real64 const > const & facePres, arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, @@ -1399,6 +1391,7 @@ DirichletFluxKernel:: CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { + GEOS_UNUSED_VAR(faceTemp); using Deriv = multifluid::DerivativeOffset; // Get element data @@ -1720,7 +1713,8 @@ evaluateBCFaceProperties( integer const numPhases, { using RelPermType = TYPEOFREF( castedRelperm ); typename RelPermType::KernelWrapper relPermWrapper = castedRelperm.createKernelWrapper(); - + GEOS_UNUSED_VAR(relPermWrapper); + // Loop over BC faces and evaluate properties at BC conditions forAll< serialPolicy >( boundaryFaceSet.size(), [=, &facePhaseMob, &facePhaseMassDens, &facePhaseCompFrac] ( localIndex const iset ) { From 9e397a1655cf09a0ceaab1dc5092bacee5de821a Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 17:01:53 -0700 Subject: [PATCH 59/91] fix: code style and reduce number of kernel combinations --- .../MimeticInnerProductDispatch.hpp | 12 +- .../fluidFlowTests/CMakeLists.txt | 6 + .../hex_pyr_tet_nested_mixed.vtu | 38 ++ ...stCompositionalMultiPhaseMFDPolyhedral.cpp | 535 +++++++++++------- .../CompositionalMultiphaseHybridFVM.cpp | 159 +++--- .../physicsSolvers/fluidFlow/kernelSpecs.json | 23 +- ...ompositionalMultiphaseHybridFVMKernels.hpp | 38 +- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 170 +++--- 8 files changed, 542 insertions(+), 439 deletions(-) create mode 100644 src/coreComponents/integrationTests/fluidFlowTests/hex_pyr_tet_nested_mixed.vtu diff --git a/src/coreComponents/finiteVolume/MimeticInnerProductDispatch.hpp b/src/coreComponents/finiteVolume/MimeticInnerProductDispatch.hpp index d9362edd0a3..a418182b715 100644 --- a/src/coreComponents/finiteVolume/MimeticInnerProductDispatch.hpp +++ b/src/coreComponents/finiteVolume/MimeticInnerProductDispatch.hpp @@ -142,10 +142,14 @@ mimeticInnerProductReducedDispatch( MimeticInnerProductBase const & input, { lambda( *ptr1 ); } - else if( auto const * const ptr2 = dynamic_cast< BdVLMInnerProduct const * >(&input) ) + else if( auto const * const ptr2 = dynamic_cast< QuasiTPFAInnerProduct const * >(&input) ) { lambda( *ptr2 ); } + else if( auto const * const ptr3 = dynamic_cast< BdVLMInnerProduct const * >(&input) ) + { + lambda( *ptr3 ); + } else { GEOS_ERROR( "mimeticInnerProductReducedDispatch() is not implemented for input of " << LvArray::system::demangleType( input ) ); @@ -169,10 +173,14 @@ mimeticInnerProductReducedDispatch( MimeticInnerProductBase & input, { lambda( *ptr1 ); } - else if( auto * const ptr2 = dynamic_cast< BdVLMInnerProduct * >(&input) ) + else if( auto * const ptr2 = dynamic_cast< QuasiTPFAInnerProduct * >(&input) ) { lambda( *ptr2 ); } + else if( auto * const ptr3 = dynamic_cast< BdVLMInnerProduct * >(&input) ) + { + lambda( *ptr3 ); + } else { GEOS_ERROR( "mimeticInnerProductReducedDispatch() is not supported for input of " << LvArray::system::demangleType( input ) ); diff --git a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt index eede401fa14..32063b4ff7b 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt @@ -57,6 +57,12 @@ foreach(test ${gtest_geosx_tests}) ${CMAKE_CURRENT_SOURCE_DIR}/polyhedral_voronoi_complex.vtu $ ) + add_custom_command( + TARGET ${test_name} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/hex_pyr_tet_nested_mixed.vtu + $ + ) endforeach() diff --git a/src/coreComponents/integrationTests/fluidFlowTests/hex_pyr_tet_nested_mixed.vtu b/src/coreComponents/integrationTests/fluidFlowTests/hex_pyr_tet_nested_mixed.vtu new file mode 100644 index 00000000000..246b49aae24 --- /dev/null +++ b/src/coreComponents/integrationTests/fluidFlowTests/hex_pyr_tet_nested_mixed.vtu @@ -0,0 +1,38 @@ + + + + + + + + + AQAAAACAAAAkBAAAKgAAAA==eJxjZGBgYBwgzEQlTG3zaGHmQIUNsX5hxoIHKsxH0w/lYUNNDACQdQG2 + + + + + AQAAAACAAABYCwAA6wEAAA==eJxtlY1xQyEMg7NGd+gMz0yTObRGO0CnSXZqKafnz+DccSjBCP/IzuPBjy6j9+t14++vj0ibASxg3p/7wotn4cVjmwGs6N/WZTx348mTNgNY0futy3ieG889bQawoo95+jhuHuNlOyJtb/vo8/WfH/AIPAKPwNPlWkeeGCv95ZtnnXJlvczjswGseLQ1zvtZr8WTNgNY0esj3856rd/SZgArem2l31kvc4/I89s+el1mzFmv20fwCDydpjNf1DW1WfVFjbDOOnLMPDFW+nv2UnJwuV7mgX3Qd9aVd4xdL/PAPvoe1vbeiIxrRMZ120ff/9p8FXgEHoGnmx3a4qwzg33P3j3njkqOdi1Tj9TUObN01Ic5Zp4Y6znvdNzbl+tlnn5WaqvrOO67XhlXN2e1aULH264X8tPMaG16oq+24ZzmrOW8VNHiOW84M9j3+3+Dmh6q+aq6pjapLzW1rbmu+WbOGLeaN2ud6hKw52GdlexD1rjeF7A/nI8qPUx91Lf5f+h61RnN/qe2qt+c05y1auZc1WWNmfODM0BN/1VN13xR19SmGl3Ufqi5Zr6ZMzX+1l6qHLmez5/L64/w/v5+fbZnczeeNt2d+Zvx3Dsu8vEez82/v8cz8+9+8A594ZvkIh/v8ZzrFw53A8o= + + + 0 + + + 1.7320508076 + + + + + + + AQAAAACAAAAQMgAAagcAAA==eJyFl1d3kEUURbH33iv2CqiASlAh9i5JlARNghCwd0nQQDQJSrF3KRpASVDA3rvYe+9dUcRe/oEP3v2y17prfDnL5Jw9cyczfPf26vX/f8uFrhK6cugOoTuG7h66m3LLh64qDrmdQvuIQ26F0NXEIbdzaF9xyK0Yuro45HYJ7ScOuZVC1xCH3K6he4jDOVHvWqFrhnJO1LtX6J7KUe/a4pCj3v7ikKPedcQhR70DxCFHveuKQ456B4pDjnNbTxxynNve4nBO1LtB6PqhnBP17hu6j3LUu6E45Kh3kDjkqHcjcchRb4U45Kh3Y3HIUe9gcchxbpuIQ45z208czol6NwvdNJRzot4DQvdXjno3F4cc9Q4Rhxz1biEOOeodKg456t1SHHLUWykOOc5tK3HIcW4HisM5UW/v0K1DOSfqPTj0IOWodxtxyFHvIeKQo95txSFHvYeKQ456txOHXGXoYeKQ49y2F4cc53a4OKXvwxGhR4YOCz1Ouez7QO6o0CpxSt8HckeHVotT+j6QOya0RpzS94HcsaHHi1P6PnBO1Ds89ATlsu/D50m+NrRKPv97iW+4fKwLF06fxAcXzjD5yMFh3f6JL/uefZFw6kKr5fO/7/hq5fP+4PRNfD6/KvnIwWHdAYkv+/5+mXBGhNbI5+8Rvjr5vD84/RKfz69aPnJwWHdg4sv6BfK8oxPFK/ULvBvuYX3oScpl/cJXSb4htFY+fz/x1cvn9+H7bx9cOMPl8/1j3UGJL+tvvpb6PTXo9/y8MVm3Ivk9ee/b78I+n2utfL6XrFuR+LI+7ZuEMzJ0hHzuW/A1yuf9+V3Y5/Ork8/vmnUHJ76sryTP+zpZvFJfyXvifo4OHaVc1ld+m+SbQhvkc5+Fb7R8fje+n/bBhVMvn+8f6w5JfFkf/F3CGRPaKJ/7QnxN8nl/vv/2+fwa5PP9Y92hiS/r279POGNDR8rnPhbfGPm8P99/+3x+jfL5/bJuZeLL5gzyvKNTxCvNGaNCuYenhZ6qXDZn+P2cLk5pzvB9PEOc0pzhv++Z4pDL5gxynNtZ4pTmjLNDzwkdF3qhctmcQe7c0GZxSnMGufNCW8QpzRnkzg8dL05pziB3QehF4pTmDM6JeltDL1bOfTecH5L8hNBm+dwH4WuVj3XhwqlKfHDhjJOPHBzWrU187rvxLUk4E0Nb5ENdb51+X6ffw/O+4bO/JfJ5nWb5yMFhHe/H84HniR8TTlvoePncB+GbKJ/3B6cm8cH1+eMjB4d1RyS+bP4gz/u6RLzS/MF74n62h16qnPt6OD8l+Y7QCfK5D8LXLp/fjd+FfXDhtMqHug7vz/vyup5D/G48Z3QWcp2Fn7OP7B2a7z6c/SxNcpNC2+RzP4OvUz7fc9/jpYkfjvdnHj6/T/bD/pbKl80R5Hknl4lXmiN4F9yzyaGXK+e+Gs7PSX5KaId87qPwTZbP9x9OQ+KDC6ddPr8D1m1KfO6r8S1LOFNDO+Vz34dvinwo6/odLdP/+z357+Pzz/jsZ0zic9+O75eEMy10knzuX/FNlc/787uwz+faKZ/fO+uOTXzZfEGe93WFeKNCs/mC98T9vCr0SuWy+cLv6mpxSvOF7+k14pTmC/99rxWnNF+Q49yuE6c0X1wfekPo9NBblcvmC3I3hs4QpzRfkLspdKY4pfmC3M2hs8QpzRfkbgm9TZzSfME5UW9X6O3Kud+G82uSnx06Qz73Ofi65GNduHCaEx9cONPlIweHdSckPvfV+H5LOHNCZ8rnPgbfbPm8Pzgtic/nN0M+cnBYd2Lic3+O7/eEMzd0lnzuj/DNkc/7gzM+8fn8ZspHDg7rtiW+bI4gzzu6Q7zSHMG74R7OC71TOf5+HeL8keS7Q2fL5z4I3zz5/D58/+2DC6dLPt8/1u2Q70/5+X1n8nt+zt/b/J5Q7gF5c/F1y+d9+11k+/X54/O9ZF3X53fhOeOvhDM/dK587oPw9cjn/cFpS3w+vzny+V2z7qTEl80f5Hlfd4lXmj94T9zPBaF3K9cR6nni7yS/MLRbPvdZ+BbI53fjd2EfXDjz5CMHh3WnJD733fj+STiLQnvkc1+Ib6F83p/vv30+v275fP9Yd2ric/+O79+Ec0/ofPncx+JbJJ/35/tvn8+vRz6/X9adlviyOYM87+he8UpzBu+Ge3h/6H3KZXOG388D4pTmDN/HB8UpzRn++z4kTmnOIMe5PSxOac54JPTR0KdDn1IumzPIPRb6jDilOYPc46HPilOaM8g9EfqcOKU5g9yToc+LU5ozOCfqfSF0sXLuu+GQo94XxXFf7T6cHPW+JI771LnikKPel8Up9ZXkOLdXxCn1lYtDqfe10FeVcz8Fhxz1vi6O+yX3V+So9w1x3H+4XyFHvW+KQy7rF8hxbm+JU+oXOCfqfSf0beX8/YRDjnrfFcffR39PyVHve+L4e+PvEznqfV+c0veBHOf2gTil7wPnRL0fhX6oXPZ9IEe9H4tT+j6Qo95PxCl9H8hR76filL4P5Di3z8T5D0nt7Wg= + + + AQAAAACAAABICAAA2QEAAA==eJwtxVlMDgAAAOBKohjFkBq1YiVMNWcMaci1xdhoNmqGMHOMUQ/uTbaMbGpkq7YcMXK0lc2VB8cYmiHMis1iY2lzMx7+73v5ugcFRDra8U52qsd7qrOd48Ve7tXe4G3e6f0+5HJX+rTr3OCbvuvHfuFWt7vDP/zXIcGBu7mno9zfsY73UKd4lEd7gic7y9me5wXOdb5XeZ03equLvNP7XOwSl7rMFa7ySZ91net91Td8x4/81C1+43du9yd3+rv/ODgkcJh7ONL9HOM4D/Ewp3mCMz3L873EeS7wRm/3Lhf7oI+43Cdc7VM+54uud6Ov+7bv+qGb/dyv3eb3/uxv/u2gLoG6OsK93dcDHOs4JzrJw53qMc7wFGd5pud6oZc6zyu91hu8xYXe4b0udokP+6iPu9I1rvUFX3Gjb/men7jFbf7gL/7p4NDA4Y7yQA92opM90uke50nO9AzPcY4XOdfLvMIFXu/NLvIe73eJS13mCle5xmd83pfd4Gtu8h0/8BM/8yu3ut0d/upf/ufQroHD3ct9He1BTnCSRzjNYz3RUz3ds73Auc73Gm9yoXf7gEt9zNWu9SVfdZPvu9kv/dYf3elfDgkLHOE+jnGCU5zuDE/zf6h1gA4= + + + AQAAAACAAAAJAQAALgAAAA==eJzj4cEL+DAAXIyLC4sgikJMY5D0QAW5IAAqiWQOQilx7kF2DkH3YAEA/7ENdw== + + + + + diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index c1948ac543c..aee44fac1be 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -12,6 +12,7 @@ */ #include +#include #include "integrationTests/fluidFlowTests/testCompFlowUtils.hpp" #include "mainInterface/initialization.hpp" @@ -39,12 +40,15 @@ static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-10; static constexpr real64 TIME_STEP = 1.0e-2; // 0.01 static constexpr auto INNER_TPFA = "TPFA"; +static constexpr auto INNER_quasiTPFA = "quasiTPFA"; +static constexpr auto INNER_BDVLM = "beiraoDaVeigaLipnikovManzini"; // Generate XML for compositional multiphase FV-TPFA (simplified from user-provided template) static std::string generateXmlInputCompTPFA( std::string const & meshFile ) { std::ostringstream oss; - oss << R"xml( + oss << + R"xml( @@ -52,7 +56,7 @@ static std::string generateXmlInputCompTPFA( std::string const & meshFile ) name="FlowSolverTPFA" discretization="TPFA" targetRegions="{ Domain }" - logLevel="1" + logLevel="0" useMass="1" temperature="300"> + file=")xml" << meshFile << + R"xml("/> @@ -178,7 +183,8 @@ static std::string generateXmlInputCompMFD( std::string const & innerProductType std::string const & meshFile ) { std::ostringstream oss; - oss << R"xml( + oss << + R"xml( @@ -186,7 +192,7 @@ static std::string generateXmlInputCompMFD( std::string const & innerProductType name="FlowSolverMFD" discretization="compositionalHybridMimetic" targetRegions="{ Domain }" - logLevel="1" + logLevel="0" useMass="1" temperature="300"> + file=")xml" << meshFile << + R"xml("/> @@ -216,7 +223,8 @@ static std::string generateXmlInputCompMFD( std::string const & innerProductType + << innerProductType << + R"xml("/> @@ -335,77 +343,76 @@ static inline std::vector< real64 > arrayView2dToVector( View2D & arr, localInde // TPFA test: check linear pressure profile on regular polyhedral mesh class CompositionalTPFAIntegrationTest : public ::testing::TestWithParam< const char * > { - public: - CompositionalTPFAIntegrationTest() - : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} - - protected: - void SetUp() override - { - testBinaryDir = TEST_BINARY_DIR; - std::string meshFile = testBinaryDir + std::string("/") + GetParam(); - std::string xmlInput = generateXmlInputCompTPFA( meshFile ); - setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); - } - - GeosxState state; - std::string testBinaryDir; - }; +public: + CompositionalTPFAIntegrationTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + +protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + std::string meshFile = testBinaryDir + std::string( "/" ) + GetParam(); + std::string xmlInput = generateXmlInputCompTPFA( meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; +}; INSTANTIATE_TEST_SUITE_P( MeshFiles, CompositionalTPFAIntegrationTest, ::testing::Values( "polyhedral_voronoi_regular.vtu", - "polyhedral_voronoi_complex.vtu", - "polyhedral_voronoi_lattice.vtu" + "hex_pyr_tet_nested_mixed.vtu" ) -); + ); TEST_P( CompositionalTPFAIntegrationTest, PressureFieldL2Error ) { - ProblemManager & problemManager = state.getProblemManager(); - DomainPartition & domain = problemManager.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseFVM & >( - problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); - - // One implicit step with dt = 0.01 - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) - { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; - } ); - - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; - - // Expect exact solution only on the k-orthogonal regular mesh + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + // Expect exact solution only on the k-orthogonal regular mesh; expect non-zero error on mixed mesh std::string meshFile = GetParam(); - if( meshFile == std::string("polyhedral_voronoi_regular.vtu") ) + if( meshFile == std::string( "polyhedral_voronoi_regular.vtu" ) ) { EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); } @@ -418,76 +425,83 @@ TEST_P( CompositionalTPFAIntegrationTest, PressureFieldL2Error ) // MFD-TPFA test: check linear pressure profile on polyhedral meshes class CompositionalMFDTPFAIntegrationTest : public ::testing::TestWithParam< const char * > { - public: - CompositionalMFDTPFAIntegrationTest() - : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} - - protected: - void SetUp() override - { - testBinaryDir = TEST_BINARY_DIR; - std::string meshFile = testBinaryDir + std::string("/") + GetParam(); - std::string xmlInput = generateXmlInputCompMFD( INNER_TPFA, meshFile ); - setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); - } - - GeosxState state; - std::string testBinaryDir; - }; +public: + CompositionalMFDTPFAIntegrationTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + +protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + std::string meshFile = testBinaryDir + std::string( "/" ) + GetParam(); + std::string xmlInput = generateXmlInputCompMFD( INNER_TPFA, meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; +}; INSTANTIATE_TEST_SUITE_P( MeshFiles, CompositionalMFDTPFAIntegrationTest, ::testing::Values( "polyhedral_voronoi_regular.vtu", - "polyhedral_voronoi_complex.vtu", - "polyhedral_voronoi_lattice.vtu" + "hex_pyr_tet_nested_mixed.vtu" ) -); + ); TEST_P( CompositionalMFDTPFAIntegrationTest, PressureFieldL2Error ) { - ProblemManager & problemManager = state.getProblemManager(); - DomainPartition & domain = problemManager.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseHybridFVM & >( - problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); - - // One implicit step with dt = 0.01 - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) - { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; - } ); - - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; - - // MFD(TPFA) is expected to be exact on these meshes - EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + // Expect exact solution only on the k-orthogonal regular mesh; expect non-zero error on mixed mesh + std::string meshFile = GetParam(); + if( meshFile == std::string( "polyhedral_voronoi_regular.vtu" ) ) + { + EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); + } + else + { + EXPECT_GT( l2Error, PRESSURE_L2_TOLERANCE ); + } } // Cross-check: TPFA vs MFD(TPFA): pressure and saturation profiles must match exactly @@ -498,103 +512,186 @@ INSTANTIATE_TEST_SUITE_P( CompositionalTPFAvsMFDTPFA, ::testing::Values( "polyhedral_voronoi_regular.vtu", - "polyhedral_voronoi_complex.vtu", - "polyhedral_voronoi_lattice.vtu" + "hex_pyr_tet_nested_mixed.vtu" ) -); + ); TEST_P( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) { std::string const testBinaryDir = TEST_BINARY_DIR; - std::string const meshFile = testBinaryDir + std::string("/") + GetParam(); - - std::vector< real64 > p_tpfa, p_mfd; - std::vector< real64 > sat_tpfa, sat_mfd; // phase volume fractions flattened [cell,phase] - localIndex n_cells_tpfa = 0, n_cells_mfd = 0; - localIndex n_phases_tpfa = 2, n_phases_mfd = 2; // From XML phaseNames - - // --- Run TPFA solver --- - { - GeosxState tpfaState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); - std::string xml = generateXmlInputCompTPFA( meshFile ); - setupProblemFromXML( tpfaState.getProblemManager(), xml.c_str() ); - - ProblemManager & pm = tpfaState.getProblemManager(); - DomainPartition & domain = pm.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseFVM & >( - pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); - - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); - n_cells_tpfa = subRegion.size(); - p_tpfa = arrayViewToVector( p_h, n_cells_tpfa ); - - auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); - sat_tpfa = arrayView2dToVector( sat, n_cells_tpfa, n_phases_tpfa ); - } - - // --- Run MFD solver (innerProductType = TPFA) --- - { - GeosxState mfdState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); - std::string xml = generateXmlInputCompMFD( INNER_TPFA, meshFile ); - setupProblemFromXML( mfdState.getProblemManager(), xml.c_str() ); - - ProblemManager & pm = mfdState.getProblemManager(); - DomainPartition & domain = pm.getDomainPartition(); - - auto & solver = - dynamic_cast< CompositionalMultiphaseHybridFVM & >( - pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); - - solver.setupSystem( domain, solver.getDofManager(), - solver.getLocalMatrix(), solver.getSystemRhs(), - solver.getSystemSolution() ); - solver.implicitStepSetup( 0.0, TIME_STEP, domain ); - solver.solverStep( 0.0, TIME_STEP, 0, domain ); - solver.updateState( domain ); - solver.implicitStepComplete( 0.0, TIME_STEP, domain ); - - MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); - CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - - arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); - n_cells_mfd = subRegion.size(); - p_mfd = arrayViewToVector( p_h, n_cells_mfd ); - - auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); - sat_mfd = arrayView2dToVector( sat, n_cells_mfd, n_phases_mfd ); - } - - ASSERT_EQ( n_cells_tpfa, n_cells_mfd ); - ASSERT_EQ( n_phases_tpfa, n_phases_mfd ); - - // Pressure profile equality - for( localIndex i = 0; i < n_cells_tpfa; ++i ) - { - real64 const diff = std::abs( p_tpfa[i] - p_mfd[i] ); - EXPECT_NEAR( diff, 0.0, PRESSURE_L2_TOLERANCE ); - } - - // Saturation profile (phase volume fraction) equality - size_t const nTot = static_cast< size_t >( n_cells_tpfa ) * static_cast< size_t >( n_phases_tpfa ); - for( size_t k = 0; k < nTot; ++k ) - { - real64 const diff = std::abs( sat_tpfa[k] - sat_mfd[k] ); - EXPECT_NEAR( diff, 0.0, SATURATION_L2_TOLERANCE ); - } - } + std::string const meshFile = testBinaryDir + std::string( "/" ) + GetParam(); + + std::vector< real64 > p_tpfa, p_mfd; + std::vector< real64 > sat_tpfa, sat_mfd; // phase volume fractions flattened [cell,phase] + localIndex n_cells_tpfa = 0, n_cells_mfd = 0; + localIndex n_phases_tpfa = 2, n_phases_mfd = 2; // From XML phaseNames + + // --- Run TPFA solver --- + { + GeosxState tpfaState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); + std::string xml = generateXmlInputCompTPFA( meshFile ); + setupProblemFromXML( tpfaState.getProblemManager(), xml.c_str() ); + + ProblemManager & pm = tpfaState.getProblemManager(); + DomainPartition & domain = pm.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseFVM & >( + pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseFVM >( "FlowSolverTPFA" ) ); + + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); + n_cells_tpfa = subRegion.size(); + p_tpfa = arrayViewToVector( p_h, n_cells_tpfa ); + + auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); + sat_tpfa = arrayView2dToVector( sat, n_cells_tpfa, n_phases_tpfa ); + } + + // --- Run MFD solver (innerProductType = TPFA) --- + { + GeosxState mfdState( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ); + std::string xml = generateXmlInputCompMFD( INNER_TPFA, meshFile ); + setupProblemFromXML( mfdState.getProblemManager(), xml.c_str() ); + + ProblemManager & pm = mfdState.getProblemManager(); + DomainPartition & domain = pm.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + pm.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); + n_cells_mfd = subRegion.size(); + p_mfd = arrayViewToVector( p_h, n_cells_mfd ); + + auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); + sat_mfd = arrayView2dToVector( sat, n_cells_mfd, n_phases_mfd ); + } + + ASSERT_EQ( n_cells_tpfa, n_cells_mfd ); + ASSERT_EQ( n_phases_tpfa, n_phases_mfd ); + + // Pressure profile equality + for( localIndex i = 0; i < n_cells_tpfa; ++i ) + { + real64 const diff = std::abs( p_tpfa[i] - p_mfd[i] ); + EXPECT_NEAR( diff, 0.0, PRESSURE_L2_TOLERANCE ); + } + + // Saturation profile (phase volume fraction) equality + size_t const nTot = static_cast< size_t >( n_cells_tpfa ) * static_cast< size_t >( n_phases_tpfa ); + for( size_t k = 0; k < nTot; ++k ) + { + real64 const diff = std::abs( sat_tpfa[k] - sat_mfd[k] ); + EXPECT_NEAR( diff, 0.0, SATURATION_L2_TOLERANCE ); + } +} + +// MFD non-TPFA inner products: check linear pressure profile is exact on both meshes +class CompositionalMFDNonTPFAExactnessTest : public ::testing::TestWithParam< std::tuple< const char *, const char * > > +{ +public: + CompositionalMFDNonTPFAExactnessTest() + : state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) {} + +protected: + void SetUp() override + { + testBinaryDir = TEST_BINARY_DIR; + auto const params = GetParam(); + innerProduct = std::get< 1 >( params ); + std::string const meshRel = std::get< 0 >( params ); + std::string const meshFile = testBinaryDir + std::string( "/" ) + meshRel; + std::string xmlInput = generateXmlInputCompMFD( innerProduct, meshFile ); + setupProblemFromXML( state.getProblemManager(), xmlInput.c_str() ); + } + + GeosxState state; + std::string testBinaryDir; + std::string innerProduct; +}; + +INSTANTIATE_TEST_SUITE_P( + MeshAndInnerProducts, + CompositionalMFDNonTPFAExactnessTest, + ::testing::Combine( + ::testing::Values( + "polyhedral_voronoi_regular.vtu", + "hex_pyr_tet_nested_mixed.vtu" + ), + ::testing::Values( + INNER_quasiTPFA, + INNER_BDVLM + ) + ) + ); + +TEST_P( CompositionalMFDNonTPFAExactnessTest, PressureFieldL2ErrorExact ) +{ + ProblemManager & problemManager = state.getProblemManager(); + DomainPartition & domain = problemManager.getDomainPartition(); + + auto & solver = + dynamic_cast< CompositionalMultiphaseHybridFVM & >( + problemManager.getPhysicsSolverManager().getGroup< CompositionalMultiphaseHybridFVM >( "FlowSolverMFD" ) ); + + // One implicit step with dt = 0.01 + solver.setupSystem( domain, solver.getDofManager(), + solver.getLocalMatrix(), solver.getSystemRhs(), + solver.getSystemSolution() ); + solver.implicitStepSetup( 0.0, TIME_STEP, domain ); + solver.solverStep( 0.0, TIME_STEP, 0, domain ); + solver.updateState( domain ); + solver.implicitStepComplete( 0.0, TIME_STEP, domain ); + + MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); + CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); + + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 x = centers[i][0]; + real64 volume = volumes[i]; + real64 pNumeric = p_h[i]; + real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; + l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; + totalVolume_ReduceSum += volume; + } ); + + real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; + real64 l2Error = std::sqrt( data[0] ) / data[1]; + + // Expect exact solution for these inner products on both meshes + EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); +} int main( int argc, char * * argv ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 9ec224a97d0..4189728c1ec 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -76,39 +76,39 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) // primary variables: face pressure changes faceManager.registerField< flow::facePressure_n >( getName() ); - + // Register the face data for global component fraction faceManager.registerField< flow::faceGlobalCompFraction >( getName() ); - + // Register the face data for temperature faceManager.registerField< flow::faceTemperature >( getName() ); - - - + + + // Register the bc face data for pressure faceManager.registerField< flow::bcPressure >( getName() ); // Register the bc face data for global component fraction faceManager.registerField< flow::bcGlobalCompFraction >( getName() ); - + // Register the bc face data for temperature faceManager.registerField< flow::bcTemperature >( getName() ); - + // Register face-based constitutive properties for BC faces // These will store fluid properties evaluated at BC conditions faceManager.registerField< flow::facePhaseMobility >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); - + faceManager.registerField< flow::facePhaseMassDensity >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); - + faceManager.registerField< flow::facePhaseCompFraction >( getName() ). 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() ); } ); @@ -188,7 +188,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou // Initialize all faces as interior (0), then mark boundary faces (1) arrayView1d< integer > const isBoundaryFaceView = faceManager.getReference< array1d< integer > >( flow::isBoundaryFace::key() ); // isBoundaryFaceView.setValues< serialPolicy >( 0 ); // default is zero - + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) { @@ -207,7 +207,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou } } } ); - + fsManager.forSubGroups< AquiferBoundaryCondition >( [&] ( AquiferBoundaryCondition const & bc ) { GEOS_LOG_RANK_0( getCatalogName() << " " << getDataContext() << ": An aquifer boundary condition named " << @@ -384,7 +384,7 @@ void CompositionalMultiphaseHybridFVM::assembleFluxTerms( real64 const dt, // Get boundary face indicator (initialized during initializePostInitialConditionsPreSubGroups) arrayView1d< integer const > const isBoundaryFaceView = faceManager.getField< flow::isBoundaryFace >(); - + // get the element dof numbers for the assembly string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > elemDofNumber = @@ -642,7 +642,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n using namespace mimeticInnerProduct; FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - + // Get the inner product type from the discretization NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); @@ -696,14 +696,13 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Get face boundary values arrayView1d< real64 const > const facePres = faceManager.getField< fields::flow::facePressure >(); -// std::cout << "facePres: " << facePres << std::endl; arrayView1d< real64 const > const faceTemp = faceManager.getField< fields::flow::faceTemperature >(); arrayView2d< real64 const, compflow::USD_COMP > const faceCompFrac = faceManager.getField< fields::flow::faceGlobalCompFraction >(); arrayView1d< real64 const > const faceGravCoef = faceManager.getField< fields::flow::gravityCoefficient >(); // Loop over regions and apply Dirichlet flux kernel elemManager.forElementSubRegions< CellElementSubRegion >( regionNames, [&]( localIndex const erIndex, - CellElementSubRegion & subRegion ) + CellElementSubRegion & subRegion ) { string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); @@ -731,7 +730,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } } } ); - + // Get writable face arrays for storing BC face properties arrayView2d< real64, compflow::USD_PHASE > facePhaseMob = faceManager.getField< flow::facePhaseMobility >(); @@ -750,7 +749,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Call evaluateBCFaceProperties to compute face properties at BC conditions constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) { - GEOS_UNUSED_VAR(fluidWrapper); + GEOS_UNUSED_VAR( fluidWrapper ); integer constexpr NUM_COMP = NC(); auto evaluateWithPhases = [&]( auto NP_VALUE ) @@ -759,20 +758,20 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n compositionalMultiphaseHybridFVMKernels::evaluateBCFaceProperties< NUM_COMP, NUM_PHASES > ( m_numPhases, - targetSet, - facePres, - faceTemp, - faceCompFrac, - elemRegionList, - elemSubRegionList, - elemList, - erIndex, - subRegion.getIndexInParent(), - fluid, - relperm, - facePhaseMob, - facePhaseMassDens, - facePhaseCompFrac ); + targetSet, + facePres, + faceTemp, + faceCompFrac, + elemRegionList, + elemSubRegionList, + elemList, + erIndex, + subRegion.getIndexInParent(), + fluid, + relperm, + facePhaseMob, + facePhaseMassDens, + facePhaseCompFrac ); }; if( m_numPhases == 2 ) @@ -793,7 +792,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n faceManager.getField< flow::facePhaseMassDensity >(); arrayView3d< real64 const, compflow::USD_PHASE_COMP > const facePhaseCompFracField = faceManager.getField< flow::facePhaseCompFraction >(); - + // Apply Dirichlet boundary fluxes for each face set using DirichletFluxKernel for( string const & setName : bcFaceSets ) { @@ -804,7 +803,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Launch the Dirichlet flux kernel with compile-time dispatch constitutive::constitutiveComponentUpdatePassThru( fluid, m_numComponents, [&]( auto & fluidWrapper, auto NC ) { - GEOS_UNUSED_VAR(fluidWrapper); + GEOS_UNUSED_VAR( fluidWrapper ); integer constexpr NUM_COMP = NC(); typename DirichletFluxKernel::CompFlowAccessors compFlowAccessors( elemManager, getName() ); @@ -817,7 +816,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n auto launchWithPhases = [&]( auto NP_VALUE ) { integer constexpr NP = decltype( NP_VALUE )::value; - + auto launchKernel = [&]( auto IP_TYPE_WRAPPER, auto NF_VALUE ) { using IP_TYPE = decltype( IP_TYPE_WRAPPER ); @@ -825,33 +824,33 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n DirichletFluxKernel::launch< NF, NUM_COMP, NP, IP_TYPE > ( m_numPhases, - erIndex, - subRegion.getIndexInParent(), - subRegion, - permeabilityModel, - targetSet, - facePres, - faceTemp, - facePhaseMobField, - facePhaseMassDensField, - facePhaseCompFracField, - nodePosition, - faceToNodes, - elemRegionList, - elemSubRegionList, - elemList, - faceDofNumber, - faceGravCoef, - transMultiplier, - lengthTolerance, - dt, - rankOffset, - m_useTotalMassEquation, - compFlowAccessors, - multiFluidAccessors, - elemDofNumberAccessor.toNestedViewConst(), - localMatrix, - localRhs ); + erIndex, + subRegion.getIndexInParent(), + subRegion, + permeabilityModel, + targetSet, + facePres, + faceTemp, + facePhaseMobField, + facePhaseMassDensField, + facePhaseCompFracField, + nodePosition, + faceToNodes, + elemRegionList, + elemSubRegionList, + elemList, + faceDofNumber, + faceGravCoef, + transMultiplier, + lengthTolerance, + dt, + rankOffset, + m_useTotalMassEquation, + compFlowAccessors, + multiFluidAccessors, + elemDofNumberAccessor.toNestedViewConst(), + localMatrix, + localRhs ); }; // Helper lambda to dispatch on number of faces per element @@ -863,20 +862,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n launchKernel( IP_TAG, std::integral_constant< integer, 5 >{} ); else if( numFacesPerElement == 6 ) launchKernel( IP_TAG, std::integral_constant< integer, 6 >{} ); - else if( numFacesPerElement == 7 ) - launchKernel( IP_TAG, std::integral_constant< integer, 7 >{} ); - else if( numFacesPerElement == 8 ) - launchKernel( IP_TAG, std::integral_constant< integer, 8 >{} ); - else if( numFacesPerElement == 9 ) - launchKernel( IP_TAG, std::integral_constant< integer, 9 >{} ); - else if( numFacesPerElement == 10 ) - launchKernel( IP_TAG, std::integral_constant< integer, 10 >{} ); - else if( numFacesPerElement == 11 ) - launchKernel( IP_TAG, std::integral_constant< integer, 11 >{} ); - else if( numFacesPerElement == 12 ) - launchKernel( IP_TAG, std::integral_constant< integer, 12 >{} ); - else if( numFacesPerElement == 13 ) - launchKernel( IP_TAG, std::integral_constant< integer, 13 >{} ); else GEOS_ERROR( "Unsupported number of faces per element: " << numFacesPerElement ); }; @@ -886,6 +871,10 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n { launchForFaces( TPFAInnerProduct{} ); } + else if( innerProductType == "quasiTPFA" ) + { + launchForFaces( QuasiTPFAInnerProduct{} ); + } else if( innerProductType == "beiraoDaVeigaLipnikovManzini" ) { launchForFaces( BdVLMInnerProduct{} ); @@ -905,7 +894,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } ); } } ); - + // Keep strong enforcement that the face pressure equals the informed bcPressure value (original behavior) arrayView1d< real64 const > const presFace = faceManager.getField< flow::facePressure >(); @@ -921,7 +910,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n FaceManager & targetGroup, string const & ) { - GEOS_UNUSED_VAR(setName); + GEOS_UNUSED_VAR( setName ); // Using the field specification functions to apply the boundary conditions to the system fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, @@ -941,7 +930,7 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // Get the dof number of this face globalIndex const dofIndex = faceDofNumber[kf]; localIndex const localRow = dofIndex - rankOffset; - + // ENFORCE DIRICHLET CONSTRAINT: x_i = x_spec // 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 @@ -952,13 +941,13 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n // 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() ) { arraySlice1d< globalIndex const > const columns = localMatrix.getColumns( localRow ); arraySlice1d< real64 > const entries = localMatrix.getEntries( localRow ); localIndex const numEntries = localMatrix.numNonZeros( localRow ); - + // Step 1: Zero out all row entries and set diagonal to 1 for( localIndex j = 0; j < numEntries; ++j ) { @@ -971,14 +960,14 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n entries[j] = 0.0; // Zero out off-diagonal entries } } - + // Set RHS to the prescribed boundary value (absolute value) localRhs[localRow] = presFace[kf] - presFaceBC[kf]; } - + } ); } ); - + } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index 65a8f1ce8f1..865b79a1462 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -94,13 +94,6 @@ 4, 5, 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13 ], "NCOMPS": [ 1, @@ -130,13 +123,6 @@ 4, 5, 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13 ], "NCOMPS": [ 1, @@ -151,6 +137,7 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", + "mimeticInnerProduct::QuasiTPFAInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, @@ -170,13 +157,6 @@ 4, 5, 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13 ], "NCOMPS": [ 1, @@ -191,6 +171,7 @@ ], "IP_TYPE": [ "mimeticInnerProduct::TPFAInnerProduct", + "mimeticInnerProduct::QuasiTPFAInnerProduct", "mimeticInnerProduct::BdVLMInnerProduct" ] }, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index c97e4e0b864..498dfa0c6b8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -391,7 +391,7 @@ struct AssemblerKernelHelper real64 ( &divMassFluxes )[ NC ], real64 ( &dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ], real64 ( &dDivMassFluxes_dFaceVars )[ NC ][ NF ], - globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ]); + globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ] ); /** * @brief In a given element, compute the buoyancy flux divergence, i.e, sum the buoyancy fluxes at this element's faces @@ -1233,35 +1233,17 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) switch( value ) { - case 4: { - return lambda( std::integral_constant{} ); - } - case 5: { - return lambda( std::integral_constant{} ); - } - case 6: { - return lambda( std::integral_constant{} ); - } - case 7: { - return lambda( std::integral_constant{} ); - } - case 8: { - return lambda( std::integral_constant{} ); - } - case 9: { - return lambda( std::integral_constant{} ); - } - case 10: { - return lambda( std::integral_constant{} ); - } - case 11: { - return lambda( std::integral_constant{} ); + case 4: + { + return lambda( std::integral_constant< int, 4 >{} ); } - case 12: { - return lambda( std::integral_constant{} ); + case 5: + { + return lambda( std::integral_constant< int, 5 >{} ); } - case 13: { - return lambda( std::integral_constant{} ); + case 6: + { + return lambda( std::integral_constant< int, 6 >{} ); } default: GEOS_ERROR( "Unknown numFacesInElem value: " << value ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 6390af0cd6f..537458ae3e9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -449,7 +449,7 @@ UpwindingHelper:: localIndex ( & totalMobIds )[ NP ][ 3 ], localIndex ( & totalMobPos )[ NP ] ) { - if constexpr( NP == 2 ) + if constexpr ( NP == 2 ) { if( gravTerm[0][0] > 0 ) { @@ -474,7 +474,7 @@ UpwindingHelper:: totalMobPos[1] = Pos::LOCAL; } } - else if constexpr( NP == 3 ) + else if constexpr ( NP == 3 ) { // TODO Francois: this should be improved // currently this implements the algorithm proposed by SH Lee @@ -681,7 +681,7 @@ AssemblerKernelHelper:: // for each element, loop over the one-sided faces for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc ) { - + // Contribute and Collect face DOF number only if this is not a boundary face if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) { @@ -777,7 +777,7 @@ AssemblerKernelHelper:: dt, divMassFluxes, dDivMassFluxes_dElemVars ); - + } else { @@ -813,14 +813,14 @@ AssemblerKernelHelper:: // Need to compact both DOF indices and derivatives to only include non-boundary neighbors globalIndex compactElemDofs[ NDOF*(NF+1) ]; real64 compactElemDerivs[ NDOF*(NF+1) ]; - + // Copy current element DOFs and derivatives for( integer idof = 0; idof < NDOF; ++idof ) { compactElemDofs[idof] = dofColIndicesElemVars[idof]; compactElemDerivs[idof] = dDivMassFluxes_dElemVars[ic][idof]; } - + // Copy neighbor DOFs and derivatives only for non-boundary faces integer compactIdx = NDOF; for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) @@ -836,7 +836,7 @@ AssemblerKernelHelper:: } } } - + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex, compactElemDofs, compactElemDerivs, @@ -854,7 +854,7 @@ AssemblerKernelHelper:: compactFaceDerivs[faceIndexMap[jfaceLoc]] = dDivMassFluxes_dFaceVars[ic][jfaceLoc]; } } - + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowLocalIndex, &dofColIndicesFaceVars[0], compactFaceDerivs, @@ -883,7 +883,7 @@ AssemblerKernelHelper:: real64 ( & divMassFluxes )[ NC ], real64 ( & dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ], real64 ( & dDivMassFluxes_dFaceVars )[ NC ][ NF ], - globalIndex ( & dofColIndicesElemVars )[ (NC+1)*(NF+1) ]) + globalIndex ( & dofColIndicesElemVars )[ (NC+1)*(NF+1) ] ) { integer constexpr NDOF = NC+1; localIndex const elemVarsOffset = NDOF*(ifaceLoc+1); @@ -1040,13 +1040,13 @@ AssemblerKernelHelper:: for( integer ifaceLoc = 0; ifaceLoc < NF; ++ifaceLoc ) { localIndex const kf = elemToFaces[ifaceLoc]; - + // Skip ghost faces if( faceGhostRank[kf] >= 0 ) { continue; } - + // Skip boundary faces - they have Dirichlet constraints, not flux continuity if( isBoundaryFace[kf] > 0 ) { @@ -1391,7 +1391,7 @@ DirichletFluxKernel:: CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - GEOS_UNUSED_VAR(faceTemp); + GEOS_UNUSED_VAR( faceTemp ); using Deriv = multifluid::DerivativeOffset; // Get element data @@ -1462,7 +1462,8 @@ DirichletFluxKernel:: break; } } - if( ifaceLoc < 0 ){ + if( ifaceLoc < 0 ) + { return; } @@ -1491,7 +1492,7 @@ DirichletFluxKernel:: real64 const elemDens = phaseMassDens[erAdj][esrAdj][eiAdj][0][ip]; real64 const faceDens = facePhaseMassDens[kf][ip]; real64 const densMean = 0.5 * (elemDens + faceDens); - + applyChainRule( NC, dCompFrac_dCompDens[erAdj][esrAdj][eiAdj], dPhaseMassDens[erAdj][esrAdj][eiAdj][0][ip], @@ -1534,7 +1535,7 @@ DirichletFluxKernel:: dF_dC[jc] += -Tij * dDensMean_dC[jc] * gravTimesDz_j; } } - + // Use element mobility (simplified upwinding for Dirichlet BC) // Upwind phase component fraction based on flow direction // Use the total flux f for upwinding decision @@ -1560,12 +1561,12 @@ DirichletFluxKernel:: { real64 const ycpElem = phaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic]; real64 const ycpFace = facePhaseCompFrac[kf][ip][ic]; - + // Upwind phase component fraction based on flow direction real64 const ycp = beta * ycpElem + (1.0 - beta) * ycpFace; - + compFlux[ic] += ycp * phaseFlux; - + // For derivatives, use element properties (simplified for boundary conditions) dCompFlux_dP[ic] += dPhaseFlux_dP * ycp + beta * phaseFlux * dPhaseCompFrac[erAdj][esrAdj][eiAdj][0][ip][ic][Deriv::dP]; @@ -1582,7 +1583,7 @@ DirichletFluxKernel:: // dycp/dC = beta * dycpElem/dC (ycpFace is BC, independent of C) dCompFlux_dC[ic][jc] += ycp * dPhaseFlux_dC[jc] + beta * phaseFlux * dycpElem_dC[jc]; } - + // Add derivatives w.r.t. face pressures for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { @@ -1620,27 +1621,27 @@ DirichletFluxKernel:: for( integer ic = 0; ic < NC; ++ic ) { RAJA::atomicAdd( parallelDeviceAtomic{}, &localRhs[localRow + ic], localFlux[ic] ); - + globalIndex dofColIndices[NC+1]; dofColIndices[0] = elemDof; for( integer jc = 0; jc < NC; ++jc ) { dofColIndices[jc+1] = elemDof + jc + 1; } - + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic, dofColIndices, localFluxJacobian[ic], NC+1 ); - + // Add contributions from face pressure derivatives for( integer jfaceLoc = 0; jfaceLoc < NF; ++jfaceLoc ) { localIndex const kfj = cellFaces[jfaceLoc]; globalIndex const faceDof = faceDofNumber[kfj]; - + real64 facePressureJacobian = dt * dCompFlux_dFaceP[ic][jfaceLoc]; - + // Apply total mass equation transformation if needed if( useTotalMassEquation && ic == 0 ) { @@ -1651,15 +1652,15 @@ DirichletFluxKernel:: facePressureJacobian += dt * dCompFlux_dFaceP[icc][jfaceLoc]; } } - + localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow + ic, &faceDof, &facePressureJacobian, 1 ); } - + } - + } ); } @@ -1713,71 +1714,72 @@ evaluateBCFaceProperties( integer const numPhases, { using RelPermType = TYPEOFREF( castedRelperm ); typename RelPermType::KernelWrapper relPermWrapper = castedRelperm.createKernelWrapper(); - GEOS_UNUSED_VAR(relPermWrapper); - + GEOS_UNUSED_VAR( relPermWrapper ); + // Loop over BC faces and evaluate properties at BC conditions forAll< serialPolicy >( boundaryFaceSet.size(), [=, &facePhaseMob, &facePhaseMassDens, &facePhaseCompFrac] ( localIndex const iset ) - { - localIndex const kf = boundaryFaceSet[iset]; - - // Find adjacent element in target region - localIndex eiAdj = -1; - for( integer ke = 0; ke < elemRegionList.size( 1 ); ++ke ) { - if( elemRegionList[kf][ke] == er && elemSubRegionList[kf][ke] == esr ) + localIndex const kf = boundaryFaceSet[iset]; + + // Find adjacent element in target region + localIndex eiAdj = -1; + for( integer ke = 0; ke < elemRegionList.size( 1 ); ++ke ) { - eiAdj = elemList[kf][ke]; - break; + if( elemRegionList[kf][ke] == er && elemSubRegionList[kf][ke] == esr ) + { + eiAdj = elemList[kf][ke]; + break; + } } - } - if( eiAdj < 0 ) return; - - // Allocate temporary storage for face constitutive properties - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseFrac( 1, 1, numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseDens( 1, 1, numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseMassDensLocal( 1, 1, numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseVisc( 1, 1, numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseEnthalpy( 1, 1, numPhases ); - StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); - StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, - constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); - real64 faceTotalDens = 0.0; - - // Evaluate fluid properties at BC face conditions using flash calculation - constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper, - facePres[kf], - faceTemp[kf], - faceCompFrac[kf], - facePhaseFrac[0][0], - facePhaseDens[0][0], - facePhaseMassDensLocal[0][0], - facePhaseVisc[0][0], - facePhaseEnthalpy[0][0], - facePhaseInternalEnergy[0][0], - facePhaseCompFracLocal[0][0], - faceTotalDens ); - - // Evaluate relative permeability at face saturation from flash calculation + if( eiAdj < 0 ) + return; + + // Allocate temporary storage for face constitutive properties + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseFrac( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseDens( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseMassDensLocal( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseVisc( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseEnthalpy( 1, 1, numPhases ); + StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); + StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, + constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); + real64 faceTotalDens = 0.0; + + // Evaluate fluid properties at BC face conditions using flash calculation + constitutive::MultiFluidBase::KernelWrapper::computeValues( fluidWrapper, + facePres[kf], + faceTemp[kf], + faceCompFrac[kf], + facePhaseFrac[0][0], + facePhaseDens[0][0], + facePhaseMassDensLocal[0][0], + facePhaseVisc[0][0], + facePhaseEnthalpy[0][0], + facePhaseInternalEnergy[0][0], + facePhaseCompFracLocal[0][0], + faceTotalDens ); + + // Evaluate relative permeability at face saturation from flash calculation // relPermWrapper.compute( facePhaseFrac[0][0], 0, 0 ); - - // Store computed properties in output arrays - for( integer ip = 0; ip < numPhases; ++ip ) - { - // Store phase mass density from flash calculation - facePhaseMassDens[kf][ip] = facePhaseMassDensLocal[0][0][ip]; - - // Compute mobility from relative permeability evaluated at face conditions - real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; - real64 const mu = facePhaseVisc[0][0][ip]; - facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; - - // Store phase composition from flash calculation - for( integer ic = 0; ic < NC; ++ic ) + + // Store computed properties in output arrays + for( integer ip = 0; ip < numPhases; ++ip ) { - facePhaseCompFrac[kf][ip][ic] = facePhaseCompFracLocal[0][0][ip][ic]; + // Store phase mass density from flash calculation + facePhaseMassDens[kf][ip] = facePhaseMassDensLocal[0][0][ip]; + + // Compute mobility from relative permeability evaluated at face conditions + real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; + real64 const mu = facePhaseVisc[0][0][ip]; + facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; + + // Store phase composition from flash calculation + for( integer ic = 0; ic < NC; ++ic ) + { + facePhaseCompFrac[kf][ip][ic] = facePhaseCompFracLocal[0][0][ip][ic]; + } } - } - } ); + } ); } ); // end nested constitutiveUpdatePassThru for relperm } ); // end constitutiveUpdatePassThru for fluid } From 5fb7a624d8333cfd98d71bd3db68ecc1b1b93f87 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 20:02:18 -0700 Subject: [PATCH 60/91] fix: code style and reduce number of kernel combinations --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 26 +- ...aseHybridFVMKernels_dirichlet.cpp.template | 63 --- ...ltiphaseHybridFVMKernels_flux.cpp.template | 52 --- .../SinglePhaseHybridFVMKernels.cpp.template | 21 - .../physicsSolvers/fluidFlow/kernelSpecs.json | 104 ----- ...ltiphaseHybridFVMKernelsInstantiations.cpp | 359 ++++++++++++++++++ ...itionalMultiphaseHybridFVMKernels_impl.hpp | 171 --------- ...glePhaseHybridFVMKernelsInstantiations.cpp | 97 +++++ 8 files changed, 467 insertions(+), 426 deletions(-) delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVMKernels.cpp.template create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 3dcef5bca76..ca1a3e0745e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -152,27 +152,21 @@ set( fluidFlowSolvers_sources wells/WellControls.cpp wells/WellSolverBase.cpp proppantTransport/ProppantTransport.cpp - proppantTransport/ProppantTransportKernels.cpp ) - -set( dependencyList ${parallelDeps} physicsSolversBase ) - -geos_decorate_link_dependencies( LIST decoratedDependencies DEPENDENCIES ${dependencyList} ) - - - + proppantTransport/ProppantTransportKernels.cpp + # Macro-based explicit instantiations for hybrid FVM kernels + kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp + kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp ) +# Remove the old generator-based hybrid flux/dirichlet kernels and switch to macro approach file( READ "${CMAKE_CURRENT_LIST_DIR}/kernelSpecs.json" kernelSpecs ) set( kernelTemplateFileList "" ) +# Keep only the templates that are unrelated to hybrid flux/dirichlet list( APPEND kernelTemplateFileList - SinglePhaseHybridFVMKernels.cpp.template CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template - CompositionalMultiphaseHybridFVMKernels_flux.cpp.template - CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template ReactiveCompositionalMultiphaseOBLKernels.cpp.template ) - foreach( kernelTemplateFile ${kernelTemplateFileList} ) get_filename_component( jsonKey ${kernelTemplateFile} NAME_WE ) generateKernels( TEMPLATE ${kernelTemplateFile} @@ -180,9 +174,8 @@ foreach( kernelTemplateFile ${kernelTemplateFileList} ) KEY ${jsonKey} HEADERS headerFiles SOURCES sourceFiles ) - -list(APPEND fluidFlowSolvers_headers ${headerFiles}) -list(APPEND fluidFlowSolvers_sources ${sourceFiles}) + list(APPEND fluidFlowSolvers_headers ${headerFiles}) + list(APPEND fluidFlowSolvers_sources ${sourceFiles}) endforeach() # TODO: The two kernels below have non-matching file names and JSON keys. @@ -216,6 +209,9 @@ blt_add_library( NAME fluidFlowSolvers SHARED ${GEOS_BUILD_SHARED_LIBS} ) +# Always enable the manual instantiation compile flag +target_compile_definitions( fluidFlowSolvers PUBLIC GEOS_ENABLE_MANUAL_HYBRID_FVM_INST ) + target_include_directories( fluidFlowSolvers PUBLIC ${CMAKE_SOURCE_DIR}/coreComponents ) install( TARGETS fluidFlowSolvers LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template deleted file mode 100644 index 40be0e67241..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_dirichlet.cpp.template +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp" - -namespace geos -{ -namespace compositionalMultiphaseHybridFVMKernels -{ - constexpr int NF = @NFACES@; - constexpr int NC = @NCOMPS@; - constexpr int NP = @NPHASES@; - using IP_TYPE = @IP_TYPE@; - - @EXTERN@ - template - void - DirichletFluxKernel:: - launch< NF, NC, NP, IP_TYPE >( integer const numPhases, - localIndex const er, - localIndex const esr, - CellElementSubRegion const & subRegion, - constitutive::PermeabilityBase const & permeabilityModel, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, - ArrayOfArraysView< localIndex const > const & faceToNodes, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< real64 const > const & faceGravCoef, - arrayView1d< real64 const > const & transMultiplier, - real64 const lengthTolerance, - real64 const dt, - globalIndex const rankOffset, - integer const useTotalMassEquation, - CompFlowAccessors const & compFlowAccessors, - MultiFluidAccessors const & multiFluidAccessors, - ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - -} -} - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template deleted file mode 100644 index ccc0cce069d..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_flux.cpp.template +++ /dev/null @@ -1,52 +0,0 @@ -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp" - -namespace geos -{ -namespace compositionalMultiphaseHybridFVMKernels -{ - constexpr int NF = @NFACES@; - constexpr int NC = @NCOMPS@; - constexpr int NP = @NPHASES@; - using IP_TYPE = @IP_TYPE@; - - @EXTERN@ - template - void - FluxKernel:: - launch< NF, NC, NP, IP_TYPE >( localIndex er, localIndex esr, - CellElementSubRegion const & subRegion, - constitutive::PermeabilityBase const & permeabilityModel, - SortedArrayView< localIndex const > const & regionFilter, - arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - ArrayOfArraysView< localIndex const > const & faceToNodes, - arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< integer const > const & faceGhostRank, - arrayView1d< integer const > const & isBoundaryFace, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceGravCoef, - arrayView1d< real64 const > const & mimFaceGravCoef, - arrayView1d< real64 const > const & transMultiplier, - ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const & phaseDens, - ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const & dPhaseDens, - ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const & phaseMassDens, - ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const & dPhaseMassDens, - ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, - ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, - ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, - globalIndex const rankOffset, - real64 const lengthTolerance, - real64 const dt, - integer const useTotalMassEquation, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - -} -} - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVMKernels.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVMKernels.cpp.template deleted file mode 100644 index 5a8a3464124..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVMKernels.cpp.template +++ /dev/null @@ -1,21 +0,0 @@ -#include "physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernels.hpp" -#include "finiteVolume/mimeticInnerProducts/TPFAInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/QuasiTPFAInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/QuasiRTInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/SimpleInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/BdVLMInnerProduct.hpp" - -using ElementBasedAssemblyKernelPolicy = @ElementBasedAssemblyKernelPolicy@; - -namespace geos -{ -namespace singlePhaseHybridFVMKernels -{ - @EXTERN@ template class @NAME@ < @NFACES@, @IP@ >; - @EXTERN@ template void @NAME@ < @NFACES@, @IP@ >::launch< @NAME@Policy, - @NAME@ < @NFACES@, @IP@ > > - ( const localIndex, - @NAME@ < @NFACES@, @IP@ > const & ); -} -} - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index 865b79a1462..184d197cea3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -24,42 +24,6 @@ "generation call). Duplicate entries are unified internally" ] }, - "SinglePhaseHybridFVMKernels": { - "vars": [ - "NAME", - "NFACES", - "IP" - ], - "constants": [ - [ "ElementBasedAssemblyKernelPolicy", "geos::parallelDevicePolicy< GEOS_BLOCK_SIZE >" ] - ], - "combinations": { - "NAME": [ - "ElementBasedAssemblyKernel" - ], - "NFACES": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13 - ], - "IP": [ - "mimeticInnerProduct::TPFAInnerProduct", - "mimeticInnerProduct::QuasiTPFAInnerProduct", - "mimeticInnerProduct::QuasiRTInnerProduct", - "mimeticInnerProduct::SimpleInnerProduct", - "mimeticInnerProduct::BdVLMInnerProduct" - ] - }, - "explicit": [] - }, - "CompositionalMultiphaseHybridFVMKernels_upwinding": { "vars": [ "NCOMPS", @@ -110,74 +74,6 @@ "explicit": [] }, - "CompositionalMultiphaseHybridFVMKernels_flux": { - "vars": [ - "NFACES", - "NCOMPS", - "NPHASES", - "IP_TYPE" - ], - "constants": [], - "combinations": { - "NFACES": [ - 4, - 5, - 6, - ], - "NCOMPS": [ - 1, - 2, - 3, - 4, - 5 - ], - "NPHASES": [ - 2, - 3 - ], - "IP_TYPE": [ - "mimeticInnerProduct::TPFAInnerProduct", - "mimeticInnerProduct::QuasiTPFAInnerProduct", - "mimeticInnerProduct::BdVLMInnerProduct" - ] - }, - "explicit": [] - }, - - "CompositionalMultiphaseHybridFVMKernels_dirichlet": { - "vars": [ - "NFACES", - "NCOMPS", - "NPHASES", - "IP_TYPE" - ], - "constants": [], - "combinations": { - "NFACES": [ - 4, - 5, - 6, - ], - "NCOMPS": [ - 1, - 2, - 3, - 4, - 5 - ], - "NPHASES": [ - 2, - 3 - ], - "IP_TYPE": [ - "mimeticInnerProduct::TPFAInnerProduct", - "mimeticInnerProduct::QuasiTPFAInnerProduct", - "mimeticInnerProduct::BdVLMInnerProduct" - ] - }, - "explicit": [] - }, - "ReactiveCompositionalMultiphaseOBLKernels": { "vars": [ "NAME", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp new file mode 100644 index 00000000000..b755757a75c --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp @@ -0,0 +1,359 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp + * @brief Centralized explicit template instantiations for compositional hybrid FVM kernels. + * + * Define GEOS_ENABLE_MANUAL_HYBRID_FVM_INST to activate the explicit instantiations below. + * When enabled, ensure overlapping template-generated sources are not compiled to avoid duplicates. + */ + +#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp" + +#include "finiteVolume/mimeticInnerProducts/TPFAInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/QuasiTPFAInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/BdVLMInnerProduct.hpp" + +namespace geos +{ +namespace compositionalMultiphaseHybridFVMKernels +{ + +#if defined(GEOS_ENABLE_MANUAL_HYBRID_FVM_INST) + +// ----------------------------------------------------------------------------- +// Range driver +// ----------------------------------------------------------------------------- +#define GEOS_NFACES_LIST \ + X_NF( 4 ) \ + X_NF( 5 ) \ + X_NF( 6 ) + +// ----------------------------------------------------------------------------- +// Common parameter macros (kept in sync with kernel signatures) +// ----------------------------------------------------------------------------- +#define GEOS_DIRICHLET_LAUNCH_PARAMS \ + integer const numPhases, \ + localIndex const er, \ + localIndex const esr, \ + CellElementSubRegion const & subRegion, \ + constitutive::PermeabilityBase const & permeabilityModel, \ + SortedArrayView< localIndex const > const & boundaryFaceSet, \ + arrayView1d< real64 const > const & facePres, \ + arrayView1d< real64 const > const & faceTemp, \ + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMob, \ + arrayView2d< real64 const, compflow::USD_PHASE > const & facePhaseMassDens, \ + arrayView3d< real64 const, compflow::USD_PHASE_COMP > const & facePhaseCompFrac, \ + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, \ + ArrayOfArraysView< localIndex const > const & faceToNodes, \ + arrayView2d< localIndex const > const & elemRegionList, \ + arrayView2d< localIndex const > const & elemSubRegionList, \ + arrayView2d< localIndex const > const & elemList, \ + arrayView1d< globalIndex const > const & faceDofNumber, \ + arrayView1d< real64 const > const & faceGravCoef, \ + arrayView1d< real64 const > const & transMultiplier, \ + real64 const lengthTolerance, \ + real64 const dt, \ + globalIndex const rankOffset, \ + integer const useTotalMassEquation, \ + DirichletFluxKernel::CompFlowAccessors const & compFlowAccessors, \ + DirichletFluxKernel::MultiFluidAccessors const & multiFluidAccessors, \ + DirichletFluxKernel::ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, \ + CRSMatrixView< real64, globalIndex const > const & localMatrix, \ + arrayView1d< real64 > const & localRhs + +#define GEOS_FLUX_LAUNCH_PARAMS \ + localIndex er, localIndex esr, \ + CellElementSubRegion const & subRegion, \ + constitutive::PermeabilityBase const & permeabilityModel, \ + SortedArrayView< localIndex const > const & regionFilter, \ + arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const & nodePosition, \ + arrayView2d< localIndex const > const & elemRegionList, \ + arrayView2d< localIndex const > const & elemSubRegionList, \ + arrayView2d< localIndex const > const & elemList, \ + ArrayOfArraysView< localIndex const > const & faceToNodes, \ + arrayView1d< globalIndex const > const & faceDofNumber, \ + arrayView1d< integer const > const & faceGhostRank, \ + arrayView1d< integer const > const & isBoundaryFace, \ + arrayView1d< real64 const > const & facePres, \ + arrayView1d< real64 const > const & faceGravCoef, \ + arrayView1d< real64 const > const & mimFaceGravCoef, \ + arrayView1d< real64 const > const & transMultiplier, \ + FluxKernel::ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, \ + FluxKernel::ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, \ + FluxKernel::ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, \ + FluxKernel::ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const & phaseDens, \ + FluxKernel::ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const & dPhaseDens, \ + FluxKernel::ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const & phaseMassDens, \ + FluxKernel::ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const & dPhaseMassDens, \ + FluxKernel::ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_COMP > > const & phaseCompFrac, \ + FluxKernel::ElementViewConst< arrayView5d< real64 const, multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, \ + FluxKernel::ElementViewConst< arrayView1d< globalIndex const > > const & elemDofNumber, \ + globalIndex const rankOffset, \ + real64 const lengthTolerance, \ + real64 const dt, \ + integer const useTotalMassEquation, \ + CRSMatrixView< real64, globalIndex const > const & localMatrix, \ + arrayView1d< real64 > const & localRhs + +// ----------------------------------------------------------------------------- +// IP list helper +// ----------------------------------------------------------------------------- +#define GEOS_FOR_EACH_IP( NF, NC, NP, MACRO ) \ + MACRO( NF, NC, NP, mimeticInnerProduct::TPFAInnerProduct ) \ + MACRO( NF, NC, NP, mimeticInnerProduct::QuasiTPFAInnerProduct ) \ + MACRO( NF, NC, NP, mimeticInnerProduct::BdVLMInnerProduct ) + +// ----------------------------------------------------------------------------- +// DirichletFluxKernel explicit instantiations +// ----------------------------------------------------------------------------- +#define INSTANTIATE_DIRICHLET( NF, NC, NP, IP ) \ + template void DirichletFluxKernel::launch< NF, NC, NP, IP >( GEOS_DIRICHLET_LAUNCH_PARAMS ); + +#define INSTANTIATE_DIRICHLET_FOR_NP( NF, NC, NP ) \ + GEOS_FOR_EACH_IP( NF, NC, NP, INSTANTIATE_DIRICHLET ) + +#define INSTANTIATE_DIRICHLET_FOR_NC( NF, NC ) \ + INSTANTIATE_DIRICHLET_FOR_NP( NF, NC, 2 ) \ + INSTANTIATE_DIRICHLET_FOR_NP( NF, NC, 3 ) + +#define INSTANTIATE_DIRICHLET_FOR_NF( NF ) \ + INSTANTIATE_DIRICHLET_FOR_NC( NF, 1 ) \ + INSTANTIATE_DIRICHLET_FOR_NC( NF, 2 ) \ + INSTANTIATE_DIRICHLET_FOR_NC( NF, 3 ) \ + INSTANTIATE_DIRICHLET_FOR_NC( NF, 4 ) \ + INSTANTIATE_DIRICHLET_FOR_NC( NF, 5 ) + +#define X_NF( NF ) INSTANTIATE_DIRICHLET_FOR_NF( NF ) +GEOS_NFACES_LIST +#undef X_NF + +// ----------------------------------------------------------------------------- +// FluxKernel explicit instantiations +// ----------------------------------------------------------------------------- +#define INSTANTIATE_FLUX( NF, NC, NP, IP ) \ + template void FluxKernel::launch< NF, NC, NP, IP >( GEOS_FLUX_LAUNCH_PARAMS ); + +#define INSTANTIATE_FLUX_FOR_NP( NF, NC, NP ) \ + GEOS_FOR_EACH_IP( NF, NC, NP, INSTANTIATE_FLUX ) + +#define INSTANTIATE_FLUX_FOR_NC( NF, NC ) \ + INSTANTIATE_FLUX_FOR_NP( NF, NC, 2 ) \ + INSTANTIATE_FLUX_FOR_NP( NF, NC, 3 ) + +#define INSTANTIATE_FLUX_FOR_NF( NF ) \ + INSTANTIATE_FLUX_FOR_NC( NF, 1 ) \ + INSTANTIATE_FLUX_FOR_NC( NF, 2 ) \ + INSTANTIATE_FLUX_FOR_NC( NF, 3 ) \ + INSTANTIATE_FLUX_FOR_NC( NF, 4 ) \ + INSTANTIATE_FLUX_FOR_NC( NF, 5 ) + +#define X_NF( NF ) INSTANTIATE_FLUX_FOR_NF( NF ) +GEOS_NFACES_LIST +#undef X_NF + +// Cleanup local helper macros +#undef GEOS_DIRICHLET_LAUNCH_PARAMS +#undef GEOS_FLUX_LAUNCH_PARAMS +#undef GEOS_FOR_EACH_IP +#undef INSTANTIATE_DIRICHLET +#undef INSTANTIATE_DIRICHLET_FOR_NP +#undef INSTANTIATE_DIRICHLET_FOR_NC +#undef INSTANTIATE_DIRICHLET_FOR_NF +#undef INSTANTIATE_FLUX +#undef INSTANTIATE_FLUX_FOR_NP +#undef INSTANTIATE_FLUX_FOR_NC +#undef INSTANTIATE_FLUX_FOR_NF +#undef GEOS_NFACES_LIST + +// ----------------------------------------------------------------------------- +// evaluateBCFaceProperties explicit instantiations +// ----------------------------------------------------------------------------- +template void +evaluateBCFaceProperties< 1, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 2, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 3, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 4, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 5, 2 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 1, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 2, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 3, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 4, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +template void +evaluateBCFaceProperties< 5, 3 >( integer const numPhases, + SortedArrayView< localIndex const > const & boundaryFaceSet, + arrayView1d< real64 const > const & facePres, + arrayView1d< real64 const > const & faceTemp, + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, + arrayView2d< localIndex const > const & elemRegionList, + arrayView2d< localIndex const > const & elemSubRegionList, + arrayView2d< localIndex const > const & elemList, + localIndex const er, + localIndex const esr, + constitutive::MultiFluidBase & fluid, + constitutive::RelativePermeabilityBase & relperm, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +#endif // GEOS_ENABLE_MANUAL_HYBRID_FVM_INST + +} // namespace compositionalMultiphaseHybridFVMKernels +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 537458ae3e9..0d569e43cc6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1784,177 +1784,6 @@ evaluateBCFaceProperties( integer const numPhases, } ); // end constitutiveUpdatePassThru for fluid } -// Explicit template instantiations -template void -evaluateBCFaceProperties< 1, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 2, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 3, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 4, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 5, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 1, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 2, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 3, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 4, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 5, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - } // namespace compositionalMultiphaseHybridFVMKernels } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp new file mode 100644 index 00000000000..a573b1db6cb --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp @@ -0,0 +1,97 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file SinglePhaseHybridFVMKernelsInstantiations.cpp + * @brief Centralized explicit template instantiations for single-phase hybrid FVM kernels. + * + * Define GEOS_ENABLE_MANUAL_HYBRID_FVM_INST to activate the explicit instantiations below. + * When enabled, ensure overlapping template-generated sources are not compiled to avoid duplicates. + */ + +#include "physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernels.hpp" + +#include "finiteVolume/mimeticInnerProducts/TPFAInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/QuasiTPFAInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/QuasiRTInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/SimpleInnerProduct.hpp" +#include "finiteVolume/mimeticInnerProducts/BdVLMInnerProduct.hpp" + +namespace geos +{ +namespace singlePhaseHybridFVMKernels +{ + +#if defined(GEOS_ENABLE_MANUAL_HYBRID_FVM_INST) + +// ----------------------------------------------------------------------------- +// Faces-per-element list (kept in sync with kernelLaunchSelectorFaceSwitch) +// ----------------------------------------------------------------------------- +#define GEOS_NFACES_LIST \ + X_NF( 4 ) \ + X_NF( 5 ) \ + X_NF( 6 ) \ + X_NF( 7 ) \ + X_NF( 8 ) \ + X_NF( 9 ) \ + X_NF( 10 ) \ + X_NF( 11 ) \ + X_NF( 12 ) \ + X_NF( 13 ) + +// ----------------------------------------------------------------------------- +// Inner product list helper +// ----------------------------------------------------------------------------- +#define GEOS_FOR_EACH_IP( NF, MACRO ) \ + MACRO( NF, mimeticInnerProduct::TPFAInnerProduct ) \ + MACRO( NF, mimeticInnerProduct::QuasiTPFAInnerProduct ) \ + MACRO( NF, mimeticInnerProduct::QuasiRTInnerProduct ) \ + MACRO( NF, mimeticInnerProduct::SimpleInnerProduct ) \ + MACRO( NF, mimeticInnerProduct::BdVLMInnerProduct ) + +// ----------------------------------------------------------------------------- +// AveragePressureGradientKernel explicit class instantiations +// ----------------------------------------------------------------------------- +#define INSTANTIATE_AVG_PRES_GRAD( NF ) \ + template class AveragePressureGradientKernel< NF >; + +#define X_NF( NF ) INSTANTIATE_AVG_PRES_GRAD( NF ) +GEOS_NFACES_LIST +#undef X_NF +#undef INSTANTIATE_AVG_PRES_GRAD + +// ----------------------------------------------------------------------------- +// ElementBasedAssemblyKernel explicit class instantiations +// ----------------------------------------------------------------------------- +#define INSTANTIATE_ELEM_KERNEL( NF, IP ) \ + template class ElementBasedAssemblyKernel< NF, IP >; + +#define INSTANTIATE_ELEM_KERNEL_FOR_IPS( NF ) \ + GEOS_FOR_EACH_IP( NF, INSTANTIATE_ELEM_KERNEL ) + +#define X_NF( NF ) INSTANTIATE_ELEM_KERNEL_FOR_IPS( NF ) +GEOS_NFACES_LIST +#undef X_NF +#undef INSTANTIATE_ELEM_KERNEL_FOR_IPS +#undef INSTANTIATE_ELEM_KERNEL + +// Cleanup local helper macros +#undef GEOS_FOR_EACH_IP +#undef GEOS_NFACES_LIST + +#endif // GEOS_ENABLE_MANUAL_HYBRID_FVM_INST + +} // namespace singlePhaseHybridFVMKernels +} // namespace geos From 4204558ff92c44ad48eae476d017efa9bb3f579f Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 22:12:54 -0700 Subject: [PATCH 61/91] Update src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../integrationTests/fluidFlowTests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt index 32063b4ff7b..ce446028ce0 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt @@ -62,7 +62,7 @@ foreach(test ${gtest_geosx_tests}) COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/hex_pyr_tet_nested_mixed.vtu $ - ) + ) endforeach() From 1428556ab3292e96cbdc637a70ba5019a05a5e9f Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 22:13:15 -0700 Subject: [PATCH 62/91] Update src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index 184d197cea3..fcaf45e21c2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -57,7 +57,7 @@ "NFACES": [ 4, 5, - 6, + 6 ], "NCOMPS": [ 1, From 4d97286b74b5c1286afcea9650b64ccf53ced247 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 22:13:36 -0700 Subject: [PATCH 63/91] Update src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 4189728c1ec..3ff037f47da 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -187,7 +187,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou // Mark boundary faces (faces with Dirichlet BCs) to skip flux continuity constraint // Initialize all faces as interior (0), then mark boundary faces (1) arrayView1d< integer > const isBoundaryFaceView = faceManager.getReference< array1d< integer > >( flow::isBoundaryFace::key() ); -// isBoundaryFaceView.setValues< serialPolicy >( 0 ); // default is zero + // isBoundaryFaceView is default-initialized to zero FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); fsManager.forSubGroups< FieldSpecificationBase >( [&]( FieldSpecificationBase const & fs ) From cfb1fdedaf6bb13c1aff6f9f9f5094dc39b71a5c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 22:30:19 -0700 Subject: [PATCH 64/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 0d569e43cc6..623d9c8d852 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -685,6 +685,12 @@ AssemblerKernelHelper:: // Contribute and Collect face DOF number only if this is not a boundary face if( isBoundaryFace[elemToFaces[ifaceLoc]] == 0 ) { + + faceIndexMap[ifaceLoc] = numNonBoundaryFaces; + dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; + numNonBoundaryFaces++; + + // 1) Find if there is a neighbor, and if there is, grab the indices of the neighbor element localIndex neighborIds[ 3 ] = { localIds[0], localIds[1], localIds[2] }; hybridFVMKernels::CellConnectivity::isNeighborFound( localIds, @@ -735,11 +741,6 @@ AssemblerKernelHelper:: dofColIndicesElemVars ); - faceIndexMap[ifaceLoc] = numNonBoundaryFaces; - dofColIndicesFaceVars[numNonBoundaryFaces] = faceDofNumber[elemToFaces[ifaceLoc]]; - numNonBoundaryFaces++; - - // 3) *************** Assemble buoyancy terms ****************** real64 const transGravCoef = (localIds[0] != neighborIds[0] || localIds[1] != neighborIds[1] || localIds[2] != neighborIds[2]) From 92747f2fc7f73276fbc73ad819e7b080c6b7cfa5 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 22:44:46 -0700 Subject: [PATCH 65/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- .../compositional/CompositionalMultiphaseHybridFVMKernels.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index b6509135f81..bd59b444fab 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -362,6 +362,7 @@ struct AssemblerKernelHelper arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & mimeticTransGgradZ, + arrayView1d< real64 const > const & faceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, From 0feb21a12be213ff89455c83e5085b55a4d06753 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 22:58:53 -0700 Subject: [PATCH 66/91] fix: merge conflicts --- src/cmake/GeosxOptions.cmake | 2 +- ...haseHybridFVMKernels_assembly.cpp.template | 1 + ...ompositionalMultiphaseHybridFVMKernels.hpp | 54 +++++-------------- 3 files changed, 16 insertions(+), 41 deletions(-) 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/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template index f415d455135..4761352a359 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template @@ -44,6 +44,7 @@ namespace compositionalMultiphaseHybridFVMKernels arrayView1d< globalIndex const > const & faceDofNumber, arrayView1d< integer const > const & isBoundaryFace, arrayView1d< real64 const > const & mimeticTransGgradZ, + arrayView1d< real64 const > const & faceGravCoef, arraySlice1d< localIndex const > const & elemToFaces, real64 const & elemGravCoef, integer const useTotalMassEquation, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index bd59b444fab..2f0a4ec08d7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -55,17 +55,20 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) switch( value ) { - case 4: lambda( std::integral_constant< T, 4 >() ); return; - case 5: lambda( std::integral_constant< T, 5 >() ); return; - case 6: lambda( std::integral_constant< T, 6 >() ); return; - case 7: lambda( std::integral_constant< T, 7 >() ); return; - case 8: lambda( std::integral_constant< T, 8 >() ); return; - case 9: lambda( std::integral_constant< T, 9 >() ); return; - case 10: lambda( std::integral_constant< T, 10 >() ); return; - case 11: lambda( std::integral_constant< T, 11 >() ); return; - case 12: lambda( std::integral_constant< T, 12 >() ); return; - case 13: lambda( std::integral_constant< T, 13 >() ); return; - default: GEOS_ERROR( "Unknown numFacesInElem value: " << 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 >{} ); + } + default: + GEOS_ERROR( "Unknown numFacesInElem value: " << value ); } } @@ -1297,35 +1300,6 @@ struct PrecomputeMimeticTransGgradZKernel /******************************** 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 >{} ); - } - default: - GEOS_ERROR( "Unknown numFacesInElem value: " << value ); - } -} - -} // namespace internal - template< typename KERNELWRAPPER, typename INNER_PRODUCT, typename ... ARGS > void simpleKernelLaunchSelector( localIndex numFacesInElem, ARGS && ... args ) { From 9e7b03db34e3a2b80b67fe549749d4c1936df7b2 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 29 Oct 2025 23:16:36 -0700 Subject: [PATCH 67/91] wip: fix merge conflicts --- .../CompositionalMultiphaseHybridFVM.cpp | 31 +++++++++---------- ...ompositionalMultiphaseHybridFVMKernels.cpp | 4 +-- ...ompositionalMultiphaseHybridFVMKernels.hpp | 6 ++-- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 4 +-- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 80e9829f704..c8982cb4b68 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -77,9 +77,6 @@ void CompositionalMultiphaseHybridFVM::registerDataOnMesh( Group & meshBodies ) faceManager.registerField< flow::facePressure_n >( getName() ); - // precomputed mimetic gravity-driven trans coefficient on faces - faceManager.registerField< flow::mimeticTransGgradZ >( getName() ); - // Register the face data for global component fraction faceManager.registerField< flow::faceGlobalCompFraction >( getName() ); @@ -107,12 +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() ); + } ); } @@ -242,20 +238,22 @@ void CompositionalMultiphaseHybridFVM::precomputeData( MeshLevel & mesh, string_ 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 ) + 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() ); + nodeManager, + faceManager, + subRegion, + permeability, + lengthTolerance, + invSum.toView(), + count.toView() ); } ); // Reduce to effective value per face and write to field @@ -263,7 +261,8 @@ void CompositionalMultiphaseHybridFVM::precomputeData( MeshLevel & mesh, string_ arrayView1d< integer const > ghost = faceManager.ghostRank(); forAll< parallelDevicePolicy<> >( faceManager.size(), [=] GEOS_HOST_DEVICE ( localIndex const kf ) { - if( ghost[kf] >= 0 ) { + if( ghost[kf] >= 0 ) + { return; } real64 const s = invSum[kf]; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp index e3c7955c86d..3c164da1c6e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.cpp @@ -742,8 +742,8 @@ AssemblerKernelHelper:: real64 const T_ij = transMatrix[ifaceLoc][jfaceLoc]; // local mimetic coupling (i,j) gFlux_i += T_ij * gravCoefDif; } - integer const sign = integer(gFlux_i > 0.0) - integer(gFlux_i < 0.0); - + integer const sign = integer( gFlux_i > 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]]; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 2f0a4ec08d7..94d4ee33a76 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -1239,7 +1239,7 @@ struct PrecomputeMimeticTransGgradZKernel for( integer i = 0; i < NF; ++i ) { localIndex const kf = elemToFaces[ei][i]; - + real64 T_g_delta_z = 0.0; for( integer j = 0; j < NF; ++j ) { @@ -1247,7 +1247,7 @@ struct PrecomputeMimeticTransGgradZKernel 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{}, &faceInvSum[kf], 1.0 / LvArray::math::abs( T_g_delta_z ) ); RAJA::atomicAdd( parallelDeviceAtomic{}, &faceCount[kf], 1 ); } } ); @@ -1268,7 +1268,7 @@ struct PrecomputeMimeticTransGgradZKernel 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(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 653f7941cbb..117cdfca8a5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -752,8 +752,8 @@ AssemblerKernelHelper:: real64 const T_ij = transMatrix[ifaceLoc][jfaceLoc]; // local mimetic coupling (i,j) gFlux_i += T_ij * gravCoefDif; } - integer const sign = integer(gFlux_i > 0.0) - integer(gFlux_i < 0.0); - + integer const sign = integer( gFlux_i > 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]]; From a3d50911def1ce88269f3281375e2fba6353ca8b Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 30 Oct 2025 14:25:35 -0700 Subject: [PATCH 68/91] fix: rebaselines --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index f690dc3b864..1b81dfbde3c 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3880-14441-1132122 + baseline: integratedTests/baseline_integratedTests-pr3765-14502-dd8f391 allow_fail: all: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index a74b0fa7210..0dc5cb0742d 100644 --- a/BASELINE_NOTES.md +++ b/BASELINE_NOTES.md @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines. Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining. These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD). +PR #3765 (2025-10-30) +===================== +Adding boundary fields to handle Dirichlet conditions in compositional MFD. + PR #3880 (2025-10-13) ===================== Fix a bug introduced in #3485: mass that is used in accumulation term was not updated with porosity change after mechanics leading to always converged sequential outer loop. From c9a7242eb21ad2eab91a557ce4f2ba2c6e52b19f Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 30 Oct 2025 19:47:45 -0700 Subject: [PATCH 69/91] wip: rebase lined and adding complete instantiation of MDF kernels --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 6 + .../physicsSolvers/fluidFlow/CMakeLists.txt | 2 - ...haseHybridFVMKernels_assembly.cpp.template | 163 ------------- ...aseHybridFVMKernels_upwinding.cpp.template | 98 -------- .../physicsSolvers/fluidFlow/kernelSpecs.json | 50 ---- ...ltiphaseHybridFVMKernelsInstantiations.cpp | 226 +++++------------- 7 files changed, 64 insertions(+), 483 deletions(-) delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 3d9e32fee7a..084f4bfc9a9 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3849-14514-aaaf0f9 + baseline: integratedTests/baseline_integratedTests-pr3765-14543-498692f allow_fail: all: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index e70070b3746..c14da10239c 100644 --- a/BASELINE_NOTES.md +++ b/BASELINE_NOTES.md @@ -6,10 +6,16 @@ This file is designed to track changes to the integrated test baselines. Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining. These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD). +PR #3765 (2025-10-30) +===================== +Adding boundary fields to handle Dirichlet conditions in compositional MFD. + PR #3849 (2025-10-23) +===================== Add multiphase contact with wells PR #3880 (2025-10-13) +===================== Fix a bug introduced in #3485: mass that is used in accumulation term was not updated with porosity change after mechanics leading to always converged sequential outer loop. PR #3299 (2025-10-13) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index ca1a3e0745e..a12f17fa1c2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -163,8 +163,6 @@ set( kernelTemplateFileList "" ) # Keep only the templates that are unrelated to hybrid flux/dirichlet list( APPEND kernelTemplateFileList - CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template - CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template ReactiveCompositionalMultiphaseOBLKernels.cpp.template ) foreach( kernelTemplateFile ${kernelTemplateFileList} ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template deleted file mode 100644 index 6386db8345b..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_assembly.cpp.template +++ /dev/null @@ -1,163 +0,0 @@ -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp" - -namespace geos -{ -namespace compositionalMultiphaseHybridFVMKernels -{ - constexpr int NF = @NFACES@; - constexpr int NC = @NCOMPS@; - constexpr int NP = @NPHASES@; - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - AssemblerKernelHelper:: - applyGradient< NF, NC, NP >( arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceGravCoef, - arraySlice1d< localIndex const > const & elemToFaces, - real64 const & elemPres, - real64 const & elemGravCoef, - arraySlice1d< real64 const, constitutive::multifluid::USD_PHASE-2 > const & elemPhaseMassDens, - arraySlice2d< real64 const, constitutive::multifluid::USD_PHASE_DC-2 > const & dElemPhaseMassDens_dCompFrac, - arraySlice1d< real64 const, compflow::USD_PHASE-1 > const & elemPhaseMob, - arraySlice2d< real64 const, compflow::USD_PHASE_DC-1 > const & dElemPhaseMob, - arraySlice2d< real64 const, compflow::USD_COMP_DC-1 > const & dElemCompFrac_dCompDens, - arraySlice2d< real64 const > const & transMatrix, - real64 ( &oneSidedVolFlux )[ NF ], - real64 ( &dOneSidedVolFlux_dPres )[ NF ], - real64 ( &dOneSidedVolFlux_dFacePres )[ NF ][ NF ], - real64 ( &dOneSidedVolFlux_dCompDens )[ NF ][ NC ] ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - AssemblerKernelHelper:: - assembleFluxDivergence< NF, NC, NP >( localIndex const (&localIds)[ 3 ], - globalIndex const rankOffset, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - SortedArrayView< localIndex const > const & regionFilter, - arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< integer const > const & isBoundaryFace, - arrayView1d< real64 const > const & mimFaceGravCoef, - arraySlice1d< localIndex const > const & elemToFaces, - real64 const & elemGravCoef, - integer const useTotalMassEquation, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseDens, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseMassDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseMassDens, - ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - 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, - real64 const (&oneSidedVolFlux)[ NF ], - real64 const (&dOneSidedVolFlux_dPres)[ NF ], - real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], - real64 const (&dOneSidedVolFlux_dCompDens)[ NF ][ NC ], - real64 const & dt, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - AssemblerKernelHelper:: - assembleViscousFlux< NF, NC, NP >( localIndex const ifaceLoc, - real64 const (&oneSidedVolFlux)[ NF ], - real64 const (&dOneSidedVolFlux_dPres)[ NF ], - real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], - real64 const (&dOneSidedVolFlux_dCompDens)[ NF ][ NC ], - real64 const (&upwPhaseViscCoef)[ NP ][ NC ], - real64 const (&dUpwPhaseViscCoef_dPres)[ NP ][ NC ], - real64 const (&dUpwPhaseViscCoef_dCompDens)[ NP ][ NC ][ NC ], - globalIndex const elemDofNumber, - globalIndex const neighborDofNumber, - globalIndex const upwViscDofNumber, - real64 const & dt, - real64 ( &divMassFluxes )[ NC ], - real64 ( &dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ], - real64 ( &dDivMassFluxes_dFaceVars )[ NC ][ NF ], - globalIndex ( &dofColIndicesElemVars )[ (NC+1)*(NF+1) ] ); - @EXTERN@ - template - GEOS_HOST_DEVICE - void - AssemblerKernelHelper:: - assembleBuoyancyFlux< NF, NC, NP >( localIndex const ifaceLoc, - real64 const (&phaseGravTerm)[ NP ][ NP-1 ], - real64 const (&dPhaseGravTerm_dPres)[ NP ][ NP-1 ][ 2 ], - real64 const (&dPhaseGravTerm_dCompDens)[ NP ][ NP-1 ][ 2 ][ NC ], - real64 const (&upwPhaseGravCoef)[ NP ][ NP-1 ][ NC ], - real64 const (&dUpwPhaseGravCoef_dPres)[ NP ][ NP-1 ][ NC ][ 2 ], - real64 const (&dUpwPhaseGravCoef_dCompDens)[ NP ][ NP-1 ][ NC ][ 2 ][ NC ], - real64 const & dt, - real64 ( &divMassFluxes )[ NC ], - real64 ( &dDivMassFluxes_dElemVars )[ NC ][ (NC+1)*(NF+1) ] ); - @EXTERN@ - template - GEOS_HOST_DEVICE - void - AssemblerKernelHelper:: - assembleFaceConstraints< NF, NC >( arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< integer const > const & faceGhostRank, - arrayView1d< integer const > const & isBoundaryFace, - arraySlice1d< localIndex const > const & elemToFaces, - globalIndex const elemDofNumber, - globalIndex const rankOffset, - real64 const (&oneSidedVolFlux)[ NF ], - real64 const (&dOneSidedVolFlux_dPres)[ NF ], - real64 const (&dOneSidedVolFlux_dFacePres)[ NF ][ NF ], - real64 const (&dOneSidedVolFlux_dCompDens)[ NF ][ NC ], - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - AssemblerKernel:: - compute< NF, NC, NP >( localIndex const er, localIndex const esr, localIndex const ei, - SortedArrayView< localIndex const > const & regionFilter, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - arrayView1d< globalIndex const > const & faceDofNumber, - arrayView1d< integer const > const & faceGhostRank, - arrayView1d< integer const > const & isBoundaryFace, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceGravCoef, - arrayView1d< real64 const > const & mimFaceGravCoef, - arraySlice1d< localIndex const > const & elemToFaces, - real64 const & elemPres, - real64 const & elemGravCoef, - integer const useTotalMassEquation, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseDens, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseMassDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseMassDens, - ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - 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, - integer const elemGhostRank, - 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 ); - -} -} - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template deleted file mode 100644 index caa6b2405fe..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVMKernels_upwinding.cpp.template +++ /dev/null @@ -1,98 +0,0 @@ -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp" - -namespace geos -{ -namespace compositionalMultiphaseHybridFVMKernels -{ - constexpr int NC = @NCOMPS@; - constexpr int NP = @NPHASES@; - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - UpwindingHelper:: - upwindViscousCoefficient< NC, NP >( localIndex const (&localIds)[ 3 ], - localIndex const (&neighborIds)[ 3 ], - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseDens, - ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - 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, - real64 const & oneSidedVolFlux, - real64 ( &upwPhaseViscCoef )[ NP ][ NC ], - real64 ( &dUpwPhaseViscCoef_dPres )[ NP ][ NC ], - real64 ( &dUpwPhaseViscCoef_dCompDens )[ NP ][ NC ][ NC ], - globalIndex & upwViscDofNumber ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - UpwindingHelper:: - upwindBuoyancyCoefficient< NC, NP >( localIndex const (&localIds)[ 3 ], - localIndex const (&neighborIds)[ 3 ], - real64 const & transGravCoef, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseDens, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseMassDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseMassDens, - ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_COMP > > const & phaseCompFrac, - ElementViewConst< arrayView5d< real64 const, constitutive::multifluid::USD_PHASE_COMP_DC > > const & dPhaseCompFrac, - real64 ( &phaseGravTerm )[ NP ][ NP-1 ], - real64 ( &dPhaseGravTerm_dPres )[ NP ][ NP-1 ][ 2 ], - real64 ( &dPhaseGravTerm_dCompDens )[ NP ][ NP-1 ][ 2 ][ NC ], - real64 ( &upwPhaseGravCoef )[ NP ][ NP-1 ][ NC ], - real64 ( &dUpwPhaseGravCoef_dPres )[ NP ][ NP-1 ][ NC ][ 2 ], - real64 ( &dUpwPhaseGravCoef_dCompDens )[ NP ][ NP-1 ][ NC ][ 2 ][ NC ] ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - UpwindingHelper:: - computePhaseGravTerm< NC, NP >( localIndex const (&localIds)[ 3 ], - localIndex const (&neighborIds)[ 3 ], - real64 const & transGravCoef, - ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const & phaseMassDens, - ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const & dPhaseMassDens, - ElementViewConst< arrayView3d< real64 const, compflow::USD_COMP_DC > > const & dCompFrac_dCompDens, - real64 ( &phaseGravTerm )[ NP ][ NP-1 ], - real64 ( &dPhaseGravTerm_dPres )[ NP ][ NP-1 ][ 2 ], - real64 ( &dPhaseGravTerm_dCompDens )[ NP ][ NP-1 ][ 2 ][ NC ] ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - UpwindingHelper:: - computeUpwindedTotalMobility< NC, NP >( localIndex const (&localIds)[ 3 ], - localIndex const (&neighborIds)[ 3 ], - ElementViewConst< arrayView2d< real64 const, compflow::USD_PHASE > > const & phaseMob, - ElementViewConst< arrayView3d< real64 const, compflow::USD_PHASE_DC > > const & dPhaseMob, - real64 const (&phaseGravTerm)[ NP ][ NP-1 ], - real64 & totalMob, - real64 ( &dTotalMob_dPres )[ 2 ], - real64 ( &dTotalMob_dCompDens )[ 2 ][ NC ] ); - - @EXTERN@ - template - GEOS_HOST_DEVICE - void - UpwindingHelper:: - setIndicesForTotalMobilityUpwinding< NP >( localIndex const (&localIds)[ 3 ], - localIndex const (&neighborIds)[ 3 ], - real64 const (&gravTerm)[ NP ][ NP-1 ], - localIndex ( &totalMobIds )[ NP ][ 3 ], - localIndex ( &totalMobPos )[ NP ] ); - -} -} - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json index fcaf45e21c2..f80c23861e4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernelSpecs.json @@ -24,56 +24,6 @@ "generation call). Duplicate entries are unified internally" ] }, - "CompositionalMultiphaseHybridFVMKernels_upwinding": { - "vars": [ - "NCOMPS", - "NPHASES" - ], - "constants": [], - "combinations": { - "NCOMPS": [ - 1, - 2, - 3, - 4, - 5 - ], - "NPHASES": [ - 2, - 3 - ] - }, - "explicit": [] - }, - - "CompositionalMultiphaseHybridFVMKernels_assembly": { - "vars": [ - "NFACES", - "NCOMPS", - "NPHASES" - ], - "constants": [], - "combinations": { - "NFACES": [ - 4, - 5, - 6 - ], - "NCOMPS": [ - 1, - 2, - 3, - 4, - 5 - ], - "NPHASES": [ - 2, - 3 - ] - }, - "explicit": [] - }, - "ReactiveCompositionalMultiphaseOBLKernels": { "vars": [ "NAME", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp index b755757a75c..351724f9478 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp @@ -41,7 +41,14 @@ namespace compositionalMultiphaseHybridFVMKernels #define GEOS_NFACES_LIST \ X_NF( 4 ) \ X_NF( 5 ) \ - X_NF( 6 ) + X_NF( 6 ) \ + X_NF( 7 ) \ + X_NF( 8 ) \ + X_NF( 9 ) \ + X_NF( 10 ) \ + X_NF( 11 ) \ + X_NF( 12 ) \ + X_NF( 13 ) // ----------------------------------------------------------------------------- // Common parameter macros (kept in sync with kernel signatures) @@ -178,180 +185,61 @@ GEOS_NFACES_LIST #undef INSTANTIATE_FLUX_FOR_NP #undef INSTANTIATE_FLUX_FOR_NC #undef INSTANTIATE_FLUX_FOR_NF -#undef GEOS_NFACES_LIST // ----------------------------------------------------------------------------- // evaluateBCFaceProperties explicit instantiations // ----------------------------------------------------------------------------- -template void -evaluateBCFaceProperties< 1, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); +#define INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES( NC, NP ) \ + template void evaluateBCFaceProperties< NC, NP >( \ + integer const numPhases, \ + SortedArrayView< localIndex const > const & boundaryFaceSet, \ + arrayView1d< real64 const > const & facePres, \ + arrayView1d< real64 const > const & faceTemp, \ + arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, \ + arrayView2d< localIndex const > const & elemRegionList, \ + arrayView2d< localIndex const > const & elemSubRegionList, \ + arrayView2d< localIndex const > const & elemList, \ + localIndex const er, \ + localIndex const esr, \ + constitutive::MultiFluidBase & fluid, \ + constitutive::RelativePermeabilityBase & relperm, \ + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, \ + arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, \ + arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); + +#define INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NP( NC, NP ) \ + INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES( NC, NP ) + +#define INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC( NC ) \ + INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NP( NC, 2 ) \ + INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NP( NC, 3 ) + +INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC( 1 ) +INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC( 2 ) +INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC( 3 ) +INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC( 4 ) +INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC( 5 ) -template void -evaluateBCFaceProperties< 2, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 3, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 4, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 5, 2 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 1, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 2, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 3, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); - -template void -evaluateBCFaceProperties< 4, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); +// Cleanup local helper macros +#undef INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES +#undef INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NP +#undef INSTANTIATE_EVALUATE_BC_FACE_PROPERTIES_FOR_NC -template void -evaluateBCFaceProperties< 5, 3 >( integer const numPhases, - SortedArrayView< localIndex const > const & boundaryFaceSet, - arrayView1d< real64 const > const & facePres, - arrayView1d< real64 const > const & faceTemp, - arrayView2d< real64 const, compflow::USD_COMP > const & faceCompFrac, - arrayView2d< localIndex const > const & elemRegionList, - arrayView2d< localIndex const > const & elemSubRegionList, - arrayView2d< localIndex const > const & elemList, - localIndex const er, - localIndex const esr, - constitutive::MultiFluidBase & fluid, - constitutive::RelativePermeabilityBase & relperm, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMob, - arrayView2d< real64, compflow::USD_PHASE > const & facePhaseMassDens, - arrayView3d< real64, compflow::USD_PHASE_COMP > const & facePhaseCompFrac ); +// ----------------------------------------------------------------------------- +// NOTE: Explicit instantiations for AssemblerKernelHelper and AssemblerKernel +// functions are NOT included here because they are declared as 'inline' in +// CompositionalMultiphaseHybridFVMKernels_impl.hpp. Inline template functions +// are automatically instantiated at the point of use and cannot be explicitly +// instantiated. +// +// The following functions are inline and therefore auto-instantiated: +// - AssemblerKernelHelper::applyGradient +// - AssemblerKernelHelper::assembleFluxDivergence +// - AssemblerKernelHelper::assembleViscousFlux +// - AssemblerKernelHelper::assembleBuoyancyFlux +// - AssemblerKernelHelper::assembleFaceConstraints +// - AssemblerKernel::compute +// ----------------------------------------------------------------------------- #endif // GEOS_ENABLE_MANUAL_HYBRID_FVM_INST From 6949133ab598cb6aacaae62e069c404e9896753c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 30 Oct 2025 20:10:37 -0700 Subject: [PATCH 70/91] wip: complete selector by number of facets --- .../CompositionalMultiphaseHybridFVM.cpp | 14 ++++++++++ ...ompositionalMultiphaseHybridFVMKernels.hpp | 28 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 3ff037f47da..e832205d88e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -862,6 +862,20 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n launchKernel( IP_TAG, std::integral_constant< integer, 5 >{} ); else if( numFacesPerElement == 6 ) launchKernel( IP_TAG, std::integral_constant< integer, 6 >{} ); + else if( numFacesPerElement == 7 ) + launchKernel( IP_TAG, std::integral_constant< integer, 7 >{} ); + else if( numFacesPerElement == 8 ) + launchKernel( IP_TAG, std::integral_constant< integer, 8 >{} ); + else if( numFacesPerElement == 9 ) + launchKernel( IP_TAG, std::integral_constant< integer, 9 >{} ); + else if( numFacesPerElement == 10 ) + launchKernel( IP_TAG, std::integral_constant< integer, 10 >{} ); + else if( numFacesPerElement == 11 ) + launchKernel( IP_TAG, std::integral_constant< integer, 11 >{} ); + else if( numFacesPerElement == 12 ) + launchKernel( IP_TAG, std::integral_constant< integer, 12 >{} ); + else if( numFacesPerElement == 13 ) + launchKernel( IP_TAG, std::integral_constant< integer, 13 >{} ); else GEOS_ERROR( "Unsupported number of faces per element: " << numFacesPerElement ); }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 498dfa0c6b8..36238b3f902 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -1245,6 +1245,34 @@ void kernelLaunchSelectorFaceSwitch( T value, LAMBDA && lambda ) { 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 ); } From c7a12b401b250b990982ac1510d7874c4cbc9596 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 30 Oct 2025 20:13:56 -0700 Subject: [PATCH 71/91] wip: testing general meshes for MFD compositional --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index aee44fac1be..3161337c3c4 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -365,7 +365,9 @@ INSTANTIATE_TEST_SUITE_P( CompositionalTPFAIntegrationTest, ::testing::Values( "polyhedral_voronoi_regular.vtu", - "hex_pyr_tet_nested_mixed.vtu" + "hex_pyr_tet_nested_mixed.vtu", + "polyhedral_voronoi_lattice.vtu", + "polyhedral_voronoi_complex.vtu" ) ); @@ -447,7 +449,9 @@ INSTANTIATE_TEST_SUITE_P( CompositionalMFDTPFAIntegrationTest, ::testing::Values( "polyhedral_voronoi_regular.vtu", - "hex_pyr_tet_nested_mixed.vtu" + "hex_pyr_tet_nested_mixed.vtu", + "polyhedral_voronoi_lattice.vtu", + "polyhedral_voronoi_complex.vtu" ) ); @@ -512,7 +516,9 @@ INSTANTIATE_TEST_SUITE_P( CompositionalTPFAvsMFDTPFA, ::testing::Values( "polyhedral_voronoi_regular.vtu", - "hex_pyr_tet_nested_mixed.vtu" + "hex_pyr_tet_nested_mixed.vtu", + "polyhedral_voronoi_lattice.vtu", + "polyhedral_voronoi_complex.vtu" ) ); @@ -639,7 +645,9 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Combine( ::testing::Values( "polyhedral_voronoi_regular.vtu", - "hex_pyr_tet_nested_mixed.vtu" + "hex_pyr_tet_nested_mixed.vtu", + "polyhedral_voronoi_lattice.vtu", + "polyhedral_voronoi_complex.vtu" ), ::testing::Values( INNER_quasiTPFA, From 106b23f8e1d1f4d96f750ef8551365b8414e86cf Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 30 Oct 2025 20:21:43 -0700 Subject: [PATCH 72/91] Update testCompositionalMultiPhaseMFDPolyhedral.cpp --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index 3161337c3c4..fff74f0bfd8 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -33,8 +33,8 @@ using namespace geos::testing; CommandLineOptions g_commandLineOptions; // Pressure L2 error tolerance -static constexpr real64 PRESSURE_L2_TOLERANCE = 1.0e-10; -static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-10; +static constexpr real64 PRESSURE_L2_TOLERANCE = 1.0e-7; +static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-7; // Single time step static constexpr real64 TIME_STEP = 1.0e-2; // 0.01 @@ -60,7 +60,7 @@ static std::string generateXmlInputCompTPFA( std::string const & meshFile ) useMass="1" temperature="300"> Date: Thu, 30 Oct 2025 21:47:37 -0700 Subject: [PATCH 73/91] fix: generateXmlInputCompMFD - it initializes face pressure but NOT face component fractions --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index fff74f0bfd8..ba9ff87a55b 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -286,6 +286,17 @@ static std::string generateXmlInputCompMFD( std::string const & innerProductType + + + + + + + + From cceaa213e704d65a317352220f2867c6c8e926e1 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 31 Oct 2025 17:11:38 -0700 Subject: [PATCH 74/91] Update src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp Co-authored-by: Nicola Castelletto <38361926+castelletto1@users.noreply.github.com> --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index ba9ff87a55b..bf048bcfb97 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -328,10 +328,10 @@ static std::string generateXmlInputCompMFD( std::string const & innerProductType } // Helper: copy arrayView1d to std::vector -static inline std::vector< real64 > arrayViewToVector( arrayView1d< real64 const > & arr, localIndex n ) +static inline std::vector< real64 > arrayViewToVector( arrayView1d< real64 const > & arr ) { arr.move( hostMemorySpace, false ); - return std::vector< real64 >( arr.data(), arr.data() + n ); + return std::vector< real64 >( arr.data(), arr.data() + arr.size() ); } // Helper: copy a 2D view to flat vector (row-major by phase index), accept any 2D view type From dedbdf165f7b661b9ec4317fccc731bfcaed33d2 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 31 Oct 2025 17:11:57 -0700 Subject: [PATCH 75/91] Update src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp Co-authored-by: Nicola Castelletto <38361926+castelletto1@users.noreply.github.com> --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index bf048bcfb97..379e2362558 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -336,9 +336,11 @@ static inline std::vector< real64 > arrayViewToVector( arrayView1d< real64 const // Helper: copy a 2D view to flat vector (row-major by phase index), accept any 2D view type template< typename View2D > -static inline std::vector< real64 > arrayView2dToVector( View2D & arr, localIndex nCells, localIndex nCols ) +static inline std::vector< real64 > arrayView2dToVector( View2D & arr ) { arr.move( hostMemorySpace, false ); + localIndex nCells = arr.size( 0 ); + localIndex nCols = arr.size( 1 ); std::vector< real64 > out; out.reserve( static_cast< size_t >( nCells ) * static_cast< size_t >( nCols ) ); for( localIndex i = 0; i < nCells; ++i ) From 54900ceb515be933dd6b84fb839fdbe957ef9891 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 31 Oct 2025 17:13:20 -0700 Subject: [PATCH 76/91] Update src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp Co-authored-by: Nicola Castelletto <38361926+castelletto1@users.noreply.github.com> --- ...stCompositionalMultiPhaseMFDPolyhedral.cpp | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index 379e2362558..67a508af7e2 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -694,21 +694,25 @@ TEST_P( CompositionalMFDNonTPFAExactnessTest, PressureFieldL2ErrorExact ) arrayView1d< real64 const > volumes = subRegion.getElementVolume(); arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredPressureError_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredExactPressure_ReduceSum( 0.0 ); localIndex const n_cells = subRegion.size(); forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; + real64 const x = centers[i][0]; + real64 const cellVolume = volumes[i]; + real64 const pNumeric = p_h[i]; + real64 const pExact = 2.0 * (1.0 - x) + 1.0 * x; + squaredPressureError_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * cellVolume; + squaredExactPressure_ReduceSum += pExact * pExact * cellVolume; } ); - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; +// Gather global reductions +real64 const squaredPressureError = squaredPressureError_ReduceSum.get(); +real64 const squaredExactPressure = squaredExactPressure_ReduceSum.get(); + +// Compute pressure relative L2 error +real64 const normalizedL2Error = std::sqrt(squaredPressureError) / std::sqrt(squaredExactPressure); // Expect exact solution for these inner products on both meshes EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); From a3743bc9e04943ed1234048544615947416b0d68 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 31 Oct 2025 17:14:02 -0700 Subject: [PATCH 77/91] Update testCompositionalMultiPhaseMFDPolyhedral.cpp --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index ba9ff87a55b..94898a3ce13 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -32,7 +32,7 @@ using namespace geos::testing; CommandLineOptions g_commandLineOptions; -// Pressure L2 error tolerance +// Pressure and saturation L2 error tolerances static constexpr real64 PRESSURE_L2_TOLERANCE = 1.0e-7; static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-7; @@ -43,7 +43,7 @@ static constexpr auto INNER_TPFA = "TPFA"; static constexpr auto INNER_quasiTPFA = "quasiTPFA"; static constexpr auto INNER_BDVLM = "beiraoDaVeigaLipnikovManzini"; -// Generate XML for compositional multiphase FV-TPFA (simplified from user-provided template) +// Generate XML for compositional multiphase FV-TPFA (simplified from the user-provided template) static std::string generateXmlInputCompTPFA( std::string const & meshFile ) { std::ostringstream oss; @@ -334,7 +334,7 @@ static inline std::vector< real64 > arrayViewToVector( arrayView1d< real64 const return std::vector< real64 >( arr.data(), arr.data() + n ); } -// Helper: copy a 2D view to flat vector (row-major by phase index), accept any 2D view type +// Helper: copy a 2D view to flat vector (row-major by phase index), accepts any 2D view type template< typename View2D > static inline std::vector< real64 > arrayView2dToVector( View2D & arr, localIndex nCells, localIndex nCols ) { @@ -626,7 +626,7 @@ TEST_P( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) } } -// MFD non-TPFA inner products: check linear pressure profile is exact on both meshes +// MFD non-TPFA inner products: check linear pressure profile is exact on all meshes class CompositionalMFDNonTPFAExactnessTest : public ::testing::TestWithParam< std::tuple< const char *, const char * > > { public: From dfe87d91d7cd6dd366a4b2fae84707320cfafada Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 31 Oct 2025 17:23:30 -0700 Subject: [PATCH 78/91] Update testCompositionalMultiPhaseMFDPolyhedral.cpp --- ...stCompositionalMultiPhaseMFDPolyhedral.cpp | 107 +++++++----------- 1 file changed, 39 insertions(+), 68 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index fe5bb378e19..4d8836be3c6 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -353,6 +353,37 @@ static inline std::vector< real64 > arrayView2dToVector( View2D & arr ) return out; } +// Helper: compute normalized L2 error for linear pressure profile p(x) = 2*(1-x) + x = 2 - x +static inline real64 computeNormalizedPressureL2Error( CellElementSubRegion & subRegion ) +{ + arrayView2d< real64 const > centers = subRegion.getElementCenter(); + arrayView1d< real64 const > volumes = subRegion.getElementVolume(); + arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredPressureError_ReduceSum( 0.0 ); + RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredExactPressure_ReduceSum( 0.0 ); + localIndex const n_cells = subRegion.size(); + + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) + { + real64 const x = centers[i][0]; + real64 const cellVolume = volumes[i]; + real64 const pNumeric = p_h[i]; + real64 const pExact = 2.0 * (1.0 - x) + 1.0 * x; + squaredPressureError_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * cellVolume; + squaredExactPressure_ReduceSum += pExact * pExact * cellVolume; + } ); + + // Gather global reductions + real64 const squaredPressureError = squaredPressureError_ReduceSum.get(); + real64 const squaredExactPressure = squaredExactPressure_ReduceSum.get(); + + // Compute pressure relative L2 error + real64 const normalizedL2Error = std::sqrt( squaredPressureError ) / std::sqrt( squaredExactPressure ); + + return normalizedL2Error; +} + // TPFA test: check linear pressure profile on regular polyhedral mesh class CompositionalTPFAIntegrationTest : public ::testing::TestWithParam< const char * > { @@ -405,25 +436,7 @@ TEST_P( CompositionalTPFAIntegrationTest, PressureFieldL2Error ) MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) - { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; - } ); - - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; + real64 l2Error = computeNormalizedPressureL2Error( subRegion ); // Expect exact solution only on the k-orthogonal regular mesh; expect non-zero error on mixed mesh std::string meshFile = GetParam(); @@ -489,25 +502,7 @@ TEST_P( CompositionalMFDTPFAIntegrationTest, PressureFieldL2Error ) MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > l2Error_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > totalVolume_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) - { - real64 x = centers[i][0]; - real64 volume = volumes[i]; - real64 pNumeric = p_h[i]; - real64 pExact = 2.0 * (1.0 - x) + 1.0 * x; - l2Error_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * volume; - totalVolume_ReduceSum += volume; - } ); - - real64 const data[2] = { l2Error_ReduceSum.get(), totalVolume_ReduceSum.get() }; - real64 l2Error = std::sqrt( data[0] ) / data[1]; + real64 l2Error = computeNormalizedPressureL2Error( subRegion ); // Expect exact solution only on the k-orthogonal regular mesh; expect non-zero error on mixed mesh std::string meshFile = GetParam(); @@ -570,11 +565,10 @@ TEST_P( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); - n_cells_tpfa = subRegion.size(); - p_tpfa = arrayViewToVector( p_h, n_cells_tpfa ); + p_tpfa = arrayViewToVector( p_h ); auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); - sat_tpfa = arrayView2dToVector( sat, n_cells_tpfa, n_phases_tpfa ); + sat_tpfa = arrayView2dToVector( sat ); } // --- Run MFD solver (innerProductType = TPFA) --- @@ -602,11 +596,10 @@ TEST_P( CompositionalTPFAvsMFDTPFA, PressureAndSaturationComparison ) CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); arrayView1d< real64 const > p_h = subRegion.getField< fields::flow::pressure >(); - n_cells_mfd = subRegion.size(); - p_mfd = arrayViewToVector( p_h, n_cells_mfd ); + p_mfd = arrayViewToVector( p_h ); auto sat = subRegion.getField< fields::flow::phaseVolumeFraction >(); - sat_mfd = arrayView2dToVector( sat, n_cells_mfd, n_phases_mfd ); + sat_mfd = arrayView2dToVector( sat ); } ASSERT_EQ( n_cells_tpfa, n_cells_mfd ); @@ -690,32 +683,10 @@ TEST_P( CompositionalMFDNonTPFAExactnessTest, PressureFieldL2ErrorExact ) MeshLevel & mesh = domain.getMeshBody( 0 ).getBaseDiscretization(); CellElementSubRegion & subRegion = mesh.getElemManager().getRegion( 0 ).getSubRegion< CellElementSubRegion >( 0 ); - arrayView2d< real64 const > centers = subRegion.getElementCenter(); - arrayView1d< real64 const > volumes = subRegion.getElementVolume(); - arrayView1d< real64 const > const p_h = subRegion.getField< fields::flow::pressure >(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredPressureError_ReduceSum( 0.0 ); - RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredExactPressure_ReduceSum( 0.0 ); - localIndex const n_cells = subRegion.size(); - forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) - { - real64 const x = centers[i][0]; - real64 const cellVolume = volumes[i]; - real64 const pNumeric = p_h[i]; - real64 const pExact = 2.0 * (1.0 - x) + 1.0 * x; - squaredPressureError_ReduceSum += (pNumeric - pExact) * (pNumeric - pExact) * cellVolume; - squaredExactPressure_ReduceSum += pExact * pExact * cellVolume; - } ); - -// Gather global reductions -real64 const squaredPressureError = squaredPressureError_ReduceSum.get(); -real64 const squaredExactPressure = squaredExactPressure_ReduceSum.get(); - -// Compute pressure relative L2 error -real64 const normalizedL2Error = std::sqrt(squaredPressureError) / std::sqrt(squaredExactPressure); + real64 const normalizedL2Error = computeNormalizedPressureL2Error( subRegion ); // Expect exact solution for these inner products on both meshes - EXPECT_NEAR( l2Error, 0.0, PRESSURE_L2_TOLERANCE ); + EXPECT_NEAR( normalizedL2Error, 0.0, PRESSURE_L2_TOLERANCE ); } int main( int argc, char * * argv ) From 393e562db90f3adbe8660e92497dff35ada6d048 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 31 Oct 2025 17:36:35 -0700 Subject: [PATCH 79/91] Update testCompositionalMultiPhaseMFDPolyhedral.cpp --- .../testCompositionalMultiPhaseMFDPolyhedral.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp index 4d8836be3c6..8dfd432d91a 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testCompositionalMultiPhaseMFDPolyhedral.cpp @@ -33,8 +33,8 @@ using namespace geos::testing; CommandLineOptions g_commandLineOptions; // Pressure and saturation L2 error tolerances -static constexpr real64 PRESSURE_L2_TOLERANCE = 1.0e-7; -static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-7; +static constexpr real64 PRESSURE_L2_TOLERANCE = 1.0e-8; +static constexpr real64 SATURATION_L2_TOLERANCE = 1.0e-8; // Single time step static constexpr real64 TIME_STEP = 1.0e-2; // 0.01 @@ -363,7 +363,7 @@ static inline real64 computeNormalizedPressureL2Error( CellElementSubRegion & su RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredPressureError_ReduceSum( 0.0 ); RAJA::ReduceSum< parallelDeviceReduce, real64 > squaredExactPressure_ReduceSum( 0.0 ); localIndex const n_cells = subRegion.size(); - + forAll< geos::parallelDevicePolicy<> >( n_cells, [=] GEOS_HOST_DEVICE ( localIndex const i ) { real64 const x = centers[i][0]; @@ -380,7 +380,7 @@ static inline real64 computeNormalizedPressureL2Error( CellElementSubRegion & su // Compute pressure relative L2 error real64 const normalizedL2Error = std::sqrt( squaredPressureError ) / std::sqrt( squaredExactPressure ); - + return normalizedL2Error; } From 8d7fab636902b6ea83325d30a14f4870a18240c0 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 2 Nov 2025 16:05:12 -0800 Subject: [PATCH 80/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 623d9c8d852..eb1fa4987d9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1744,6 +1744,22 @@ evaluateBCFaceProperties( integer const numPhases, StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); + + // Initialize all temporary arrays to zero to ensure deterministic behavior on GPU + for( integer ip = 0; ip < numPhases; ++ip ) + { + facePhaseFrac[0][0][ip] = 0.0; + facePhaseDens[0][0][ip] = 0.0; + facePhaseMassDensLocal[0][0][ip] = 0.0; + facePhaseVisc[0][0][ip] = 0.0; + facePhaseEnthalpy[0][0][ip] = 0.0; + facePhaseInternalEnergy[0][0][ip] = 0.0; + for( integer ic = 0; ic < NC; ++ic ) + { + facePhaseCompFracLocal[0][0][ip][ic] = 0.0; + } + } + real64 faceTotalDens = 0.0; // Evaluate fluid properties at BC face conditions using flash calculation @@ -1772,7 +1788,8 @@ evaluateBCFaceProperties( integer const numPhases, // Compute mobility from relative permeability evaluated at face conditions real64 const faceKr = facePhaseFrac[0][0][ip]; // phaseRelPerm[eiAdj][0][ip]; real64 const mu = facePhaseVisc[0][0][ip]; - facePhaseMob[kf][ip] = (mu > 0) ? faceTotalDens * faceKr / mu : 0.0; + // Safety check: ensure faceTotalDens and mu are valid before computing mobility + facePhaseMob[kf][ip] = (mu > 0 && faceTotalDens > 0) ? faceTotalDens * faceKr / mu : 0.0; // Store phase composition from flash calculation for( integer ic = 0; ic < NC; ++ic ) From aded73cbdc8eaee9f939a1bd1d5e8ec9306a833f Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Sun, 2 Nov 2025 16:31:19 -0800 Subject: [PATCH 81/91] Update CompositionalMultiphaseHybridFVMKernels_impl.hpp --- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index eb1fa4987d9..d514bb1c68f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1744,7 +1744,7 @@ evaluateBCFaceProperties( integer const numPhases, StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); - + // Initialize all temporary arrays to zero to ensure deterministic behavior on GPU for( integer ip = 0; ip < numPhases; ++ip ) { @@ -1759,7 +1759,7 @@ evaluateBCFaceProperties( integer const numPhases, facePhaseCompFracLocal[0][0][ip][ic] = 0.0; } } - + real64 faceTotalDens = 0.0; // Evaluate fluid properties at BC face conditions using flash calculation From 7bf45fc42e6d12af0d857f50d9df146c0a361086 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 3 Nov 2025 07:56:10 -0800 Subject: [PATCH 82/91] fix: run evaluateBCFaceProperties with parallelDevicePolicy --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 3 +++ .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index e832205d88e..63816ef1d11 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -793,6 +793,9 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView3d< real64 const, compflow::USD_PHASE_COMP > const facePhaseCompFracField = faceManager.getField< flow::facePhaseCompFraction >(); + // Note: Face properties are computed on device by evaluateBCFaceProperties using parallelDevicePolicy, + // so no host-to-device memory synchronization is needed before launching DirichletFluxKernel + // Apply Dirichlet boundary fluxes for each face set using DirichletFluxKernel for( string const & setName : bcFaceSets ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index d514bb1c68f..bcbac83354e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1718,7 +1718,8 @@ evaluateBCFaceProperties( integer const numPhases, GEOS_UNUSED_VAR( relPermWrapper ); // Loop over BC faces and evaluate properties at BC conditions - forAll< serialPolicy >( boundaryFaceSet.size(), [=, &facePhaseMob, &facePhaseMassDens, &facePhaseCompFrac] ( localIndex const iset ) + // Run on device to match DirichletFluxKernel policy and avoid host-device memory synchronization + forAll< parallelDevicePolicy<> >( boundaryFaceSet.size(), [=] GEOS_DEVICE ( localIndex const iset ) { localIndex const kf = boundaryFaceSet[iset]; From 60e9849898ebfb7af4c7562e4d970e6a00f5fbad Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 3 Nov 2025 08:17:35 -0800 Subject: [PATCH 83/91] fix: run evaluateBCFaceProperties with serialPolicy --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 8 ++++++-- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 63816ef1d11..4ced555bf44 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -793,8 +793,12 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView3d< real64 const, compflow::USD_PHASE_COMP > const facePhaseCompFracField = faceManager.getField< flow::facePhaseCompFraction >(); - // Note: Face properties are computed on device by evaluateBCFaceProperties using parallelDevicePolicy, - // so no host-to-device memory synchronization is needed before launching DirichletFluxKernel + // Move face property arrays to device memory after they were computed on host + // evaluateBCFaceProperties uses serialPolicy (host) because CUDA doesn't allow extended device lambdas inside generic lambdas + // DirichletFluxKernel uses parallelDevicePolicy (device), so explicit synchronization is required + facePhaseMobField.move( parallelDeviceMemorySpace, false ); + facePhaseMassDensField.move( parallelDeviceMemorySpace, false ); + facePhaseCompFracField.move( parallelDeviceMemorySpace, false ); // Apply Dirichlet boundary fluxes for each face set using DirichletFluxKernel for( string const & setName : bcFaceSets ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index bcbac83354e..725cb463938 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1718,8 +1718,9 @@ evaluateBCFaceProperties( integer const numPhases, GEOS_UNUSED_VAR( relPermWrapper ); // Loop over BC faces and evaluate properties at BC conditions - // Run on device to match DirichletFluxKernel policy and avoid host-device memory synchronization - forAll< parallelDevicePolicy<> >( boundaryFaceSet.size(), [=] GEOS_DEVICE ( localIndex const iset ) + // Note: Using serialPolicy (host) because extended device lambdas cannot be defined inside generic lambdas + // The output arrays will be moved to device after this completes + forAll< serialPolicy >( boundaryFaceSet.size(), [=, &facePhaseMob, &facePhaseMassDens, &facePhaseCompFrac] ( localIndex const iset ) { localIndex const kf = boundaryFaceSet[iset]; From bb9a6b854eed5c8f192fa6516e8961d0b56bb29c Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 3 Nov 2025 08:37:09 -0800 Subject: [PATCH 84/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../CompositionalMultiphaseHybridFVM.cpp | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 4ced555bf44..0ca6c8d7087 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -184,6 +184,25 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou ": the transmissibility multipliers used in SinglePhaseHybridFVM must strictly larger than 0.0", std::runtime_error ); + // Initialize face-based constitutive property arrays to zero to prevent uninitialized memory usage on GPU + arrayView2d< real64, compflow::USD_PHASE > facePhaseMob = faceManager.getField< flow::facePhaseMobility >(); + arrayView2d< real64, compflow::USD_PHASE > facePhaseMassDens = faceManager.getField< flow::facePhaseMassDensity >(); + arrayView3d< real64, compflow::USD_PHASE_COMP > facePhaseCompFrac = faceManager.getField< flow::facePhaseCompFraction >(); + + localIndex const numFaces = faceManager.size(); + forAll< parallelDevicePolicy<> >( numFaces, [=] GEOS_HOST_DEVICE ( localIndex const iface ) + { + for( integer ip = 0; ip < facePhaseMob.size( 1 ); ++ip ) + { + facePhaseMob[iface][ip] = 0.0; + facePhaseMassDens[iface][ip] = 0.0; + for( integer ic = 0; ic < facePhaseCompFrac.size( 2 ); ++ic ) + { + facePhaseCompFrac[iface][ip][ic] = 0.0; + } + } + } ); + // Mark boundary faces (faces with Dirichlet BCs) to skip flux continuity constraint // Initialize all faces as interior (0), then mark boundary faces (1) arrayView1d< integer > const isBoundaryFaceView = faceManager.getReference< array1d< integer > >( flow::isBoundaryFace::key() ); @@ -739,6 +758,11 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView3d< real64, compflow::USD_PHASE_COMP > facePhaseCompFrac = faceManager.getField< flow::facePhaseCompFraction >(); + // Move arrays to host memory before evaluateBCFaceProperties runs with serialPolicy + facePhaseMob.move( hostMemorySpace, true ); + facePhaseMassDens.move( hostMemorySpace, true ); + facePhaseCompFrac.move( hostMemorySpace, true ); + // Evaluate constitutive properties at BC face conditions for each face set for( string const & setName : bcFaceSets ) { @@ -785,7 +809,14 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n } ); } - // Get pre-computed fluid properties at BC faces + // 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 ); + facePhaseCompFrac.move( parallelDeviceMemorySpace, false ); + + // Get const views to the face properties for use in DirichletFluxKernel arrayView2d< real64 const, compflow::USD_PHASE > const facePhaseMobField = faceManager.getField< flow::facePhaseMobility >(); arrayView2d< real64 const, compflow::USD_PHASE > const facePhaseMassDensField = @@ -793,13 +824,6 @@ void CompositionalMultiphaseHybridFVM::applyFaceDirichletBC( real64 const time_n arrayView3d< real64 const, compflow::USD_PHASE_COMP > const facePhaseCompFracField = faceManager.getField< flow::facePhaseCompFraction >(); - // Move face property arrays to device memory after they were computed on host - // evaluateBCFaceProperties uses serialPolicy (host) because CUDA doesn't allow extended device lambdas inside generic lambdas - // DirichletFluxKernel uses parallelDevicePolicy (device), so explicit synchronization is required - facePhaseMobField.move( parallelDeviceMemorySpace, false ); - facePhaseMassDensField.move( parallelDeviceMemorySpace, false ); - facePhaseCompFracField.move( parallelDeviceMemorySpace, false ); - // Apply Dirichlet boundary fluxes for each face set using DirichletFluxKernel for( string const & setName : bcFaceSets ) { From a642f32c6ddd7ea044a1afeb8351584c88cee92a Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 3 Nov 2025 09:01:17 -0800 Subject: [PATCH 85/91] doc: improving documentation --- .../CompositionalMultiphaseHybridFVM.cpp | 6 +-- .../CompositionalMultiphaseHybridFVM.hpp | 4 +- ...ompositionalMultiphaseHybridFVMKernels.hpp | 16 ++++++-- ...itionalMultiphaseHybridFVMKernels_impl.hpp | 40 ++++++++++--------- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 0ca6c8d7087..7f09e3e576f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -1,4 +1,4 @@ -/* +.md file/* * ------------------------------------------------------------------------------------------------------------ * SPDX-License-Identifier: LGPL-2.1-only * @@ -181,14 +181,14 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou GEOS_THROW_IF( minVal.get() <= 0.0, getCatalogName() << " " << getDataContext() << - ": the transmissibility multipliers used in SinglePhaseHybridFVM must strictly larger than 0.0", + ": the transmissibility multipliers used in SinglePhaseHybridFVM must be strictly larger than 0.0", std::runtime_error ); // Initialize face-based constitutive property arrays to zero to prevent uninitialized memory usage on GPU arrayView2d< real64, compflow::USD_PHASE > facePhaseMob = faceManager.getField< flow::facePhaseMobility >(); arrayView2d< real64, compflow::USD_PHASE > facePhaseMassDens = faceManager.getField< flow::facePhaseMassDensity >(); arrayView3d< real64, compflow::USD_PHASE_COMP > facePhaseCompFrac = faceManager.getField< flow::facePhaseCompFraction >(); - + localIndex const numFaces = faceManager.size(); forAll< parallelDevicePolicy<> >( numFaces, [=] GEOS_HOST_DEVICE ( localIndex const iface ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp index fc4c01c981f..38976e66374 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.hpp @@ -192,10 +192,10 @@ class CompositionalMultiphaseHybridFVM : public CompositionalMultiphaseBase private: - /// tolerance used in the computation of the transmissibility matrix + /// Tolerance used in the computation of the transmissibility matrix (typically domain_length * 1e-8) real64 m_lengthTolerance; - /// region filter used in flux assembly + /// Set of region indices that are targeted by this solver (used to filter flux assembly) SortedArray< localIndex > m_regionFilter; }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 36238b3f902..d713a3d0a7e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -68,7 +68,7 @@ struct UpwindingHelper /** * @brief At a given one-sided face, compute the upwind viscous transport coefficient * @param[in] localIds region, subRegion, and element indices of the local element - * @param[in] neighborIds region, subRegion, and element indices of the neigbhbor element + * @param[in] neighborIds region, subRegion, and element indices of the neighbor element * @param[in] phaseDens the phase densities in the domain (non-local) * @param[in] dPhaseDens the derivatives of the phase densities in the domain wrt pressure and component fractions (non-local) * @param[in] phaseMob the phase mobilities in the domain (non-local) @@ -106,7 +106,7 @@ struct UpwindingHelper /** * @brief At a given one-sided face, compute the upwind viscous transport coefficient * @param[in] localIds region, subRegion, and element indices of the local element - * @param[in] neighborIds region, subRegion, and element indices of the neigbhbor element + * @param[in] neighborIds region, subRegion, and element indices of the neighbor element * @param[in] transGravCoef * @param[in] phaseDens the phase densities in the domain (non-local) * @param[in] dPhaseDens the derivatives of the phase densities in the domain wrt pressure and component fractions (non-local) @@ -153,7 +153,7 @@ struct UpwindingHelper /** * @brief At a given one-sided face, compute the gravCoef multiplied by the difference in phase densities * @param[in] localIds region, subRegion, and element indices of the local element - * @param[in] neighborIds region, subRegion, and element indices of the neigbhbor element + * @param[in] neighborIds region, subRegion, and element indices of the neighbor element * @param[in] transGravCoef * @param[in] phaseDens the phase densities in the domain (non-local) * @param[in] dPhaseDens the derivatives of the phase densities in the domain wrt pressure and component fractions (non-local) @@ -179,7 +179,7 @@ struct UpwindingHelper /** * @brief At a given one-sided face, compute the upwinded total mobility * @param[in] localIds region, subRegion, and element indices of the local element - * @param[in] neighborIds region, subRegion, and element indices of the neigbhbor element + * @param[in] neighborIds region, subRegion, and element indices of the neighbor element * @param[in] phaseMob the phase mobilities in the domain (non-local) * @param[in] dPhaseMob the derivatives of the phase mobilities in the domain (non-local) * @param[in] phaseGravTerm the gravCoef multiplied by the difference in phase densities @@ -246,6 +246,14 @@ struct UpwindingHelper /******************************** AssemblerKernelHelper ********************************/ +/** + * @struct AssemblerKernelHelper + * @brief Helper structure containing static methods for flux assembly in hybrid FVM + * + * This helper provides methods to compute pressure gradients, flux divergence, and assemble + * face-based continuity equations for the hybrid finite volume method discretization. + * All methods are designed to work on both host and device (GEOS_HOST_DEVICE). + */ struct AssemblerKernelHelper { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 725cb463938..62a97e751e6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1668,24 +1668,28 @@ DirichletFluxKernel:: /******************************** EvaluateBCFacePropertiesKernel ********************************/ /** - * @brief Evaluate constitutive properties at BC face conditions + * @brief Evaluate constitutive properties at BC face conditions using flash calculations * @tparam NC number of components * @tparam NP number of phases - * @param numPhases number of phases - * @param boundaryFaceSet set of boundary faces - * @param facePres face pressures at BC - * @param faceTemp face temperatures at BC - * @param faceCompFrac face component fractions at BC - * @param elemRegionList face to element region list - * @param elemSubRegionList face to element subregion list - * @param elemList face to element list - * @param er target element region index - * @param esr target element subregion index - * @param fluid multifluid model - * @param relperm relative permeability model - * @param facePhaseMob output: face phase mobility at BC - * @param facePhaseMassDens output: face phase mass density at BC - * @param facePhaseCompFrac output: face phase component fraction at BC + * @param[in] numPhases number of phases in the simulation + * @param[in] boundaryFaceSet sorted array view of boundary face indices + * @param[in] facePres pressure values at boundary faces + * @param[in] faceTemp temperature values at boundary faces + * @param[in] faceCompFrac component fraction values at boundary faces + * @param[in] elemRegionList face-to-element region mapping + * @param[in] elemSubRegionList face-to-element subregion mapping + * @param[in] elemList face-to-element index mapping + * @param[in] er target element region index + * @param[in] esr target element subregion index + * @param[in] fluid reference to multifluid constitutive model + * @param[in] relperm reference to relative permeability constitutive model + * @param[out] facePhaseMob computed phase mobility at BC faces + * @param[out] facePhaseMassDens computed phase mass density at BC faces + * @param[out] facePhaseCompFrac computed phase component fractions at BC faces + * + * @note This function uses serialPolicy (host execution) because CUDA does not allow + * extended device lambdas inside generic lambda expressions. The output arrays + * must be explicitly moved to device memory after this function completes. */ template< integer NC, integer NP > void @@ -1746,7 +1750,7 @@ evaluateBCFaceProperties( integer const numPhases, StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); - + // Initialize all temporary arrays to zero to ensure deterministic behavior on GPU for( integer ip = 0; ip < numPhases; ++ip ) { @@ -1761,7 +1765,7 @@ evaluateBCFaceProperties( integer const numPhases, facePhaseCompFracLocal[0][0][ip][ic] = 0.0; } } - + real64 faceTotalDens = 0.0; // Evaluate fluid properties at BC face conditions using flash calculation From be93e97d49d4a1b604038f5824c87627e99c4f66 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 3 Nov 2025 09:11:13 -0800 Subject: [PATCH 86/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 7f09e3e576f..ff7d03729d3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -1,4 +1,4 @@ -.md file/* +/* * ------------------------------------------------------------------------------------------------------------ * SPDX-License-Identifier: LGPL-2.1-only * From 61c2a6a0ca0ea94942ee3e79d3fe1cd9e31ea9c0 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 3 Nov 2025 09:15:49 -0800 Subject: [PATCH 87/91] fix: code style --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 2 +- .../CompositionalMultiphaseHybridFVMKernels_impl.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index ff7d03729d3..1b9c45c5f7b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -188,7 +188,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou arrayView2d< real64, compflow::USD_PHASE > facePhaseMob = faceManager.getField< flow::facePhaseMobility >(); arrayView2d< real64, compflow::USD_PHASE > facePhaseMassDens = faceManager.getField< flow::facePhaseMassDensity >(); arrayView3d< real64, compflow::USD_PHASE_COMP > facePhaseCompFrac = faceManager.getField< flow::facePhaseCompFraction >(); - + localIndex const numFaces = faceManager.size(); forAll< parallelDevicePolicy<> >( numFaces, [=] GEOS_HOST_DEVICE ( localIndex const iface ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp index 62a97e751e6..64f8d7f0d58 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels_impl.hpp @@ -1750,7 +1750,7 @@ evaluateBCFaceProperties( integer const numPhases, StackArray< real64, 3, constitutive::MultiFluidBase::MAX_NUM_PHASES, constitutive::multifluid::LAYOUT_PHASE > facePhaseInternalEnergy( 1, 1, numPhases ); StackArray< real64, 4, constitutive::MultiFluidBase::MAX_NUM_PHASES * NC, constitutive::multifluid::LAYOUT_PHASE_COMP > facePhaseCompFracLocal( 1, 1, numPhases, NC ); - + // Initialize all temporary arrays to zero to ensure deterministic behavior on GPU for( integer ip = 0; ip < numPhases; ++ip ) { @@ -1765,7 +1765,7 @@ evaluateBCFaceProperties( integer const numPhases, facePhaseCompFracLocal[0][0][ip][ic] = 0.0; } } - + real64 faceTotalDens = 0.0; // Evaluate fluid properties at BC face conditions using flash calculation From 83ff57ccf9cddbcd346faf2f81048205ef07d4c9 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Thu, 6 Nov 2025 17:56:35 -0800 Subject: [PATCH 88/91] Update CompositionalMultiphaseHybridFVMKernels.hpp --- ...ompositionalMultiphaseHybridFVMKernels.hpp | 193 ++++++++++-------- 1 file changed, 112 insertions(+), 81 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp index 350a706ba08..69259d917d0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CompositionalMultiphaseHybridFVMKernels.hpp @@ -46,31 +46,62 @@ namespace compositionalMultiphaseHybridFVMKernels { //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 >{} ); -// } -// default: -// GEOS_ERROR( "Unknown numFacesInElem value: " << value ); -// } -//} +/******************************** 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 @@ -1308,62 +1339,62 @@ struct PrecomputeMimeticTransGgradZKernel /******************************** 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 +//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 template< typename KERNELWRAPPER, typename INNER_PRODUCT, typename ... ARGS > void simpleKernelLaunchSelector( localIndex numFacesInElem, ARGS && ... args ) From 009a46125553604b469ad736664bce4ec55c31ee Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Fri, 7 Nov 2025 21:20:54 -0800 Subject: [PATCH 89/91] wip: fix usage of usage of upwindingScheme HU2PH --- .../fluidFlow/CompositionalMultiphaseFVM.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 ) From b137713924276462ef1ca90acf108f52a7a307d5 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Tue, 11 Nov 2025 16:36:57 -0800 Subject: [PATCH 90/91] wip: removing unused instantiations file --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 6 +- ...glePhaseHybridFVMKernelsInstantiations.cpp | 97 ------------------- 2 files changed, 2 insertions(+), 101 deletions(-) delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index a12f17fa1c2..7e6a227ee02 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -145,6 +145,7 @@ set( fluidFlowSolvers_sources kernels/compositional/AquiferBCKernel.cpp kernels/compositional/CFLKernel.cpp kernels/compositional/FluxComputeKernelBase.cpp + kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp wells/CompositionalMultiphaseWell.cpp wells/kernels/CompositionalMultiphaseWellKernels.cpp wells/SinglePhaseWell.cpp @@ -152,10 +153,7 @@ set( fluidFlowSolvers_sources wells/WellControls.cpp wells/WellSolverBase.cpp proppantTransport/ProppantTransport.cpp - proppantTransport/ProppantTransportKernels.cpp - # Macro-based explicit instantiations for hybrid FVM kernels - kernels/compositional/CompositionalMultiphaseHybridFVMKernelsInstantiations.cpp - kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp ) + proppantTransport/ProppantTransportKernels.cpp ) # Remove the old generator-based hybrid flux/dirichlet kernels and switch to macro approach file( READ "${CMAKE_CURRENT_LIST_DIR}/kernelSpecs.json" kernelSpecs ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp deleted file mode 100644 index a573b1db6cb..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernelsInstantiations.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file SinglePhaseHybridFVMKernelsInstantiations.cpp - * @brief Centralized explicit template instantiations for single-phase hybrid FVM kernels. - * - * Define GEOS_ENABLE_MANUAL_HYBRID_FVM_INST to activate the explicit instantiations below. - * When enabled, ensure overlapping template-generated sources are not compiled to avoid duplicates. - */ - -#include "physicsSolvers/fluidFlow/kernels/singlePhase/SinglePhaseHybridFVMKernels.hpp" - -#include "finiteVolume/mimeticInnerProducts/TPFAInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/QuasiTPFAInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/QuasiRTInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/SimpleInnerProduct.hpp" -#include "finiteVolume/mimeticInnerProducts/BdVLMInnerProduct.hpp" - -namespace geos -{ -namespace singlePhaseHybridFVMKernels -{ - -#if defined(GEOS_ENABLE_MANUAL_HYBRID_FVM_INST) - -// ----------------------------------------------------------------------------- -// Faces-per-element list (kept in sync with kernelLaunchSelectorFaceSwitch) -// ----------------------------------------------------------------------------- -#define GEOS_NFACES_LIST \ - X_NF( 4 ) \ - X_NF( 5 ) \ - X_NF( 6 ) \ - X_NF( 7 ) \ - X_NF( 8 ) \ - X_NF( 9 ) \ - X_NF( 10 ) \ - X_NF( 11 ) \ - X_NF( 12 ) \ - X_NF( 13 ) - -// ----------------------------------------------------------------------------- -// Inner product list helper -// ----------------------------------------------------------------------------- -#define GEOS_FOR_EACH_IP( NF, MACRO ) \ - MACRO( NF, mimeticInnerProduct::TPFAInnerProduct ) \ - MACRO( NF, mimeticInnerProduct::QuasiTPFAInnerProduct ) \ - MACRO( NF, mimeticInnerProduct::QuasiRTInnerProduct ) \ - MACRO( NF, mimeticInnerProduct::SimpleInnerProduct ) \ - MACRO( NF, mimeticInnerProduct::BdVLMInnerProduct ) - -// ----------------------------------------------------------------------------- -// AveragePressureGradientKernel explicit class instantiations -// ----------------------------------------------------------------------------- -#define INSTANTIATE_AVG_PRES_GRAD( NF ) \ - template class AveragePressureGradientKernel< NF >; - -#define X_NF( NF ) INSTANTIATE_AVG_PRES_GRAD( NF ) -GEOS_NFACES_LIST -#undef X_NF -#undef INSTANTIATE_AVG_PRES_GRAD - -// ----------------------------------------------------------------------------- -// ElementBasedAssemblyKernel explicit class instantiations -// ----------------------------------------------------------------------------- -#define INSTANTIATE_ELEM_KERNEL( NF, IP ) \ - template class ElementBasedAssemblyKernel< NF, IP >; - -#define INSTANTIATE_ELEM_KERNEL_FOR_IPS( NF ) \ - GEOS_FOR_EACH_IP( NF, INSTANTIATE_ELEM_KERNEL ) - -#define X_NF( NF ) INSTANTIATE_ELEM_KERNEL_FOR_IPS( NF ) -GEOS_NFACES_LIST -#undef X_NF -#undef INSTANTIATE_ELEM_KERNEL_FOR_IPS -#undef INSTANTIATE_ELEM_KERNEL - -// Cleanup local helper macros -#undef GEOS_FOR_EACH_IP -#undef GEOS_NFACES_LIST - -#endif // GEOS_ENABLE_MANUAL_HYBRID_FVM_INST - -} // namespace singlePhaseHybridFVMKernels -} // namespace geos From 75982e7ac357eb80328fdb8705308de03bf29f14 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Mon, 17 Nov 2025 10:58:30 -0800 Subject: [PATCH 91/91] Update CompositionalMultiphaseHybridFVM.cpp --- .../fluidFlow/CompositionalMultiphaseHybridFVM.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index be78e7a85bf..229f276f6b5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -797,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 ); @@ -968,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() ) {