From adfefc3ee8eb28732fde53fbc960c7f9fc474c1a Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Tue, 7 Jan 2025 09:42:07 -0600 Subject: [PATCH 1/3] refactor: clarify new gravity, clean up kernel flags usage, move CFL computations to FVM solver (#3486) Co-authored-by: Matteo Cusini <49037133+CusiniM@users.noreply.github.com> --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 + .../finiteVolume/docs/FiniteVolume.rst.txt | 18 +- .../physicsSolvers/PhysicsSolverBase.cpp | 9 - .../physicsSolvers/PhysicsSolverBase.hpp | 11 - .../fluidFlow/CompositionalMultiphaseBase.cpp | 213 +------------- .../fluidFlow/CompositionalMultiphaseBase.hpp | 26 +- .../fluidFlow/CompositionalMultiphaseFVM.cpp | 276 ++++++++++++++++-- .../fluidFlow/CompositionalMultiphaseFVM.hpp | 54 +++- .../CompositionalMultiphaseStatistics.cpp | 21 +- .../compositional/AccumulationKernel.hpp | 9 +- .../kernels/compositional/C1PPUPhaseFlux.hpp | 7 +- .../kernels/compositional/CFLKernel.cpp | 14 +- .../kernels/compositional/CFLKernel.hpp | 7 +- .../DiffusionDispersionFluxComputeKernel.hpp | 11 +- .../DissipationFluxComputeKernel.hpp | 11 +- .../compositional/FluxComputeKernel.hpp | 29 +- .../compositional/FluxComputeKernelBase.hpp | 16 +- .../kernels/compositional/IHUPhaseFlux.hpp | 46 +-- .../kernels/compositional/PPUPhaseFlux.hpp | 12 +- .../kernels/compositional/PotGrad.hpp | 12 +- .../StabilizedFluxComputeKernel.hpp | 11 +- .../ThermalAccumulationKernel.hpp | 6 +- ...alDiffusionDispersionFluxComputeKernel.hpp | 11 +- .../ThermalDirichletFluxComputeKernel.hpp | 7 +- .../ThermalFluxComputeKernel.hpp | 13 +- .../wells/CompositionalMultiphaseWell.cpp | 16 +- .../CompositionalMultiphaseWellKernels.hpp | 15 +- ...rmalCompositionalMultiphaseWellKernels.hpp | 17 +- ...mpositionalMultiphaseReservoirAndWells.cpp | 9 +- .../CoupledReservoirAndWellKernels.hpp | 26 +- 31 files changed, 465 insertions(+), 474 deletions(-) diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 6dfbf981b0c..6f9b1951cf3 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3479-9362-cffefcc + baseline: integratedTests/baseline_integratedTests-pr3486-9492-f0c817c allow_fail: all: '' streak: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index 0bc5c80f561..d2d18fba2d3 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 #3486 (2025-01-06) +===================== +useNewGravity became gravityDensityScheme. + PR #3479 (2024-12-15) ===================== Refine inputFiles/compositionalMultiphaseFlow: shift reference pressures to initial pressures, make nonlinear tuning more reasonable, minimize output. diff --git a/src/coreComponents/finiteVolume/docs/FiniteVolume.rst.txt b/src/coreComponents/finiteVolume/docs/FiniteVolume.rst.txt index 755e215d64e..ad65ea50dd4 100644 --- a/src/coreComponents/finiteVolume/docs/FiniteVolume.rst.txt +++ b/src/coreComponents/finiteVolume/docs/FiniteVolume.rst.txt @@ -16,17 +16,27 @@ The numerical flux is obtained using the following expression for the mass flux .. math:: F_{KL} = \Upsilon_{KL} \frac{\rho^{upw}}{\mu^{upw}} \big( p_K - p_L - \rho^{avg} g ( d_K - d_L ) \big), -where :math:`p_K` is the pressure of cell :math:`K`, :math:`d_K` is the depth of cell :math:`K`, and :math:`\Upsilon_{KL}` is the standard TPFA transmissibility coefficient at the interface. + +where :math:`p_K` is the pressure of cell :math:`K`, :math:`\rho^{avg}` is the average fluid density, :math:`d_K` is the depth of cell :math:`K`, and :math:`\Upsilon_{KL}` is the standard TPFA transmissibility coefficient at the interface. The fluid density, :math:`\rho^{upw}`, and the fluid viscosity, :math:`\mu^{upw}`, are upwinded using the sign of the potential difference at the interface. -This is currently the only available discretization in the :ref:`CompositionalMultiphaseFlow`. +For :ref:`CompositionalMultiphaseFlow` there are two options to compute the average density, :math:`\rho^{avg}`. The desired option can be selected using the `gravityDensityScheme` parameter: + +#. `ArithmeticAverage`: :math:`\rho^{avg}` is computed using simple arithmetic average: :math:`\rho^{avg} = 0.5 \cdot (rho_K + rho_L)`, where :math:`rho_K` and :math:`rho_K` are densities in the two cells. + +#. `PhasePresence`: average phase density is computed using checking for phase presence: + + * :math:`\rho^{avg} = 0.5 \cdot (\rho_K + \rho_L)` if phase is present in both cells :math:`K` and :math:`L` + + * :math:`\rho^{avg} = \rho_K` if phase is present only in cell :math:`K` + + * :math:`\rho^{avg} = \rho_L` if phase is present only in cell :math:`L` Hybrid FVM ~~~~~~~~~~ This discretization scheme overcomes the limitations of the standard TPFA on non K-orthogonal meshes. The hybrid finite-volume scheme--equivalent to the well-known hybrid Mimetic Finite Difference (MFD) scheme--remains consistent with the pressure equation even when the mesh does not satisfy the K-orthogonality condition. -This numerical scheme is currently implemented in the `SinglePhaseHybridFVM` solver. The hybrid FVM scheme uses both cell-centered and face-centered pressure degrees of freedom. The one-sided face flux, :math:`F_{K,f}`, at face :math:`f` of cell :math:`K` is computed as: @@ -60,5 +70,3 @@ For a given interior face :math:`f` between two neighboring cells :math:`K` and We obtain a numerical scheme with :math:`n_{\textit{cells}}` cell-centered degrees of freedom and :math:`n_{\textit{faces}}` face-centered pressure degrees of freedom. The system involves :math:`n_{\textit{cells}}` mass conservation equations and :math:`n_{\textit{faces}}` face-based constraints. The linear systems can be efficiently solved using the MultiGrid Reduction (MGR) preconditioner implemented in the Hypre linear algebra package. - -The implementation of the hybrid FVM scheme for :ref:`CompositionalMultiphaseFlow` is in progress. diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 14ec3cbfd45..669f721b5f4 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -458,15 +458,6 @@ real64 PhysicsSolverBase::setNextDtBasedOnNewtonIter( real64 const & currentDt ) return nextDt; } - -real64 PhysicsSolverBase::setNextDtBasedOnCFL( const geos::real64 & currentDt, geos::DomainPartition & domain ) -{ - GEOS_UNUSED_VAR( currentDt, domain ); - return LvArray::NumericLimits< real64 >::max; // i.e., not implemented -} - - - real64 PhysicsSolverBase::linearImplicitStep( real64 const & time_n, real64 const & dt, integer const GEOS_UNUSED_PARAM( cycleNumber ), diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp index 92b004f8624..95a87f1a87f 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp @@ -239,17 +239,6 @@ class PhysicsSolverBase : public ExecutableGroup virtual real64 setNextDtBasedOnStateChange( real64 const & currentDt, DomainPartition & domain ); - /** - * @brief function to set the next dt based on state change - * @param [in] currentDt the current time step size - * @param[in] domain the domain object - * @return the prescribed time step size - */ - virtual real64 setNextDtBasedOnCFL( real64 const & currentDt, - DomainPartition & domain ); - - - /** * @brief Entry function for an explicit time integration step * @param time_n time at the beginning of the step diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp index 66c79677033..5bb8896898d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp @@ -53,7 +53,6 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/SolidInternalEnergyUpdateKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/HydrostaticPressureKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/StatisticsKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.hpp" #if defined( __INTEL_COMPILER ) #pragma GCC optimize "O0" @@ -78,7 +77,6 @@ CompositionalMultiphaseBase::CompositionalMultiphaseBase( const string & name, m_allowCompDensChopping( 1 ), m_useTotalMassEquation( 1 ), m_useSimpleAccumulation( 1 ), - m_useNewGravity( 0 ), m_minCompDens( isothermalCompositionalMultiphaseBaseKernels::minDensForDivision ) { //START_SPHINX_INCLUDE_00 @@ -147,12 +145,6 @@ CompositionalMultiphaseBase::CompositionalMultiphaseBase( const string & name, setApplyDefaultValue( 1 ). setDescription( "Flag indicating whether local (cell-wise) chopping of negative compositions is allowed" ); - this->registerWrapper( viewKeyStruct::targetFlowCFLString(), &m_targetFlowCFL ). - setApplyDefaultValue( -1. ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Target CFL condition `CFL condition `_" - " when computing the next timestep." ); - this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). setSizedFromParent( 0 ). setInputFlag( InputFlags::OPTIONAL ). @@ -165,12 +157,6 @@ CompositionalMultiphaseBase::CompositionalMultiphaseBase( const string & name, setApplyDefaultValue( 1 ). setDescription( "Flag indicating whether simple accumulation form is used" ); - this->registerWrapper( viewKeyStruct::useNewGravityString(), &m_useNewGravity ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0 ). - setDescription( "Flag indicating whether new gravity treatment is used" ); - this->registerWrapper( viewKeyStruct::minCompDensString(), &m_minCompDens ). setSizedFromParent( 0 ). setInputFlag( InputFlags::OPTIONAL ). @@ -359,16 +345,6 @@ void CompositionalMultiphaseBase::registerDataOnMesh( Group & meshBodies ) InputError ); } - if( m_targetFlowCFL > 0 ) - { - subRegion.registerField< fields::flow::phaseOutflux >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - subRegion.registerField< fields::flow::componentOutflux >( getName() ). - reference().resizeDimension< 1 >( m_numComponents ); - subRegion.registerField< fields::flow::phaseCFLNumber >( getName() ); - subRegion.registerField< fields::flow::componentCFLNumber >( getName() ); - } - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); @@ -1349,6 +1325,15 @@ void CompositionalMultiphaseBase::assembleAccumulationAndVolumeBalanceTerms( Dom { GEOS_MARK_FUNCTION; + using namespace isothermalCompositionalMultiphaseBaseKernels; + + BitFlags< KernelFlags > kernelFlags; + if( m_useTotalMassEquation ) + kernelFlags.set( KernelFlags::TotalMassEquation ); + if( m_useSimpleAccumulation ) + kernelFlags.set( KernelFlags::SimpleAccumulation ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, arrayView1d< string const > const & regionNames ) @@ -1371,7 +1356,7 @@ void CompositionalMultiphaseBase::assembleAccumulationAndVolumeBalanceTerms( Dom createAndLaunch< parallelDevicePolicy<> >( m_numComponents, m_numPhases, dofManager.rankOffset(), - m_useTotalMassEquation, + kernelFlags, dofKey, subRegion, fluid, @@ -1386,8 +1371,7 @@ void CompositionalMultiphaseBase::assembleAccumulationAndVolumeBalanceTerms( Dom createAndLaunch< parallelDevicePolicy<> >( m_numComponents, m_numPhases, dofManager.rankOffset(), - m_useTotalMassEquation, - m_useSimpleAccumulation, + kernelFlags, dofKey, subRegion, fluid, @@ -2181,172 +2165,6 @@ real64 CompositionalMultiphaseBase::setNextDtBasedOnStateChange( real64 const & return std::min( std::min( nextDtPressure, std::min( nextDtPhaseVolFrac, nextDtCompDens ) ), nextDtTemperature ); } -real64 CompositionalMultiphaseBase::setNextDtBasedOnCFL( const geos::real64 & currentDt, geos::DomainPartition & domain ) -{ - - real64 maxPhaseCFL, maxCompCFL; - - computeCFLNumbers( domain, currentDt, maxPhaseCFL, maxCompCFL ); - - GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max phase CFL number = {}", getName(), maxPhaseCFL ) ); - GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max component CFL number = {} ", getName(), maxCompCFL ) ); - - return std::min( m_targetFlowCFL * currentDt / maxCompCFL, - m_targetFlowCFL * currentDt / maxPhaseCFL ); -} - -void CompositionalMultiphaseBase::computeCFLNumbers( geos::DomainPartition & domain, const geos::real64 & dt, - geos::real64 & maxPhaseCFL, geos::real64 & maxCompCFL ) -{ - GEOS_MARK_FUNCTION; - - integer const numPhases = numFluidPhases(); - integer const numComps = numFluidComponents(); - - // Step 1: reset the arrays involved in the computation of CFL numbers - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView2d< real64, compflow::USD_PHASE > const & phaseOutflux = - subRegion.getField< fields::flow::phaseOutflux >(); - arrayView2d< real64, compflow::USD_COMP > const & compOutflux = - subRegion.getField< fields::flow::componentOutflux >(); - phaseOutflux.zero(); - compOutflux.zero(); - } ); - - // Step 2: compute the total volumetric outflux for each reservoir cell by looping over faces - NumericalMethodsManager & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager & fvManager = numericalMethodManager.getFiniteVolumeManager(); - FluxApproximationBase & fluxApprox = fvManager.getFluxApproximation( getDiscretizationName() ); - - isothermalCompositionalMultiphaseFVMKernels:: - CFLFluxKernel::CompFlowAccessors compFlowAccessors( mesh.getElemManager(), getName() ); - isothermalCompositionalMultiphaseFVMKernels:: - CFLFluxKernel::MultiFluidAccessors multiFluidAccessors( mesh.getElemManager(), getName() ); - isothermalCompositionalMultiphaseFVMKernels:: - CFLFluxKernel::PermeabilityAccessors permeabilityAccessors( mesh.getElemManager(), getName() ); - isothermalCompositionalMultiphaseFVMKernels:: - CFLFluxKernel::RelPermAccessors relPermAccessors( mesh.getElemManager(), getName() ); - - // TODO: find a way to compile with this modifiable accessors in CompFlowAccessors, and remove them from here - ElementRegionManager::ElementViewAccessor< arrayView2d< real64, compflow::USD_PHASE > > const phaseOutfluxAccessor = - mesh.getElemManager().constructViewAccessor< array2d< real64, compflow::LAYOUT_PHASE >, - arrayView2d< real64, compflow::USD_PHASE > >( fields::flow::phaseOutflux::key() ); - - ElementRegionManager::ElementViewAccessor< arrayView2d< real64, compflow::USD_COMP > > const compOutfluxAccessor = - mesh.getElemManager().constructViewAccessor< array2d< real64, compflow::LAYOUT_COMP >, - arrayView2d< real64, compflow::USD_COMP > >( fields::flow::componentOutflux::key() ); - - - fluxApprox.forAllStencils( mesh, [&] ( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - - // While this kernel is waiting for a factory class, pass all the accessors here - isothermalCompositionalMultiphaseBaseKernels::KernelLaunchSelector1 - < isothermalCompositionalMultiphaseFVMKernels::CFLFluxKernel >( numComps, - numPhases, - m_useNewGravity, - dt, - stencilWrapper, - compFlowAccessors.get( fields::flow::pressure{} ), - compFlowAccessors.get( fields::flow::gravityCoefficient{} ), - compFlowAccessors.get( fields::flow::phaseVolumeFraction{} ), - permeabilityAccessors.get( fields::permeability::permeability{} ), - permeabilityAccessors.get( fields::permeability::dPerm_dPressure{} ), - relPermAccessors.get( fields::relperm::phaseRelPerm{} ), - multiFluidAccessors.get( fields::multifluid::phaseViscosity{} ), - multiFluidAccessors.get( fields::multifluid::phaseDensity{} ), - multiFluidAccessors.get( fields::multifluid::phaseMassDensity{} ), - multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} ), - phaseOutfluxAccessor.toNestedView(), - compOutfluxAccessor.toNestedView() ); - } ); - } ); - - // Step 3: finalize the (cell-based) computation of the CFL numbers - real64 localMaxPhaseCFLNumber = 0.0; - real64 localMaxCompCFLNumber = 0.0; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView2d< real64 const, compflow::USD_PHASE > const & phaseOutflux = - subRegion.getField< fields::flow::phaseOutflux >(); - arrayView2d< real64 const, compflow::USD_COMP > const & compOutflux = - subRegion.getField< fields::flow::componentOutflux >(); - - arrayView1d< real64 > const & phaseCFLNumber = subRegion.getField< fields::flow::phaseCFLNumber >(); - arrayView1d< real64 > const & compCFLNumber = subRegion.getField< fields::flow::componentCFLNumber >(); - - arrayView1d< real64 const > const & volume = subRegion.getElementVolume(); - - arrayView2d< real64 const, compflow::USD_COMP > const & compDens = - subRegion.getField< fields::flow::globalCompDensity >(); - arrayView2d< real64 const, compflow::USD_COMP > const compFrac = - subRegion.getField< fields::flow::globalCompFraction >(); - arrayView2d< real64, compflow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::flow::phaseVolumeFraction >(); - - Group const & constitutiveModels = subRegion.getGroup( ElementSubRegionBase::groupKeyStruct::constitutiveModelsString() ); - - string const & fluidName = subRegion.getReference< string >( CompositionalMultiphaseBase::viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = constitutiveModels.getGroup< MultiFluidBase >( fluidName ); - arrayView3d< real64 const, multifluid::USD_PHASE > const & phaseVisc = fluid.phaseViscosity(); - - string const & relpermName = subRegion.getReference< string >( CompositionalMultiphaseBase::viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase const & relperm = constitutiveModels.getGroup< RelativePermeabilityBase >( relpermName ); - arrayView3d< real64 const, relperm::USD_RELPERM > const & phaseRelPerm = relperm.phaseRelPerm(); - arrayView4d< real64 const, relperm::USD_RELPERM_DS > const & dPhaseRelPerm_dPhaseVolFrac = relperm.dPhaseRelPerm_dPhaseVolFraction(); - - string const & solidName = subRegion.getReference< string >( CompositionalMultiphaseBase::viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & solid = constitutiveModels.getGroup< CoupledSolidBase >( solidName ); - arrayView2d< real64 const > const & porosity = solid.getPorosity(); - - real64 subRegionMaxPhaseCFLNumber = 0.0; - real64 subRegionMaxCompCFLNumber = 0.0; - - isothermalCompositionalMultiphaseBaseKernels::KernelLaunchSelector2 - < isothermalCompositionalMultiphaseFVMKernels::CFLKernel >( numComps, numPhases, - subRegion.size(), - volume, - porosity, - compDens, - compFrac, - phaseVolFrac, - phaseRelPerm, - dPhaseRelPerm_dPhaseVolFrac, - phaseVisc, - phaseOutflux, - compOutflux, - phaseCFLNumber, - compCFLNumber, - subRegionMaxPhaseCFLNumber, - subRegionMaxCompCFLNumber ); - - localMaxPhaseCFLNumber = LvArray::math::max( localMaxPhaseCFLNumber, subRegionMaxPhaseCFLNumber ); - localMaxCompCFLNumber = LvArray::math::max( localMaxCompCFLNumber, subRegionMaxCompCFLNumber ); - - } ); - } ); - - maxPhaseCFL = MpiWrapper::max( localMaxPhaseCFLNumber ); - maxCompCFL = MpiWrapper::max( localMaxCompCFLNumber ); - -} - - void CompositionalMultiphaseBase::resetStateToBeginningOfStep( DomainPartition & domain ) { GEOS_MARK_FUNCTION; @@ -2606,13 +2424,4 @@ bool CompositionalMultiphaseBase::checkSequentialSolutionIncrements( DomainParti return isConverged && (m_sequentialCompDensChange < m_maxSequentialCompDensChange); } -real64 CompositionalMultiphaseBase::setNextDt( const geos::real64 & currentDt, geos::DomainPartition & domain ) -{ - - if( m_targetFlowCFL < 0 ) - return PhysicsSolverBase::setNextDt( currentDt, domain ); - else - return setNextDtBasedOnCFL( currentDt, domain ); -} - } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp index 1cec9ca685b..318662d00fc 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp @@ -68,6 +68,8 @@ class CompositionalMultiphaseBase : public FlowSolverBase virtual void registerDataOnMesh( Group & meshBodies ) override; + virtual void registerDataForCFL( Group & meshBodies ) { GEOS_UNUSED_VAR( meshBodies ); } + /** * @defgroup Solver Interface Functions * @@ -268,7 +270,6 @@ class CompositionalMultiphaseBase : public FlowSolverBase static constexpr char const * allowLocalCompDensChoppingString() { return "allowLocalCompDensityChopping"; } static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } static constexpr char const * useSimpleAccumulationString() { return "useSimpleAccumulation"; } - static constexpr char const * useNewGravityString() { return "useNewGravity"; } static constexpr char const * minCompDensString() { return "minCompDens"; } static constexpr char const * maxSequentialCompDensChangeString() { return "maxSequentialCompDensChange"; } static constexpr char const * minScalingFactorString() { return "minScalingFactor"; } @@ -370,19 +371,12 @@ class CompositionalMultiphaseBase : public FlowSolverBase virtual real64 setNextDtBasedOnStateChange( real64 const & currentDt, DomainPartition & domain ) override; - void computeCFLNumbers( DomainPartition & domain, real64 const & dt, real64 & maxPhaseCFL, real64 & maxCompCFL ); - - /** - * @brief function to set the next time step size - * @param[in] currentDt the current time step size - * @param[in] domain the domain object - * @return the prescribed time step size - */ - real64 setNextDt( real64 const & currentDt, - DomainPartition & domain ) override; - virtual real64 setNextDtBasedOnCFL( real64 const & currentDt, - DomainPartition & domain ) override; + virtual void computeCFLNumbers( DomainPartition & domain, real64 const & dt, real64 & maxPhaseCFL, real64 & maxCompCFL ) + { + GEOS_UNUSED_VAR( domain, dt, maxPhaseCFL, maxCompCFL ); + GEOS_ERROR( GEOS_FMT( "{}: computeCFLNumbers is not implemented for {}", getDataContext(), getCatalogName() ) ); + } virtual void initializePostInitialConditionsPreSubGroups() override; @@ -487,9 +481,6 @@ class CompositionalMultiphaseBase : public FlowSolverBase /// flag indicating whether simple accumulation form is used integer m_useSimpleAccumulation; - /// flag indicating whether new gravity treatment is used - integer m_useNewGravity; - /// minimum allowed global component density real64 m_minCompDens; @@ -500,9 +491,6 @@ class CompositionalMultiphaseBase : public FlowSolverBase real64 m_sequentialCompDensChange; real64 m_maxSequentialCompDensChange; - /// the targeted CFL for timestep - real64 m_targetFlowCFL; - private: /** diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp index 9a64efef23d..d2dbcb2f3a0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp @@ -53,6 +53,7 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/PhaseMobilityKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/ThermalPhaseMobilityKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/AquiferBCKernel.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.hpp" namespace geos { @@ -100,6 +101,18 @@ CompositionalMultiphaseFVM::CompositionalMultiphaseFVM( const string & name, setApplyDefaultValue( ScalingType::Global ). setDescription( "Solution scaling type." "Valid options:\n* " + EnumStrings< ScalingType >::concat( "\n* " ) ); + + this->registerWrapper( viewKeyStruct::gravityDensitySchemeString(), &m_gravityDensityScheme ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( GravityDensityScheme::ArithmeticAverage ). + setDescription( "Scheme for density treatment in gravity" ); + + this->registerWrapper( viewKeyStruct::targetFlowCFLString(), &m_targetFlowCFL ). + setApplyDefaultValue( -1. ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Target CFL condition `CFL condition `_" + " when computing the next timestep." ); } void CompositionalMultiphaseFVM::postInputInitialization() @@ -112,6 +125,36 @@ void CompositionalMultiphaseFVM::postInputInitialization() } } +void CompositionalMultiphaseFVM::registerDataOnMesh( Group & meshBodies ) +{ + using namespace fields::flow; + + CompositionalMultiphaseBase::registerDataOnMesh( meshBodies ); + + if( m_targetFlowCFL > 0 ) + { + registerDataForCFL( meshBodies ); + } +} + +void CompositionalMultiphaseFVM::registerDataForCFL( Group & meshBodies ) +{ + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + subRegion.registerField< fields::flow::phaseOutflux >( getName()).reference().resizeDimension< 1 >( m_numPhases ); + subRegion.registerField< fields::flow::componentOutflux >( getName()).reference().resizeDimension< 1 >( m_numComponents ); + subRegion.registerField< fields::flow::phaseCFLNumber >( getName()); + subRegion.registerField< fields::flow::componentCFLNumber >( getName()); + } ); + } ); +} + void CompositionalMultiphaseFVM::initializePreSubGroups() { CompositionalMultiphaseBase::initializePreSubGroups(); @@ -164,6 +207,20 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, { GEOS_MARK_FUNCTION; + using namespace isothermalCompositionalMultiphaseFVMKernels; + + BitFlags< KernelFlags > kernelFlags; + if( m_hasCapPressure ) + kernelFlags.set( KernelFlags::CapPressure ); + if( m_hasDiffusion ) + kernelFlags.set( KernelFlags::Diffusion ); + if( m_hasDispersion ) + kernelFlags.set( KernelFlags::Dispersion ); + if( m_useTotalMassEquation ) + kernelFlags.set( KernelFlags::TotalMassEquation ); + if( m_gravityDensityScheme == GravityDensityScheme::PhasePresence ) + kernelFlags.set( KernelFlags::CheckPhasePresenceInGravity ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, arrayView1d< string const > const & ) @@ -172,6 +229,13 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + auto const & upwindingParams = fluxApprox.upwindingParams(); + if( upwindingParams.upwindingScheme == UpwindingScheme::C1PPU && + isothermalCompositionalMultiphaseFVMKernelUtilities::epsC1PPU > 0 ) + kernelFlags.set( KernelFlags::C1PPU ); + else if( upwindingParams.upwindingScheme == UpwindingScheme::IHU ) + kernelFlags.set( KernelFlags::IHU ); + string const & elemDofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); fluxApprox.forAllStencils( mesh, [&] ( auto & stencil ) @@ -187,8 +251,7 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, m_numPhases, dofManager.rankOffset(), elemDofKey, - m_hasCapPressure, - m_useTotalMassEquation, + kernelFlags, getName(), mesh.getElemManager(), stencilWrapper, @@ -206,8 +269,7 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, m_numPhases, dofManager.rankOffset(), elemDofKey, - m_hasCapPressure, - m_useTotalMassEquation, + kernelFlags, getName(), mesh.getElemManager(), stencilWrapper, @@ -229,10 +291,7 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, m_numPhases, dofManager.rankOffset(), elemDofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_useNewGravity, - fluxApprox.upwindingParams(), + kernelFlags, getName(), mesh.getElemManager(), stencilWrapper, @@ -254,9 +313,7 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, m_numPhases, dofManager.rankOffset(), elemDofKey, - m_hasDiffusion, - m_hasDispersion, - m_useTotalMassEquation, + kernelFlags, getName(), mesh.getElemManager(), stencilWrapper, @@ -272,9 +329,7 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, m_numPhases, dofManager.rankOffset(), elemDofKey, - m_hasDiffusion, - m_hasDispersion, - m_useTotalMassEquation, + kernelFlags, getName(), mesh.getElemManager(), stencilWrapper, @@ -296,6 +351,14 @@ void CompositionalMultiphaseFVM::assembleStabilizedFluxTerms( real64 const dt, { GEOS_MARK_FUNCTION; + using namespace isothermalCompositionalMultiphaseFVMKernels; + + BitFlags< KernelFlags > kernelFlags; + if( m_hasCapPressure ) + kernelFlags.set( KernelFlags::CapPressure ); + if( m_useTotalMassEquation ) + kernelFlags.set( KernelFlags::TotalMassEquation ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, arrayView1d< string const > const & ) @@ -321,8 +384,7 @@ void CompositionalMultiphaseFVM::assembleStabilizedFluxTerms( real64 const dt, m_numPhases, dofManager.rankOffset(), elemDofKey, - m_hasCapPressure, - m_useTotalMassEquation, + kernelFlags, getName(), mesh.getElemManager(), stencilWrapper, @@ -1008,6 +1070,12 @@ void CompositionalMultiphaseFVM::applyFaceDirichletBC( real64 const time_n, GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ) ); } + using namespace isothermalCompositionalMultiphaseFVMKernels; + + BitFlags< KernelFlags > kernelFlags; + if( m_useTotalMassEquation ) + kernelFlags.set( KernelFlags::TotalMassEquation ); + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); @@ -1070,7 +1138,7 @@ void CompositionalMultiphaseFVM::applyFaceDirichletBC( real64 const time_n, createAndLaunch< parallelDevicePolicy<> >( m_numComponents, m_numPhases, dofManager.rankOffset(), - m_useTotalMassEquation, + kernelFlags, elemDofKey, getName(), faceManager, @@ -1196,6 +1264,180 @@ void CompositionalMultiphaseFVM::applyAquiferBC( real64 const time, } +real64 CompositionalMultiphaseFVM::setNextDt( const geos::real64 & currentDt, geos::DomainPartition & domain ) +{ + + if( m_targetFlowCFL < 0 ) + return CompositionalMultiphaseBase::setNextDt( currentDt, domain ); + else + return setNextDtBasedOnCFL( currentDt, domain ); +} + +real64 CompositionalMultiphaseFVM::setNextDtBasedOnCFL( const geos::real64 & currentDt, geos::DomainPartition & domain ) +{ + + real64 maxPhaseCFL, maxCompCFL; + + computeCFLNumbers( domain, currentDt, maxPhaseCFL, maxCompCFL ); + + GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max phase CFL number = {}", getName(), maxPhaseCFL ) ); + GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max component CFL number = {} ", getName(), maxCompCFL ) ); + + return std::min( m_targetFlowCFL * currentDt / maxCompCFL, + m_targetFlowCFL * currentDt / maxPhaseCFL ); +} + +void CompositionalMultiphaseFVM::computeCFLNumbers( geos::DomainPartition & domain, const geos::real64 & dt, + geos::real64 & maxPhaseCFL, geos::real64 & maxCompCFL ) +{ + GEOS_MARK_FUNCTION; + + integer const numPhases = numFluidPhases(); + integer const numComps = numFluidComponents(); + + // Step 1: reset the arrays involved in the computation of CFL numbers + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView2d< real64, compflow::USD_PHASE > const & phaseOutflux = + subRegion.getField< fields::flow::phaseOutflux >(); + arrayView2d< real64, compflow::USD_COMP > const & compOutflux = + subRegion.getField< fields::flow::componentOutflux >(); + phaseOutflux.zero(); + compOutflux.zero(); + } ); + + // Step 2: compute the total volumetric outflux for each reservoir cell by looping over faces + NumericalMethodsManager & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase & fluxApprox = fvManager.getFluxApproximation( getDiscretizationName() ); + + isothermalCompositionalMultiphaseFVMKernels:: + CFLFluxKernel::CompFlowAccessors compFlowAccessors( mesh.getElemManager(), getName() ); + isothermalCompositionalMultiphaseFVMKernels:: + CFLFluxKernel::MultiFluidAccessors multiFluidAccessors( mesh.getElemManager(), getName() ); + isothermalCompositionalMultiphaseFVMKernels:: + CFLFluxKernel::PermeabilityAccessors permeabilityAccessors( mesh.getElemManager(), getName() ); + isothermalCompositionalMultiphaseFVMKernels:: + CFLFluxKernel::RelPermAccessors relPermAccessors( mesh.getElemManager(), getName() ); + + // TODO: find a way to compile with this modifiable accessors in CompFlowAccessors, and remove them from here + ElementRegionManager::ElementViewAccessor< arrayView2d< real64, compflow::USD_PHASE > > const phaseOutfluxAccessor = + mesh.getElemManager().constructViewAccessor< array2d< real64, compflow::LAYOUT_PHASE >, + arrayView2d< real64, compflow::USD_PHASE > >( fields::flow::phaseOutflux::key() ); + + ElementRegionManager::ElementViewAccessor< arrayView2d< real64, compflow::USD_COMP > > const compOutfluxAccessor = + mesh.getElemManager().constructViewAccessor< array2d< real64, compflow::LAYOUT_COMP >, + arrayView2d< real64, compflow::USD_COMP > >( fields::flow::componentOutflux::key() ); + + + fluxApprox.forAllStencils( mesh, [&] ( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + + // While this kernel is waiting for a factory class, pass all the accessors here + isothermalCompositionalMultiphaseBaseKernels::KernelLaunchSelector1 + < isothermalCompositionalMultiphaseFVMKernels::CFLFluxKernel >( numComps, + numPhases, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + dt, + stencilWrapper, + compFlowAccessors.get( fields::flow::pressure{} ), + compFlowAccessors.get( fields::flow::gravityCoefficient{} ), + compFlowAccessors.get( fields::flow::phaseVolumeFraction{} ), + permeabilityAccessors.get( fields::permeability::permeability{} ), + permeabilityAccessors.get( fields::permeability::dPerm_dPressure{} ), + relPermAccessors.get( fields::relperm::phaseRelPerm{} ), + multiFluidAccessors.get( fields::multifluid::phaseViscosity{} ), + multiFluidAccessors.get( fields::multifluid::phaseDensity{} ), + multiFluidAccessors.get( fields::multifluid::phaseMassDensity{} ), + multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} ), + phaseOutfluxAccessor.toNestedView(), + compOutfluxAccessor.toNestedView() ); + } ); + } ); + + // Step 3: finalize the (cell-based) computation of the CFL numbers + real64 localMaxPhaseCFLNumber = 0.0; + real64 localMaxCompCFLNumber = 0.0; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView2d< real64 const, compflow::USD_PHASE > const & phaseOutflux = + subRegion.getField< fields::flow::phaseOutflux >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compOutflux = + subRegion.getField< fields::flow::componentOutflux >(); + + arrayView1d< real64 > const & phaseCFLNumber = subRegion.getField< fields::flow::phaseCFLNumber >(); + arrayView1d< real64 > const & compCFLNumber = subRegion.getField< fields::flow::componentCFLNumber >(); + + arrayView1d< real64 const > const & volume = subRegion.getElementVolume(); + + arrayView2d< real64 const, compflow::USD_COMP > const & compDens = + subRegion.getField< fields::flow::globalCompDensity >(); + arrayView2d< real64 const, compflow::USD_COMP > const compFrac = + subRegion.getField< fields::flow::globalCompFraction >(); + arrayView2d< real64, compflow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::flow::phaseVolumeFraction >(); + + Group const & constitutiveModels = subRegion.getGroup( ElementSubRegionBase::groupKeyStruct::constitutiveModelsString() ); + + string const & fluidName = subRegion.getReference< string >( CompositionalMultiphaseBase::viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = constitutiveModels.getGroup< MultiFluidBase >( fluidName ); + arrayView3d< real64 const, multifluid::USD_PHASE > const & phaseVisc = fluid.phaseViscosity(); + + string const & relpermName = subRegion.getReference< string >( CompositionalMultiphaseBase::viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relperm = constitutiveModels.getGroup< RelativePermeabilityBase >( relpermName ); + arrayView3d< real64 const, relperm::USD_RELPERM > const & phaseRelPerm = relperm.phaseRelPerm(); + arrayView4d< real64 const, relperm::USD_RELPERM_DS > const & dPhaseRelPerm_dPhaseVolFrac = relperm.dPhaseRelPerm_dPhaseVolFraction(); + + string const & solidName = subRegion.getReference< string >( CompositionalMultiphaseBase::viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & solid = constitutiveModels.getGroup< CoupledSolidBase >( solidName ); + arrayView2d< real64 const > const & porosity = solid.getPorosity(); + + real64 subRegionMaxPhaseCFLNumber = 0.0; + real64 subRegionMaxCompCFLNumber = 0.0; + + isothermalCompositionalMultiphaseBaseKernels::KernelLaunchSelector2 + < isothermalCompositionalMultiphaseFVMKernels::CFLKernel >( numComps, numPhases, + subRegion.size(), + volume, + porosity, + compDens, + compFrac, + phaseVolFrac, + phaseRelPerm, + dPhaseRelPerm_dPhaseVolFrac, + phaseVisc, + phaseOutflux, + compOutflux, + phaseCFLNumber, + compCFLNumber, + subRegionMaxPhaseCFLNumber, + subRegionMaxCompCFLNumber ); + + localMaxPhaseCFLNumber = LvArray::math::max( localMaxPhaseCFLNumber, subRegionMaxPhaseCFLNumber ); + localMaxCompCFLNumber = LvArray::math::max( localMaxCompCFLNumber, subRegionMaxCompCFLNumber ); + + } ); + } ); + + maxPhaseCFL = MpiWrapper::max( localMaxPhaseCFLNumber ); + maxCompCFL = MpiWrapper::max( localMaxCompCFLNumber ); + +} + //START_SPHINX_INCLUDE_01 REGISTER_CATALOG_ENTRY( PhysicsSolverBase, CompositionalMultiphaseFVM, string const &, Group * const ) //END_SPHINX_INCLUDE_01 diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp index f14b2436740..896dc87b7f1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp @@ -25,6 +25,26 @@ namespace geos { +/** + * @brief Options for density treatment in gravity + */ +enum class GravityDensityScheme : integer +{ + ArithmeticAverage, ///< average phase density is computed using simple arithmetic average: + /// rho_ave = 0.5 * (rho_i + rho_j) + PhasePresence, ///< average phase density is computed using checking for phase presence: + /// rho_ave = 0.5 * (rho_i + rho_j) if phase is present in both cells i and j + /// = rho_i if phase is present in only cell i + /// = rho_j if phase is present in only cell j +}; + +/** + * @brief Strings for options for density treatment in gravity + */ +ENUM_STRINGS( GravityDensityScheme, + "ArithmeticAverage", + "PhasePresence" ); + /** * @class CompositionalMultiphaseFVM * @@ -85,6 +105,11 @@ class CompositionalMultiphaseFVM : public CompositionalMultiphaseBase */ /**@{*/ + virtual void + registerDataOnMesh( Group & MeshBodies ) override; + + virtual void registerDataForCFL( Group & meshBodies ) override; + virtual void setupDofs( DomainPartition const & domain, DofManager & dofManager ) const override; @@ -150,6 +175,20 @@ class CompositionalMultiphaseFVM : public CompositionalMultiphaseBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const override; + virtual void computeCFLNumbers( DomainPartition & domain, + real64 const & dt, + real64 & maxPhaseCFL, + real64 & maxCompCFL ) override; + + /** + * @brief function to set the next time step size + * @param[in] currentDt the current time step size + * @param[in] domain the domain object + * @return the prescribed time step size + */ + real64 setNextDt( real64 const & currentDt, + DomainPartition & domain ) override; + struct viewKeyStruct : CompositionalMultiphaseBase::viewKeyStruct { // DBC parameters @@ -162,7 +201,8 @@ class CompositionalMultiphaseFVM : public CompositionalMultiphaseBase static constexpr char const * contMultiplierDBCString() { return "contMultiplierDBC"; } // nonlinear solver parameters - static constexpr char const * scalingTypeString() { return "scalingType"; } + static constexpr char const * scalingTypeString() { return "scalingType"; } + static constexpr char const * gravityDensitySchemeString() { return "gravityDensityScheme"; } }; /** @@ -191,8 +231,10 @@ class CompositionalMultiphaseFVM : public CompositionalMultiphaseBase virtual void postInputInitialization() override; - virtual void - initializePreSubGroups() override; + virtual void initializePreSubGroups() override; + + real64 setNextDtBasedOnCFL( real64 const & currentDt, + DomainPartition & domain ); struct DBCParameters { @@ -215,6 +257,12 @@ class CompositionalMultiphaseFVM : public CompositionalMultiphaseBase /// Solution scaling type ScalingType m_scalingType; + /// scheme for density treatment in gravity + GravityDensityScheme m_gravityDensityScheme; + + /// the targeted CFL for timestep + real64 m_targetFlowCFL; + private: /** diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp index 254c2a72a17..7f44f5f5c16 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp @@ -142,22 +142,13 @@ void CompositionalMultiphaseStatistics::registerDataOnMesh( Group & meshBodies ) } } } - - // if we have to compute CFL numbers later, we need to register additional variables - if( m_computeCFLNumbers ) - { - elemManager.forElementSubRegions( regionNames, [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - subRegion.registerField< fields::flow::phaseOutflux >( getName() ). - reference().resizeDimension< 1 >( numPhases ); - subRegion.registerField< fields::flow::componentOutflux >( getName() ). - reference().resizeDimension< 1 >( numComps ); - subRegion.registerField< fields::flow::phaseCFLNumber >( getName() ); - subRegion.registerField< fields::flow::componentCFLNumber >( getName() ); - } ); - } } ); + + // if we have to compute CFL numbers later, we need to register additional variables + if( m_computeCFLNumbers ) + { + m_solver->registerDataForCFL( meshBodies ); + } } bool CompositionalMultiphaseStatistics::execute( real64 const time_n, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/AccumulationKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/AccumulationKernel.hpp index c88ec507449..e283affcf43 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/AccumulationKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/AccumulationKernel.hpp @@ -474,8 +474,7 @@ class AccumulationKernelFactory createAndLaunch( integer const numComps, integer const numPhases, globalIndex const rankOffset, - integer const useTotalMassEquation, - integer const useSimpleAccumulation, + BitFlags< KernelFlags > kernelFlags, string const dofKey, ElementSubRegionBase const & subRegion, constitutive::MultiFluidBase const & fluid, @@ -488,12 +487,6 @@ class AccumulationKernelFactory integer constexpr NUM_COMP = NC(); integer constexpr NUM_DOF = NC()+1; - BitFlags< KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( KernelFlags::TotalMassEquation ); - if( useSimpleAccumulation ) - kernelFlags.set( KernelFlags::SimpleAccumulation ); - AccumulationKernel< NUM_COMP, NUM_DOF > kernel( numPhases, rankOffset, dofKey, subRegion, fluid, solid, localMatrix, localRhs, kernelFlags ); AccumulationKernel< NUM_COMP, NUM_DOF >::template launch< POLICY >( subRegion.size(), kernel ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/C1PPUPhaseFlux.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/C1PPUPhaseFlux.hpp index 6b31d7b9165..f92335dd726 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/C1PPUPhaseFlux.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/C1PPUPhaseFlux.hpp @@ -79,7 +79,7 @@ struct C1PPUPhaseFlux compute( integer const numPhase, integer const ip, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const ( &seri )[numFluxSupportPoints], localIndex const ( &sesri )[numFluxSupportPoints], localIndex const ( &sei )[numFluxSupportPoints], @@ -111,8 +111,9 @@ struct C1PPUPhaseFlux real64 dPresGrad_dC[numFluxSupportPoints][numComp]{}; real64 dGravHead_dP[numFluxSupportPoints]{}; real64 dGravHead_dC[numFluxSupportPoints][numComp]{}; - PotGrad::compute< numComp, numFluxSupportPoints >( numPhase, ip, hasCapPressure, useNewGravity, seri, sesri, sei, trans, dTrans_dPres, pres, - gravCoef, phaseVolFrac, dPhaseVolFrac, dCompFrac_dCompDens, phaseMassDens, dPhaseMassDens, + PotGrad::compute< numComp, numFluxSupportPoints >( numPhase, ip, hasCapPressure, checkPhasePresenceInGravity, + seri, sesri, sei, trans, dTrans_dPres, pres, gravCoef, + phaseVolFrac, dPhaseVolFrac, dCompFrac_dCompDens, phaseMassDens, dPhaseMassDens, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, potGrad, dPresGrad_dP, dPresGrad_dC, dGravHead_dP, dGravHead_dC ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.cpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.cpp index 0b34792763f..ab2b2838d7b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.cpp @@ -39,7 +39,7 @@ inline void CFLFluxKernel:: compute( integer const numPhases, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const stencilSize, real64 const dt, arraySlice1d< localIndex const > const seri, @@ -69,7 +69,7 @@ CFLFluxKernel:: real64 gravHead{}; // calculate quantities on primary connected cells - calculateMeanDensity( useNewGravity, ip, stencilSize, seri, sesri, sei, phaseVolFrac, phaseMassDens, densMean ); + calculateMeanDensity( checkPhasePresenceInGravity, ip, stencilSize, seri, sesri, sei, phaseVolFrac, phaseMassDens, densMean ); //***** calculation of phase volumetric flux ***** @@ -123,7 +123,7 @@ CFLFluxKernel:: GEOS_HOST_DEVICE inline void -CFLFluxKernel::calculateMeanDensity( integer const useNewGravity, integer const ip, localIndex const stencilSize, +CFLFluxKernel::calculateMeanDensity( integer const checkPhasePresenceInGravity, integer const ip, localIndex const stencilSize, arraySlice1d< localIndex const > const seri, arraySlice1d< localIndex const > const sesri, arraySlice1d< localIndex const > const sei, @@ -139,7 +139,7 @@ CFLFluxKernel::calculateMeanDensity( integer const useNewGravity, integer const localIndex const ei = sei[i]; bool const phaseExists = (phaseVolFrac[er][esr][ei][ip] > 0); - if( useNewGravity && !phaseExists ) + if( checkPhasePresenceInGravity && !phaseExists ) { continue; } @@ -156,7 +156,7 @@ CFLFluxKernel::calculateMeanDensity( integer const useNewGravity, integer const template< integer NC, typename STENCILWRAPPER_TYPE > void CFLFluxKernel:: launch( integer const numPhases, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, real64 const dt, STENCILWRAPPER_TYPE const & stencilWrapper, ElementViewConst< arrayView1d< real64 const > > const & pres, @@ -189,7 +189,7 @@ void CFLFluxKernel:: dTrans_dPres ); CFLFluxKernel::compute< NC >( numPhases, - useNewGravity, + checkPhasePresenceInGravity, sei[iconn].size(), dt, seri[iconn], @@ -213,7 +213,7 @@ void CFLFluxKernel:: template \ void CFLFluxKernel:: \ launch< NC, STENCILWRAPPER_TYPE >( integer const numPhases, \ - integer const useNewGravity, \ + integer const checkPhasePresenceInGravity, \ real64 const dt, \ STENCILWRAPPER_TYPE const & stencil, \ ElementViewConst< arrayView1d< real64 const > > const & pres, \ diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.hpp index a13c9170bc6..b4574fe1ece 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/CFLKernel.hpp @@ -87,7 +87,7 @@ struct CFLFluxKernel template< integer NC > GEOS_HOST_DEVICE inline static void compute( integer const numPhases, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const stencilSize, real64 const dt, arraySlice1d< localIndex const > const seri, @@ -106,7 +106,8 @@ struct CFLFluxKernel ElementView< arrayView2d< real64, compflow::USD_COMP > > const & compOutflux ); GEOS_HOST_DEVICE inline static void - calculateMeanDensity( integer const useNewGravity, integer const ip, localIndex const stencilSize, + calculateMeanDensity( integer const checkPhasePresenceInGravity, + integer const ip, localIndex const stencilSize, arraySlice1d< localIndex const > const seri, arraySlice1d< localIndex const > const sesri, arraySlice1d< localIndex const > const sei, @@ -117,7 +118,7 @@ struct CFLFluxKernel template< integer NC, typename STENCILWRAPPER_TYPE > static void launch( integer const numPhases, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, real64 const dt, STENCILWRAPPER_TYPE const & stencil, ElementViewConst< arrayView1d< real64 const > > const & pres, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DiffusionDispersionFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DiffusionDispersionFluxComputeKernel.hpp index f4293d5f83d..a078cb402d1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DiffusionDispersionFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DiffusionDispersionFluxComputeKernel.hpp @@ -725,9 +725,7 @@ class DiffusionDispersionFluxComputeKernelFactory integer const numPhases, globalIndex const rankOffset, string const & dofKey, - integer const hasDiffusion, - integer const hasDispersion, - integer const useTotalMassEquation, + BitFlags< KernelFlags > kernelFlags, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -744,10 +742,6 @@ class DiffusionDispersionFluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - BitFlags< KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( KernelFlags::TotalMassEquation ); - using kernelType = DiffusionDispersionFluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >; typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); @@ -760,7 +754,8 @@ class DiffusionDispersionFluxComputeKernelFactory diffusionAccessors, dispersionAccessors, porosityAccessors, dt, localMatrix, localRhs, kernelFlags ); kernelType::template launch< POLICY >( stencilWrapper.size(), - hasDiffusion, hasDispersion, + kernelFlags.isSet( KernelFlags::Diffusion ), + kernelFlags.isSet( KernelFlags::Dispersion ), kernel ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DissipationFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DissipationFluxComputeKernel.hpp index 3d09e878fbf..b3544545b66 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DissipationFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/DissipationFluxComputeKernel.hpp @@ -185,7 +185,7 @@ class FluxComputeKernel : public isothermalCompositionalMultiphaseFVMKernels::Fl // // We use the lambda below (called **inside** the phase loop of the base computeFlux) to compute dissipation terms Base::computeFlux( iconn, stack, [&] ( integer const ip, - integer const GEOS_UNUSED_PARAM( useNewGravity ), + integer const GEOS_UNUSED_PARAM( checkPhasePresenceInGravity ), localIndex const (&k)[2], localIndex const (&seri)[2], localIndex const (&sesri)[2], @@ -349,8 +349,7 @@ class FluxComputeKernelFactory integer const numPhases, globalIndex const rankOffset, string const & dofKey, - integer const hasCapPressure, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -374,12 +373,6 @@ class FluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; - if( hasCapPressure ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::CapPressure ); - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); - using KERNEL_TYPE = FluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >; typename KERNEL_TYPE::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename KERNEL_TYPE::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernel.hpp index 83af007a79f..78271f54416 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernel.hpp @@ -277,7 +277,7 @@ class FluxComputeKernel : public FluxComputeKernelBase ( m_numPhases, ip, m_kernelFlags.isSet( KernelFlags::CapPressure ), - m_kernelFlags.isSet( KernelFlags::NewGravity ), + m_kernelFlags.isSet( KernelFlags::CheckPhasePresenceInGravity ), seri, sesri, sei, trans, dTrans_dPres, @@ -304,7 +304,7 @@ class FluxComputeKernel : public FluxComputeKernelBase ( m_numPhases, ip, m_kernelFlags.isSet( KernelFlags::CapPressure ), - m_kernelFlags.isSet( KernelFlags::NewGravity ), + m_kernelFlags.isSet( KernelFlags::CheckPhasePresenceInGravity ), seri, sesri, sei, trans, dTrans_dPres, @@ -331,7 +331,7 @@ class FluxComputeKernel : public FluxComputeKernelBase ( m_numPhases, ip, m_kernelFlags.isSet( KernelFlags::CapPressure ), - m_kernelFlags.isSet( KernelFlags::NewGravity ), + m_kernelFlags.isSet( KernelFlags::CheckPhasePresenceInGravity ), seri, sesri, sei, trans, dTrans_dPres, @@ -355,12 +355,12 @@ class FluxComputeKernel : public FluxComputeKernelBase // call the lambda in the phase loop to allow the reuse of the phase fluxes and their derivatives // possible use: assemble the derivatives wrt temperature, and the flux term of the energy equation for this phase - compFluxKernelOp( ip, m_kernelFlags.isSet( KernelFlags::NewGravity ), + compFluxKernelOp( ip, m_kernelFlags.isSet( KernelFlags::CheckPhasePresenceInGravity ), k, seri, sesri, sei, connectionIndex, k_up, seri[k_up], sesri[k_up], sei[k_up], potGrad, phaseFlux, dPhaseFlux_dP, dPhaseFlux_dC ); - } // loop over phases + } // loop over phases /// populate local flux vector and derivatives for( integer ic = 0; ic < numComp; ++ic ) @@ -527,10 +527,7 @@ class FluxComputeKernelFactory integer const numPhases, globalIndex const rankOffset, string const & dofKey, - integer const hasCapPressure, - integer const useTotalMassEquation, - integer const useNewGravity, - UpwindingParameters upwindingParams, + BitFlags< KernelFlags > kernelFlags, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -547,20 +544,6 @@ class FluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - BitFlags< KernelFlags > kernelFlags; - if( hasCapPressure ) - kernelFlags.set( KernelFlags::CapPressure ); - if( useTotalMassEquation ) - kernelFlags.set( KernelFlags::TotalMassEquation ); - if( useNewGravity ) - kernelFlags.set( KernelFlags::NewGravity ); - if( upwindingParams.upwindingScheme == UpwindingScheme::C1PPU && - isothermalCompositionalMultiphaseFVMKernelUtilities::epsC1PPU > 0 ) - kernelFlags.set( KernelFlags::C1PPU ); - else if( upwindingParams.upwindingScheme == UpwindingScheme::IHU ) - kernelFlags.set( KernelFlags::IHU ); - - using kernelType = FluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >; typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernelBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernelBase.hpp index ff96044c991..c7b85da8d97 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernelBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/FluxComputeKernelBase.hpp @@ -45,17 +45,19 @@ enum class KernelFlags { /// Flag to specify whether capillary pressure is used or not CapPressure = 1 << 0, // 1 + /// Flag to specify whether diffusion is used or not + Diffusion = 1 << 1, // 2 + /// Flag to specify whether dispersion is used or not + Dispersion = 1 << 2, // 4 /// Flag indicating whether total mass equation is formed or not - TotalMassEquation = 1 << 1, // 2 - /// Flag indicating whether new gravity treatment is used or not - NewGravity = 1 << 2, // 4 + TotalMassEquation = 1 << 3, // 8 + /// Flag indicating whether gravity treatment is checking phase presence or not + CheckPhasePresenceInGravity = 1 << 4, // 16 /// Flag indicating whether C1-PPU is used or not - C1PPU = 1 << 3, // 8 + C1PPU = 1 << 5, // 32 /// Flag indicating whether IHU is used or not - IHU = 1 << 4 // 16 + IHU = 1 << 6 // 64 /// Add more flags like that if needed: - // Flag6 = 1 << 5, // 32 - // Flag7 = 1 << 6, // 64 // Flag8 = 1 << 7 //128 }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/IHUPhaseFlux.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/IHUPhaseFlux.hpp index 98ee6989a18..9365a96c830 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/IHUPhaseFlux.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/IHUPhaseFlux.hpp @@ -140,7 +140,7 @@ upwindMobilityGravity( localIndex const numPhase, ElementViewConst< arrayView3d< real64 const, constitutive::cappres::USD_CAPPRES > > const & phaseCapPressure, ElementViewConst< arrayView4d< real64 const, constitutive::cappres::USD_CAPPRES_DS > > const & dPhaseCapPressure_dPhaseVolFrac, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex & upwindDir, real64 & mobility, real64( &dMobility_dP), @@ -176,7 +176,7 @@ upwindMobilityGravity( localIndex const numPhase, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, hasCapPressure, - useNewGravity, + checkPhasePresenceInGravity, upwindDir ); localIndex const er_up = seri[upwindDir]; @@ -408,7 +408,7 @@ computeFractionalFlowGravity( localIndex const numPhase, ElementViewConst< arrayView3d< real64 const, constitutive::cappres::USD_CAPPRES > > const & phaseCapPressure, ElementViewConst< arrayView4d< real64 const, constitutive::cappres::USD_CAPPRES_DS > > const & dPhaseCapPressure_dPhaseVolFrac, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex & k_up_main, real64 & fractionalFlow, real64 ( & dFractionalFlow_dP)[numFluxSupportPoints], @@ -459,7 +459,7 @@ computeFractionalFlowGravity( localIndex const numPhase, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, hasCapPressure, - useNewGravity, + checkPhasePresenceInGravity, k_up, mob, dMob_dP, @@ -662,7 +662,7 @@ struct computePotentialGravity GEOS_HOST_DEVICE static void compute( localIndex const GEOS_UNUSED_PARAM( numPhase ), localIndex const ip, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const (&seri)[numFluxSupportPoints], localIndex const (&sesri)[numFluxSupportPoints], localIndex const (&sei)[numFluxSupportPoints], @@ -702,7 +702,9 @@ struct computePotentialGravity } } - calculateMeanDensity( useNewGravity, ip, seri, sesri, sei, phaseVolFrac, dCompFrac_dCompDens, phaseMassDens, dPhaseMassDens, dProp_dComp, + calculateMeanDensity( checkPhasePresenceInGravity, ip, seri, sesri, sei, + phaseVolFrac, dCompFrac_dCompDens, + phaseMassDens, dPhaseMassDens, dProp_dComp, densMean, dDensMean_dPres, dDensMean_dComp ); // compute potential difference MPFA-style @@ -730,7 +732,7 @@ struct computePotentialGravity template< localIndex numComp, localIndex numFluxSupportPoints > GEOS_HOST_DEVICE - static void calculateMeanDensity( integer const useNewGravity, + static void calculateMeanDensity( integer const checkPhasePresenceInGravity, localIndex const ip, localIndex const (&seri)[numFluxSupportPoints], localIndex const (&sesri)[numFluxSupportPoints], @@ -750,7 +752,7 @@ struct computePotentialGravity localIndex const ei = sei[i]; bool const phaseExists = (phaseVolFrac[er][esr][ei][ip] > 0); - if( useNewGravity && !phaseExists ) + if( checkPhasePresenceInGravity && !phaseExists ) { continue; } @@ -878,7 +880,7 @@ static void computePotentialFluxesGravity( localIndex const numPhase, ElementViewConst< arrayView3d< real64 const, constitutive::cappres::USD_CAPPRES > > const & phaseCapPressure, ElementViewConst< arrayView4d< real64 const, constitutive::cappres::USD_CAPPRES_DS > > const & dPhaseCapPressure_dPhaseVolFrac, localIndex const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex( &k_up), localIndex (&k_up_o), real64 & phaseFlux, @@ -898,7 +900,7 @@ static void computePotentialFluxesGravity( localIndex const numPhase, // UpwindHelpers::computePotentialGravity::compute< numComp, numFluxSupportPoints >( numPhase, ip, - useNewGravity, + checkPhasePresenceInGravity, seri, sesri, sei, @@ -944,7 +946,7 @@ static void computePotentialFluxesGravity( localIndex const numPhase, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, hasCapPressure, - useNewGravity, + checkPhasePresenceInGravity, k_up, fflow, dFflow_dP, @@ -964,7 +966,7 @@ static void computePotentialFluxesGravity( localIndex const numPhase, //Fetch pot for phase j!=i defined as \rho_j g dz/dx UpwindHelpers::computePotentialGravity::compute< numComp, numFluxSupportPoints >( numPhase, jp, - useNewGravity, + checkPhasePresenceInGravity, seri, sesri, sei, @@ -1012,7 +1014,7 @@ static void computePotentialFluxesGravity( localIndex const numPhase, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, hasCapPressure, - useNewGravity, + checkPhasePresenceInGravity, k_up_o, mobOther, dMobOther_dP, @@ -1341,7 +1343,7 @@ class UpwindScheme ElementViewConst< arrayView3d< real64 const, constitutive::cappres::USD_CAPPRES > > const & phaseCapPressure, ElementViewConst< arrayView4d< real64 const, constitutive::cappres::USD_CAPPRES_DS > > const & dPhaseCapPressure_dPhaseVolFrac, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex & upwindDir ) { @@ -1368,7 +1370,7 @@ class UpwindScheme phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, hasCapPressure, - useNewGravity, + checkPhasePresenceInGravity, pot ); //all definition has been changed to fit pot>0 => first cell is upstream @@ -1567,9 +1569,8 @@ class HybridUpwind : public UpwindScheme ElementViewConst< arrayView3d< real64 const, constitutive::cappres::USD_CAPPRES > > const & phaseCapPressure, ElementViewConst< arrayView4d< real64 const, constitutive::cappres::USD_CAPPRES_DS > > const & dPhaseCapPressure_dPhaseVolFrac, integer const GEOS_UNUSED_PARAM( hasCapPressure ), - integer const useNewGravity, - real64 & potential - ) + integer const checkPhasePresenceInGravity, + real64 & potential ) { //Form total velocity @@ -1587,7 +1588,7 @@ class HybridUpwind : public UpwindScheme UpwindHelpers::computePotentialGravity::compute< numComp, numFluxSupportPoints >( numPhase, ipp, - useNewGravity, + checkPhasePresenceInGravity, seri, sesri, sei, @@ -1715,7 +1716,7 @@ struct IHUPhaseFlux compute( integer const numPhase, integer const ip, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const ( &seri )[numFluxSupportPoints], localIndex const ( &sesri )[numFluxSupportPoints], localIndex const ( &sei )[numFluxSupportPoints], @@ -1763,7 +1764,8 @@ struct IHUPhaseFlux for( integer jp = 0; jp < numPhase; ++jp ) { - PPUPhaseFlux::compute( numPhase, jp, hasCapPressure, useNewGravity, + PPUPhaseFlux::compute( numPhase, jp, + hasCapPressure, checkPhasePresenceInGravity, seri, sesri, sei, trans, dTrans_dPres, pres, gravCoef, @@ -1917,7 +1919,7 @@ struct IHUPhaseFlux phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, hasCapPressure, - useNewGravity, + checkPhasePresenceInGravity, k_up_g, k_up_og, gravitationalPhaseFlux, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PPUPhaseFlux.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PPUPhaseFlux.hpp index 483e8c4c2ba..468adabb4b1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PPUPhaseFlux.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PPUPhaseFlux.hpp @@ -75,7 +75,7 @@ struct PPUPhaseFlux compute( integer const numPhase, integer const ip, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const ( &seri )[numFluxSupportPoints], localIndex const ( &sesri )[numFluxSupportPoints], localIndex const ( &sei )[numFluxSupportPoints], @@ -107,10 +107,12 @@ struct PPUPhaseFlux real64 dPresGrad_dC[numFluxSupportPoints][numComp]{}; real64 dGravHead_dP[numFluxSupportPoints]{}; real64 dGravHead_dC[numFluxSupportPoints][numComp]{}; - PotGrad::compute< numComp, numFluxSupportPoints >( numPhase, ip, hasCapPressure, useNewGravity, seri, sesri, sei, trans, dTrans_dPres, pres, - gravCoef, phaseVolFrac, dPhaseVolFrac, dCompFrac_dCompDens, phaseMassDens, dPhaseMassDens, - phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, potGrad, dPresGrad_dP, - dPresGrad_dC, dGravHead_dP, dGravHead_dC ); + PotGrad::compute< numComp, numFluxSupportPoints >( numPhase, ip, hasCapPressure, checkPhasePresenceInGravity, + seri, sesri, sei, trans, dTrans_dPres, pres, + gravCoef, phaseVolFrac, dPhaseVolFrac, dCompFrac_dCompDens, + phaseMassDens, dPhaseMassDens, + phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac, potGrad, + dPresGrad_dP, dPresGrad_dC, dGravHead_dP, dGravHead_dC ); // *** upwinding *** diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PotGrad.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PotGrad.hpp index 2b4522343e3..b783b061712 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PotGrad.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/PotGrad.hpp @@ -46,7 +46,7 @@ struct PotGrad compute ( integer const numPhase, integer const ip, integer const hasCapPressure, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const ( &seri )[numFluxSupportPoints], localIndex const ( &sesri )[numFluxSupportPoints], localIndex const ( &sei )[numFluxSupportPoints], @@ -88,7 +88,11 @@ struct PotGrad real64 gravHead = 0.0; real64 dCapPressure_dC[numComp]{}; - calculateMeanDensity( useNewGravity, ip, seri, sesri, sei, phaseVolFrac, dCompFrac_dCompDens, phaseMassDens, dPhaseMassDens, densMean, dDensMean_dP, dDensMean_dC ); + calculateMeanDensity( checkPhasePresenceInGravity, ip, + seri, sesri, sei, + phaseVolFrac, dCompFrac_dCompDens, + phaseMassDens, dPhaseMassDens, + densMean, dDensMean_dP, dDensMean_dC ); /// compute the TPFA potential difference for( integer i = 0; i < numFluxSupportPoints; i++ ) @@ -157,7 +161,7 @@ struct PotGrad template< integer numComp, integer numFluxSupportPoints > GEOS_HOST_DEVICE static void - calculateMeanDensity( integer const useNewGravity, + calculateMeanDensity( integer const checkPhasePresenceInGravity, integer const ip, localIndex const ( &seri )[numFluxSupportPoints], localIndex const ( &sesri )[numFluxSupportPoints], @@ -178,7 +182,7 @@ struct PotGrad localIndex const ei = sei[i]; bool const phaseExists = (phaseVolFrac[er][esr][ei][ip] > 0); - if( useNewGravity && !phaseExists ) + if( checkPhasePresenceInGravity && !phaseExists ) { continue; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/StabilizedFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/StabilizedFluxComputeKernel.hpp index eb679f2942c..74332aaf862 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/StabilizedFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/StabilizedFluxComputeKernel.hpp @@ -193,7 +193,7 @@ class FluxComputeKernel : public isothermalCompositionalMultiphaseFVMKernels::Fl // // We use the lambda below (called **inside** the phase loop of the base computeFlux) to compute stabilization terms Base::computeFlux( iconn, stack, [&] ( integer const ip, - integer const GEOS_UNUSED_PARAM( useNewGravity ), + integer const GEOS_UNUSED_PARAM( checkPhasePresenceInGravity ), localIndex const (&k)[2], localIndex const (&seri)[2], localIndex const (&sesri)[2], @@ -327,8 +327,7 @@ class FluxComputeKernelFactory integer const numPhases, globalIndex const rankOffset, string const & dofKey, - integer const hasCapPressure, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -346,12 +345,6 @@ class FluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; - if( hasCapPressure ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::CapPressure ); - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); - using KERNEL_TYPE = FluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >; typename KERNEL_TYPE::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename KERNEL_TYPE::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalAccumulationKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalAccumulationKernel.hpp index 58d6aa12cf4..e5839bd023d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalAccumulationKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalAccumulationKernel.hpp @@ -311,7 +311,7 @@ class AccumulationKernelFactory createAndLaunch( localIndex const numComps, localIndex const numPhases, globalIndex const rankOffset, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, ElementSubRegionBase const & subRegion, constitutive::MultiFluidBase const & fluid, @@ -325,10 +325,6 @@ class AccumulationKernelFactory localIndex constexpr NUM_COMP = NC(); localIndex constexpr NUM_DOF = NC()+2; - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - AccumulationKernel< NUM_COMP, NUM_DOF > kernel( numPhases, rankOffset, dofKey, subRegion, fluid, solid, localMatrix, localRhs, kernelFlags ); AccumulationKernel< NUM_COMP, NUM_DOF >::template launch< POLICY >( subRegion.size(), kernel ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDiffusionDispersionFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDiffusionDispersionFluxComputeKernel.hpp index 957d98bee43..c5f2d67951d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDiffusionDispersionFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDiffusionDispersionFluxComputeKernel.hpp @@ -302,9 +302,7 @@ class DiffusionDispersionFluxComputeKernelFactory integer const numPhases, globalIndex const rankOffset, string const & dofKey, - integer const hasDiffusion, - integer const hasDispersion, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -322,10 +320,6 @@ class DiffusionDispersionFluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); - using kernelType = DiffusionDispersionFluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >; typename kernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename kernelType::MultiFluidAccessors multiFluidAccessors( elemManager, solverName ); @@ -338,7 +332,8 @@ class DiffusionDispersionFluxComputeKernelFactory diffusionAccessors, dispersionAccessors, porosityAccessors, dt, localMatrix, localRhs, kernelFlags ); kernelType::template launch< POLICY >( stencilWrapper.size(), - hasDiffusion, hasDispersion, + kernelFlags.isSet( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::Diffusion ), + kernelFlags.isSet( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::Dispersion ), kernel ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDirichletFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDirichletFluxComputeKernel.hpp index 5df89fc5e3e..009ab3ce63c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDirichletFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalDirichletFluxComputeKernel.hpp @@ -430,7 +430,7 @@ class DirichletFluxComputeKernelFactory createAndLaunch( integer const numComps, integer const numPhases, globalIndex const rankOffset, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, string const & dofKey, string const & solverName, FaceManager const & faceManager, @@ -453,11 +453,6 @@ class DirichletFluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - // for now, we neglect capillary pressure in the kernel - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); - using KernelType = DirichletFluxComputeKernel< NUM_COMP, NUM_DOF, typename FluidType::KernelWrapper >; typename KernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename KernelType::ThermalCompFlowAccessors thermalCompFlowAccessors( elemManager, solverName ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalFluxComputeKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalFluxComputeKernel.hpp index 519b1a538bb..1eb02a44f38 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalFluxComputeKernel.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/compositional/ThermalFluxComputeKernel.hpp @@ -197,7 +197,7 @@ class FluxComputeKernel : public isothermalCompositionalMultiphaseFVMKernels::Fl // such as potGrad, phaseFlux, and the indices of the upwind cell // We use the lambda below (called **inside** the phase loop of the base computeFlux) to access these variables Base::computeFlux( iconn, stack, [&] ( integer const ip, - integer const useNewGravity, + integer const checkPhasePresenceInGravity, localIndex const (&k)[2], localIndex const (&seri)[2], localIndex const (&sesri)[2], @@ -235,7 +235,7 @@ class FluxComputeKernel : public isothermalCompositionalMultiphaseFVMKernels::Fl localIndex const ei = sei[i]; bool const phaseExists = (m_phaseVolFrac[er_up][esr_up][ei_up][ip] > 0); - if( useNewGravity && !phaseExists ) + if( checkPhasePresenceInGravity && !phaseExists ) { continue; } @@ -522,8 +522,7 @@ class FluxComputeKernelFactory integer const numPhases, globalIndex const rankOffset, string const & dofKey, - integer const hasCapPressure, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -541,12 +540,6 @@ class FluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - BitFlags< isothermalCompositionalMultiphaseFVMKernels::KernelFlags > kernelFlags; - if( hasCapPressure ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::CapPressure ); - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseFVMKernels::KernelFlags::TotalMassEquation ); - using KernelType = FluxComputeKernel< NUM_COMP, NUM_DOF, STENCILWRAPPER >; typename KernelType::CompFlowAccessors compFlowAccessors( elemManager, solverName ); typename KernelType::ThermalCompFlowAccessors thermalCompFlowAccessors( elemManager, solverName ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 1f13044d87d..90f3a8677ec 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1090,6 +1090,9 @@ void CompositionalMultiphaseWell::assembleFluxTerms( real64 const & time, { GEOS_MARK_FUNCTION; + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; + if( m_useTotalMassEquation ) + kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); string const wellDofKey = dofManager.getKey( wellElementDofName()); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, @@ -1114,7 +1117,7 @@ void CompositionalMultiphaseWell::assembleFluxTerms( real64 const & time, createAndLaunch< parallelDevicePolicy<> >( numComponents, dt, dofManager.rankOffset(), - m_useTotalMassEquation, + kernelFlags, wellDofKey, well_controls, subRegion, @@ -1129,7 +1132,7 @@ void CompositionalMultiphaseWell::assembleFluxTerms( real64 const & time, createAndLaunch< parallelDevicePolicy<> >( numComponents, dt, dofManager.rankOffset(), - m_useTotalMassEquation, + kernelFlags, wellDofKey, well_controls, subRegion, @@ -1152,6 +1155,11 @@ void CompositionalMultiphaseWell::assembleAccumulationTerms( real64 const & time GEOS_MARK_FUNCTION; GEOS_UNUSED_VAR( time ); GEOS_UNUSED_VAR( dt ); + + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; + if( m_useTotalMassEquation ) + kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); + string const wellDofKey = dofManager.getKey( wellElementDofName() ); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, @@ -1177,7 +1185,7 @@ void CompositionalMultiphaseWell::assembleAccumulationTerms( real64 const & time numPhases, wellControls.isProducer(), dofManager.rankOffset(), - m_useTotalMassEquation, + kernelFlags, wellDofKey, subRegion, fluid, @@ -1192,7 +1200,7 @@ void CompositionalMultiphaseWell::assembleAccumulationTerms( real64 const & time numPhases, wellControls.isProducer(), dofManager.rankOffset(), - m_useTotalMassEquation, + kernelFlags, wellDofKey, subRegion, fluid, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index 41d63148bfb..aae86fcf48c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -1331,7 +1331,7 @@ class ElementBasedAssemblyKernelFactory localIndex const numPhases, integer const isProducer, globalIndex const rankOffset, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, WellElementSubRegion const & subRegion, constitutive::MultiFluidBase const & fluid, @@ -1344,10 +1344,6 @@ class ElementBasedAssemblyKernelFactory integer constexpr istherm = IS_THERMAL(); - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - ElementBasedAssemblyKernel< NUM_COMP, istherm > kernel( numPhases, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ); ElementBasedAssemblyKernel< NUM_COMP, istherm >::template @@ -1888,7 +1884,7 @@ class FaceBasedAssemblyKernelFactory createAndLaunch( integer const numComps, real64 const dt, globalIndex const rankOffset, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, WellControls const & wellControls, WellElementSubRegion const & subRegion, @@ -1899,14 +1895,7 @@ class FaceBasedAssemblyKernelFactory { integer constexpr NUM_COMP = NC(); - - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - using kernelType = FaceBasedAssemblyKernel< NUM_COMP, 0 >; - - kernelType kernel( dt, rankOffset, dofKey, wellControls, subRegion, localMatrix, localRhs, kernelFlags ); kernelType::template launch< POLICY >( subRegion.size(), kernel ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp index e7beb347528..6e225367a36 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp @@ -638,7 +638,7 @@ class ElementBasedAssemblyKernelFactory localIndex const numPhases, integer const isProducer, globalIndex const rankOffset, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, WellElementSubRegion const & subRegion, MultiFluidBase const & fluid, @@ -650,11 +650,6 @@ class ElementBasedAssemblyKernelFactory { localIndex constexpr NUM_COMP = NC(); - - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - ElementBasedAssemblyKernel< NUM_COMP > kernel( numPhases, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ); ElementBasedAssemblyKernel< NUM_COMP >::template @@ -1089,7 +1084,7 @@ class FaceBasedAssemblyKernelFactory createAndLaunch( integer const numComps, real64 const dt, globalIndex const rankOffset, - integer const useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, string const dofKey, WellControls const & wellControls, WellElementSubRegion const & subRegion, @@ -1101,15 +1096,7 @@ class FaceBasedAssemblyKernelFactory { integer constexpr NUM_COMP = NC(); - - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - - using kernelType = FaceBasedAssemblyKernel< NUM_COMP >; - - kernelType kernel( dt, rankOffset, dofKey, wellControls, subRegion, fluid, localMatrix, localRhs, kernelFlags ); kernelType::template launch< POLICY >( subRegion.size(), kernel ); } ); diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp index ea2c6f34b3e..afa810d945a 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp @@ -281,6 +281,10 @@ assembleCouplingTerms( real64 const time_n, this->getCatalogName(), this->getName() ), std::runtime_error ); + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; + if( Base::wellSolver()->useTotalMassEquation() ) + kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); + this->template forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel const & mesh, arrayView1d< string const > const & regionNames ) @@ -322,7 +326,6 @@ assembleCouplingTerms( real64 const time_n, string const wellDofKey = dofManager.getKey( Base::wellSolver()->wellElementDofName() ); areWellsShut = 0; - integer useTotalMassEquation=Base::wellSolver()->useTotalMassEquation(); integer numCrossflowPerforations=0; if( isThermal ( ) ) { @@ -337,7 +340,7 @@ assembleCouplingTerms( real64 const time_n, resDofNumber, perforationData, fluid, - useTotalMassEquation, + kernelFlags, detectCrossflow, numCrossflowPerforations, localRhs, @@ -355,7 +358,7 @@ assembleCouplingTerms( real64 const time_n, resDofNumber, perforationData, fluid, - useTotalMassEquation, + kernelFlags, detectCrossflow, numCrossflowPerforations, localRhs, diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp index 5fdb80fdf62..d1d7a131817 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp @@ -306,7 +306,7 @@ class IsothermalCompositionalMultiPhaseFluxKernelFactory ElementRegionManager::ElementViewConst< arrayView1d< globalIndex const > > const resDofNumber, PerforationData const * const perforationData, MultiFluidBase const & fluid, - integer const & useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, bool const & detectCrossflow, integer & numCrossFlowPerforations, arrayView1d< real64 > const & localRhs, @@ -317,16 +317,9 @@ class IsothermalCompositionalMultiPhaseFluxKernelFactory { integer constexpr NUM_COMP = NC(); - - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - - using kernelType = IsothermalCompositionalMultiPhaseFluxKernel< NUM_COMP, 0 >; - - - kernelType kernel( dt, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags ); + kernelType kernel( dt, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, + fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags ); kernelType::template launch< POLICY >( perforationData->size(), kernel ); } ); @@ -559,7 +552,7 @@ class ThermalCompositionalMultiPhaseFluxKernelFactory ElementRegionManager::ElementViewConst< arrayView1d< globalIndex const > > const resDofNumber, PerforationData const * const perforationData, MultiFluidBase const & fluid, - integer const & useTotalMassEquation, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, bool const & detectCrossflow, integer & numCrossFlowPerforations, arrayView1d< real64 > const & localRhs, @@ -570,16 +563,9 @@ class ThermalCompositionalMultiPhaseFluxKernelFactory { integer constexpr NUM_COMP = NC(); - - BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; - if( useTotalMassEquation ) - kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - - using kernelType = ThermalCompositionalMultiPhaseFluxKernel< NUM_COMP, 1 >; - - - kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags ); + kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, + fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags ); kernelType::template launch< POLICY >( perforationData->size(), kernel ); } ); From a8a57c707365cbe47e9f7e14fa62e25fbdd7226e Mon Sep 17 00:00:00 2001 From: Ryan Aronson Date: Tue, 7 Jan 2025 14:32:12 -0800 Subject: [PATCH 2/3] feat: plastic strain output (#3384) --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 + .../constitutive/solid/ElasticIsotropic.hpp | 57 ++++++++++++-- .../ElasticIsotropicPressureDependent.hpp | 59 +++++++++++++++ .../constitutive/solid/ElasticOrthotropic.hpp | 75 +++++++++++++++++++ .../solid/ElasticTransverseIsotropic.hpp | 70 +++++++++++++++++ .../constitutive/solid/SolidBase.hpp | 18 +++++ .../solidMechanics/SolidMechanicsFields.hpp | 8 ++ .../SolidMechanicsLagrangianFEM.cpp | 38 +++++++--- .../SolidMechanicsStateReset.cpp | 10 +++ .../solidMechanics/kernels/StrainHelper.hpp | 71 ++++++++++++++---- 11 files changed, 376 insertions(+), 36 deletions(-) diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 6f9b1951cf3..6009de53427 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3486-9492-f0c817c + baseline: integratedTests/baseline_integratedTests-pr3384-9542-4e0f693 allow_fail: all: '' streak: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index d2d18fba2d3..26bf74a58a5 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 #3384 (2024-01-07) +===================== +Added plastic strain output. + PR #3486 (2025-01-06) ===================== useNewGravity became gravityDensityScheme. diff --git a/src/coreComponents/constitutive/solid/ElasticIsotropic.hpp b/src/coreComponents/constitutive/solid/ElasticIsotropic.hpp index bed64cb6e6a..97573fce5f3 100644 --- a/src/coreComponents/constitutive/solid/ElasticIsotropic.hpp +++ b/src/coreComponents/constitutive/solid/ElasticIsotropic.hpp @@ -135,6 +135,11 @@ class ElasticIsotropicUpdates : public SolidBaseUpdates localIndex const q, real64 ( &elasticStrain )[6] ) const override final; + GEOS_HOST_DEVICE + virtual void getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( &elasticStrainInc )[6] ) const override final; + GEOS_HOST_DEVICE virtual real64 getBulkModulus( localIndex const k ) const override final { @@ -171,6 +176,13 @@ class ElasticIsotropicUpdates : public SolidBaseUpdates protected: + GEOS_HOST_DEVICE + virtual void computeElasticStrain( localIndex const k, + localIndex const q, + real64 const ( &stress )[6], + real64 ( &elasticStrainInc )[6] ) const; + + /// A reference to the ArrayView holding the bulk modulus for each element. arrayView1d< real64 const > const m_bulkModulus; @@ -210,24 +222,53 @@ void ElasticIsotropicUpdates::getElasticStiffness( localIndex const k, } +GEOS_HOST_DEVICE +inline +void ElasticIsotropicUpdates::computeElasticStrain( localIndex const k, + localIndex const q, + real64 const ( &stress )[6], + real64 ( & elasticStrain)[6] ) const +{ + GEOS_UNUSED_VAR( q ); + real64 const E = conversions::bulkModAndShearMod::toYoungMod( m_bulkModulus[k], m_shearModulus[k] ); + real64 const nu = conversions::bulkModAndShearMod::toPoissonRatio( m_bulkModulus[k], m_shearModulus[k] ); + + elasticStrain[0] = ( stress[0] - nu*stress[1] - nu*stress[2])/E; + elasticStrain[1] = (-nu*stress[0] + stress[1] - nu*stress[2])/E; + elasticStrain[2] = (-nu*stress[0] - nu*stress[1] + stress[2])/E; + + elasticStrain[3] = stress[3] / m_shearModulus[k]; + elasticStrain[4] = stress[4] / m_shearModulus[k]; + elasticStrain[5] = stress[5] / m_shearModulus[k]; +} + GEOS_HOST_DEVICE inline void ElasticIsotropicUpdates::getElasticStrain( localIndex const k, localIndex const q, real64 ( & elasticStrain)[6] ) const { - real64 const E = conversions::bulkModAndShearMod::toYoungMod( m_bulkModulus[k], m_shearModulus[k] ); - real64 const nu = conversions::bulkModAndShearMod::toPoissonRatio( m_bulkModulus[k], m_shearModulus[k] ); - elasticStrain[0] = ( m_newStress[k][q][0] - nu*m_newStress[k][q][1] - nu*m_newStress[k][q][2])/E; - elasticStrain[1] = (-nu*m_newStress[k][q][0] + m_newStress[k][q][1] - nu*m_newStress[k][q][2])/E; - elasticStrain[2] = (-nu*m_newStress[k][q][0] - nu*m_newStress[k][q][1] + m_newStress[k][q][2])/E; + real64 stress[6] = {m_newStress[k][q][0], m_newStress[k][q][1], m_newStress[k][q][2], m_newStress[k][q][3], m_newStress[k][q][4], m_newStress[k][q][5]}; + + computeElasticStrain( k, q, stress, elasticStrain ); - elasticStrain[3] = m_newStress[k][q][3] / m_shearModulus[k]; - elasticStrain[4] = m_newStress[k][q][4] / m_shearModulus[k]; - elasticStrain[5] = m_newStress[k][q][5] / m_shearModulus[k]; } +GEOS_HOST_DEVICE +inline +void ElasticIsotropicUpdates::getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( & elasticStrainInc)[6] ) const +{ + + real64 stress[6] = + {m_newStress[k][q][0] - m_oldStress[k][q][0], m_newStress[k][q][1] - m_oldStress[k][q][1], m_newStress[k][q][2] - m_oldStress[k][q][2], m_newStress[k][q][3] - m_oldStress[k][q][3], + m_newStress[k][q][4] - m_oldStress[k][q][4], m_newStress[k][q][5] - m_oldStress[k][q][5]}; + + computeElasticStrain( k, q, stress, elasticStrainInc ); + +} GEOS_HOST_DEVICE inline diff --git a/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.hpp b/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.hpp index 4181e8e2013..01f36bf937f 100644 --- a/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.hpp +++ b/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.hpp @@ -115,6 +115,11 @@ class ElasticIsotropicPressureDependentUpdates : public SolidBaseUpdates localIndex const q, real64 ( &elasticStrain )[6] ) const override final; + GEOS_HOST_DEVICE + virtual void getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( &elasticStrainInc )[6] ) const override final; + GEOS_HOST_DEVICE virtual void viscousStateUpdate( localIndex const k, localIndex const q, @@ -223,6 +228,60 @@ void ElasticIsotropicPressureDependentUpdates::getElasticStrain( localIndex cons } +GEOS_HOST_DEVICE +inline +void ElasticIsotropicPressureDependentUpdates::getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( & elasticStrainInc)[6] ) const +{ + real64 const mu = m_shearModulus[k]; + real64 const p0 = m_refPressure; + real64 const eps_v0 = m_refStrainVol; + real64 const Cr = m_recompressionIndex[k]; + real64 deviator[6]{}; + real64 stress[6]{}; + real64 P; + real64 Q; + + LvArray::tensorOps::copy< 6 >( stress, m_newStress[k][q] ); + + twoInvariant::stressDecomposition( stress, + P, + Q, + deviator ); + + real64 elasticStrainVol = LvArray::math::log( P/p0 ) * Cr * (-1.0) + eps_v0; + real64 elasticStrainDev = Q/3./mu; + + twoInvariant::strainRecomposition( elasticStrainVol, + elasticStrainDev, + deviator, + elasticStrainInc ); + + real64 oldStrain[6]{}; + + LvArray::tensorOps::copy< 6 >( stress, m_oldStress[k][q] ); + + twoInvariant::stressDecomposition( stress, + P, + Q, + deviator ); + + elasticStrainVol = LvArray::math::log( P/p0 ) * Cr * (-1.0) + eps_v0; + elasticStrainDev = Q/3./mu; + + twoInvariant::strainRecomposition( elasticStrainVol, + elasticStrainDev, + deviator, + oldStrain ); + + for( localIndex i = 0; i<6; ++i ) + { + elasticStrainInc[i] -= oldStrain[i]; + } +} + + GEOS_HOST_DEVICE inline void ElasticIsotropicPressureDependentUpdates::smallStrainUpdate( localIndex const k, diff --git a/src/coreComponents/constitutive/solid/ElasticOrthotropic.hpp b/src/coreComponents/constitutive/solid/ElasticOrthotropic.hpp index 4445b88cc12..49179c5a95a 100644 --- a/src/coreComponents/constitutive/solid/ElasticOrthotropic.hpp +++ b/src/coreComponents/constitutive/solid/ElasticOrthotropic.hpp @@ -147,6 +147,16 @@ class ElasticOrthotropicUpdates : public SolidBaseUpdates real64 ( &stress )[6], DiscretizationOps & stiffness ) const final; + GEOS_HOST_DEVICE + virtual void getElasticStrain( localIndex const k, + localIndex const q, + real64 ( &elasticStrain )[6] ) const override final; + + GEOS_HOST_DEVICE + virtual void getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( &elasticStrainInc )[6] ) const override final; + // miscellaneous getters GEOS_HOST_DEVICE @@ -162,6 +172,13 @@ class ElasticOrthotropicUpdates : public SolidBaseUpdates return LvArray::math::max( LvArray::math::max( m_c44[k], m_c55[k] ), m_c66[k] ); } +protected: + GEOS_HOST_DEVICE + virtual void computeElasticStrain( localIndex const k, + localIndex const q, + real64 const (&stress)[6], + real64 ( &elasticStrain )[6] ) const; + private: /// A reference to the ArrayView holding c11 for each element. arrayView1d< real64 const > const m_c11; @@ -219,6 +236,64 @@ void ElasticOrthotropicUpdates::getElasticStiffness( localIndex const k, stiffness[5][5] = m_c66[k]; } + +GEOS_HOST_DEVICE +inline +void ElasticOrthotropicUpdates::computeElasticStrain( localIndex const k, + localIndex const q, + real64 const (&stress)[6], + real64 ( & elasticStrain)[6] ) const +{ + + GEOS_UNUSED_VAR( q ); + + real64 const detC = m_c11[k]*(m_c22[k]*m_c33[k] - m_c23[k]*m_c23[k]) - m_c12[k]*(m_c12[k]*m_c33[k] - m_c23[k]*m_c13[k]) + m_c13[k]*(m_c12[k]*m_c23[k] - m_c22[k]*m_c13[k]); + + elasticStrain[0] = + ( (m_c22[k]*m_c33[k] - m_c23[k]*m_c23[k])*stress[0] + (m_c13[k]*m_c23[k] - m_c12[k]*m_c33[k])*stress[1] + (m_c12[k]*m_c23[k] - m_c13[k]*m_c22[k])*stress[2] ) / + detC; + elasticStrain[1] = + ( (m_c23[k]*m_c13[k] - m_c12[k]*m_c33[k])*stress[0] + (m_c11[k]*m_c33[k] - m_c13[k]*m_c13[k])*stress[1] + (m_c13[k]*m_c12[k] - m_c11[k]*m_c23[k])*stress[2] ) / + detC; + elasticStrain[2] = + ( (m_c12[k]*m_c23[k] - m_c22[k]*m_c13[k])*stress[0] + (m_c12[k]*m_c13[k] - m_c11[k]*m_c23[k])*stress[1] + (m_c11[k]*m_c22[k] - m_c12[k]*m_c12[k])*stress[2] ) / + detC; + + elasticStrain[3] = stress[3] / m_c44[k]; + elasticStrain[4] = stress[4] / m_c55[k]; + elasticStrain[5] = stress[5] / m_c66[k]; +} + + +GEOS_HOST_DEVICE +inline +void ElasticOrthotropicUpdates::getElasticStrain( localIndex const k, + localIndex const q, + real64 ( & elasticStrain)[6] ) const +{ + + real64 stress[6] = {m_newStress[k][q][0], m_newStress[k][q][1], m_newStress[k][q][2], m_newStress[k][q][3], m_newStress[k][q][4], m_newStress[k][q][5]}; + + computeElasticStrain( k, q, stress, elasticStrain ); + +} + +GEOS_HOST_DEVICE +inline +void ElasticOrthotropicUpdates::getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( & elasticStrainInc)[6] ) const +{ + + real64 stress[6] = + {m_newStress[k][q][0] - m_oldStress[k][q][0], m_newStress[k][q][1] - m_oldStress[k][q][1], m_newStress[k][q][2] - m_oldStress[k][q][2], m_newStress[k][q][3] - m_oldStress[k][q][3], + m_newStress[k][q][4] - m_oldStress[k][q][4], m_newStress[k][q][5] - m_oldStress[k][q][5]}; + + computeElasticStrain( k, q, stress, elasticStrainInc ); + +} + + inline GEOS_HOST_DEVICE void ElasticOrthotropicUpdates::smallStrainNoStateUpdate_StressOnly( localIndex const k, diff --git a/src/coreComponents/constitutive/solid/ElasticTransverseIsotropic.hpp b/src/coreComponents/constitutive/solid/ElasticTransverseIsotropic.hpp index f2c86d4439a..17fabe5479e 100644 --- a/src/coreComponents/constitutive/solid/ElasticTransverseIsotropic.hpp +++ b/src/coreComponents/constitutive/solid/ElasticTransverseIsotropic.hpp @@ -144,6 +144,16 @@ class ElasticTransverseIsotropicUpdates : public SolidBaseUpdates GEOS_HOST_DEVICE virtual void getElasticStiffness( localIndex const k, localIndex const q, real64 ( &stiffness )[6][6] ) const override final; + GEOS_HOST_DEVICE + virtual void getElasticStrain( localIndex const k, + localIndex const q, + real64 ( &elasticStrain )[6] ) const override final; + + GEOS_HOST_DEVICE + virtual void getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( &elasticStrainInc )[6] ) const override final; + /** * @brief Getter for apparent shear modulus. * @return reference to shear modulus that will be used for computing stabilization scalling parameter. @@ -155,6 +165,15 @@ class ElasticTransverseIsotropicUpdates : public SolidBaseUpdates } +protected: + + GEOS_HOST_DEVICE + virtual void computeElasticStrain( localIndex const k, + localIndex const q, + real64 const (&stress)[6], + real64 ( &elasticStrain )[6] ) const; + + private: /// A reference to the ArrayView holding c11 for each element. @@ -200,6 +219,57 @@ void ElasticTransverseIsotropicUpdates::getElasticStiffness( localIndex const k, stiffness[5][5] = m_c66[k]; } +GEOS_HOST_DEVICE +inline +void ElasticTransverseIsotropicUpdates::computeElasticStrain( localIndex const k, + localIndex const q, + real64 const (&stress)[6], + real64 ( & elasticStrain)[6] ) const +{ + GEOS_UNUSED_VAR( q ); + real64 const c12 = ( m_c11[k] - 2.0 * m_c66[k] ); + real64 const detC = m_c11[k]*(m_c11[k]*m_c33[k] - m_c13[k]*m_c13[k]) - c12*(c12*m_c33[k] - m_c13[k]*m_c13[k]) + m_c13[k]*(c12*m_c13[k] - m_c11[k]*m_c13[k]); + + elasticStrain[0] = + ( (m_c11[k]*m_c33[k] - m_c13[k]*m_c13[k])*stress[0] + (m_c13[k]*m_c13[k] - c12*m_c33[k])*stress[1] + (c12*m_c13[k] - m_c13[k]*m_c11[k])*stress[2] ) / detC; + elasticStrain[1] = + ( (m_c13[k]*m_c13[k] - c12*m_c33[k])*stress[0] + (m_c11[k]*m_c33[k] - m_c13[k]*m_c13[k])*stress[1] + (m_c13[k]*c12 - m_c11[k]*m_c13[k])*stress[2] ) / detC; + elasticStrain[2] = ( (c12*m_c13[k] - m_c11[k]*m_c13[k])*stress[0] + (c12*m_c13[k] - m_c11[k]*m_c13[k])*stress[1] + (m_c11[k]*m_c11[k] - c12*c12)*stress[2] ) / detC; + + elasticStrain[3] = stress[3] / m_c44[k]; + elasticStrain[4] = stress[4] / m_c44[k]; + elasticStrain[5] = stress[5] / m_c66[k]; +} + + +GEOS_HOST_DEVICE +inline +void ElasticTransverseIsotropicUpdates::getElasticStrain( localIndex const k, + localIndex const q, + real64 ( & elasticStrain)[6] ) const +{ + + real64 stress[6] = {m_newStress[k][q][0], m_newStress[k][q][1], m_newStress[k][q][2], m_newStress[k][q][3], m_newStress[k][q][4], m_newStress[k][q][5]}; + + computeElasticStrain( k, q, stress, elasticStrain ); + +} + +GEOS_HOST_DEVICE +inline +void ElasticTransverseIsotropicUpdates::getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( & elasticStrainInc)[6] ) const +{ + + real64 stress[6] = + {m_newStress[k][q][0] - m_oldStress[k][q][0], m_newStress[k][q][1] - m_oldStress[k][q][1], m_newStress[k][q][2] - m_oldStress[k][q][2], m_newStress[k][q][3] - m_oldStress[k][q][3], + m_newStress[k][q][4] - m_oldStress[k][q][4], m_newStress[k][q][5] - m_oldStress[k][q][5]}; + + computeElasticStrain( k, q, stress, elasticStrainInc ); + +} + inline GEOS_HOST_DEVICE void ElasticTransverseIsotropicUpdates::smallStrainNoStateUpdate_StressOnly( localIndex const k, diff --git a/src/coreComponents/constitutive/solid/SolidBase.hpp b/src/coreComponents/constitutive/solid/SolidBase.hpp index 24b05eea71a..b56bd38b53a 100644 --- a/src/coreComponents/constitutive/solid/SolidBase.hpp +++ b/src/coreComponents/constitutive/solid/SolidBase.hpp @@ -337,6 +337,24 @@ class SolidBaseUpdates GEOS_ERROR( "getElasticStrain() not implemented for this model" ); } + /** + * @brief Return the current elastic strain increment at a given material point (small-strain interface) + * + * @param k the element inex + * @param q the quadrature index + * @param elasticStrainInc Current elastic strain increment + */ + GEOS_HOST_DEVICE + virtual void getElasticStrainInc( localIndex const k, + localIndex const q, + real64 ( & elasticStrainInc )[6] ) const + { + GEOS_UNUSED_VAR( k ); + GEOS_UNUSED_VAR( q ); + GEOS_UNUSED_VAR( elasticStrainInc ); + GEOS_ERROR( "getElasticStrainInc() of SolidBase was called." ); + } + /** * @brief Perform a viscous (rate-dependent) state update * diff --git a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsFields.hpp b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsFields.hpp index 68117918b7f..8ffee2ab6f3 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsFields.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsFields.hpp @@ -87,6 +87,14 @@ DECLARE_FIELD( strain, WRITE_AND_READ, "Average strain in cell" ); +DECLARE_FIELD( plasticStrain, + "plasticStrain", + array2dLayoutStrain, + 0, + LEVEL_0, + WRITE_AND_READ, + "Average plastic strain in cell" ); + DECLARE_FIELD( incrementalBubbleDisplacement, "incrementalBubbleDisplacement", array2d< real64 >, diff --git a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp index 70cb8b3c56e..fa5c1685db3 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp @@ -162,6 +162,8 @@ void SolidMechanicsLagrangianFEM::registerDataOnMesh( Group & meshBodies ) setConstitutiveNamesCallSuper( subRegion ); subRegion.registerField< solidMechanics::strain >( getName() ).setDimLabels( 1, voightLabels ).reference().resizeDimension< 1 >( 6 ); + subRegion.registerField< solidMechanics::plasticStrain >( getName() ).setDimLabels( 1, voightLabels ).reference().resizeDimension< 1 >( 6 ); + } ); NodeManager & nodes = meshLevel.getNodeManager(); @@ -455,6 +457,7 @@ void SolidMechanicsLagrangianFEM::initializePostInitialConditionsPreSubGroups() m_targetNodes.insert( m_nonSendOrReceiveNodes.begin(), m_nonSendOrReceiveNodes.end() ); + } ); } ); @@ -946,23 +949,36 @@ void SolidMechanicsLagrangianFEM::implicitStepComplete( real64 const & GEOS_UNUS { string const & solidMaterialName = subRegion.template getReference< string >( viewKeyStruct::solidMaterialNamesString() ); SolidBase & constitutiveRelation = getConstitutiveModel< SolidBase >( subRegion, solidMaterialName ); - constitutiveRelation.saveConvergedState(); + solidMechanics::arrayView2dLayoutStrain strain = subRegion.getField< solidMechanics::strain >(); + solidMechanics::arrayView2dLayoutStrain plasticStrain = subRegion.getField< solidMechanics::plasticStrain >(); - finiteElement::FiniteElementBase & subRegionFE = subRegion.template getReference< finiteElement::FiniteElementBase >( this->getDiscretizationName()); - finiteElement::FiniteElementDispatchHandler< BASE_FE_TYPES >::dispatch3D( subRegionFE, [&] ( auto const finiteElement ) + constitutive::ConstitutivePassThru< SolidBase >::execute( constitutiveRelation, [&] ( auto & solidModel ) { - using FE_TYPE = decltype( finiteElement ); - AverageStrainOverQuadraturePointsKernelFactory::createAndLaunch< CellElementSubRegion, FE_TYPE, parallelDevicePolicy<> >( nodeManager, - mesh.getEdgeManager(), - mesh.getFaceManager(), - subRegion, - finiteElement, - disp, - strain ); + + using SOLID_TYPE = TYPEOFREF( solidModel ); + + finiteElement::FiniteElementBase & subRegionFE = subRegion.template getReference< finiteElement::FiniteElementBase >( this->getDiscretizationName()); + finiteElement::FiniteElementDispatchHandler< BASE_FE_TYPES >::dispatch3D( subRegionFE, [&] ( auto const finiteElement ) + { + using FE_TYPE = decltype( finiteElement ); + AverageStrainOverQuadraturePointsKernelFactory::createAndLaunch< FE_TYPE, SOLID_TYPE, parallelDevicePolicy<> >( nodeManager, + mesh.getEdgeManager(), + mesh.getFaceManager(), + subRegion, + finiteElement, + solidModel, + disp, + uhat, + strain, + plasticStrain ); + } ); + + } ); + constitutiveRelation.saveConvergedState(); } ); } ); diff --git a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp index 764d86d8f38..083047a880e 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp @@ -98,6 +98,16 @@ bool SolidMechanicsStateReset::execute( real64 const time_n, } nodeManager.getField< solidMechanics::totalDisplacement >().zero(); nodeManager.getField< solidMechanics::incrementalDisplacement >().zero(); + + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< CellElementSubRegion >( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + subRegion.getField< solidMechanics::strain >().zero(); + subRegion.getField< solidMechanics::plasticStrain >().zero(); + } ); + } // Option 2: enable / disable inelastic behavior diff --git a/src/coreComponents/physicsSolvers/solidMechanics/kernels/StrainHelper.hpp b/src/coreComponents/physicsSolvers/solidMechanics/kernels/StrainHelper.hpp index d1c5567eff4..faf51f89351 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/kernels/StrainHelper.hpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/kernels/StrainHelper.hpp @@ -23,6 +23,7 @@ #include "common/DataTypes.hpp" #include "common/GEOS_RAJA_Interface.hpp" #include "finiteElement/FiniteElementDispatch.hpp" +#include "constitutive/ConstitutivePassThru.hpp" #include "mesh/CellElementSubRegion.hpp" #include "mesh/utilities/AverageOverQuadraturePointsKernel.hpp" #include "physicsSolvers/solidMechanics/SolidMechanicsFields.hpp" @@ -33,17 +34,18 @@ namespace geos * @class AverageStrainOverQuadraturePoints * @tparam SUBREGION_TYPE the subRegion type * @tparam FE_TYPE the finite element type + * @tparam SOLID_TYPE the solid mechanics constitutuve type */ -template< typename SUBREGION_TYPE, - typename FE_TYPE > +template< typename FE_TYPE, + typename SOLID_TYPE > class AverageStrainOverQuadraturePoints : - public AverageOverQuadraturePointsBase< SUBREGION_TYPE, + public AverageOverQuadraturePointsBase< CellElementSubRegion, FE_TYPE > { public: /// Alias for the base class; - using Base = AverageOverQuadraturePointsBase< SUBREGION_TYPE, + using Base = AverageOverQuadraturePointsBase< CellElementSubRegion, FE_TYPE >; using Base::m_elementVolume; @@ -63,24 +65,31 @@ class AverageStrainOverQuadraturePoints : AverageStrainOverQuadraturePoints( NodeManager & nodeManager, EdgeManager const & edgeManager, FaceManager const & faceManager, - SUBREGION_TYPE const & elementSubRegion, + CellElementSubRegion const & elementSubRegion, FE_TYPE const & finiteElementSpace, + SOLID_TYPE const & solidModel, fields::solidMechanics::arrayViewConst2dLayoutTotalDisplacement const displacement, - fields::solidMechanics::arrayView2dLayoutStrain const avgStrain ): + fields::solidMechanics::arrayViewConst2dLayoutIncrDisplacement const displacementInc, + fields::solidMechanics::arrayView2dLayoutStrain const avgStrain, + fields::solidMechanics::arrayView2dLayoutStrain const avgPlasticStrain ): Base( nodeManager, edgeManager, faceManager, elementSubRegion, finiteElementSpace ), + m_solidUpdate( solidModel.createKernelUpdates()), m_displacement( displacement ), - m_avgStrain( avgStrain ) + m_displacementInc( displacementInc ), + m_avgStrain( avgStrain ), + m_avgPlasticStrain( avgPlasticStrain ) {} /** * @copydoc finiteElement::KernelBase::StackVariables */ struct StackVariables : Base::StackVariables - {real64 uLocal[FE_TYPE::maxSupportPoints][3]; }; + {real64 uLocal[FE_TYPE::maxSupportPoints][3]; + real64 uHatLocal[FE_TYPE::maxSupportPoints][3]; }; /** * @brief Performs the setup phase for the kernel. @@ -99,12 +108,14 @@ class AverageStrainOverQuadraturePoints : for( int i = 0; i < 3; ++i ) { stack.uLocal[a][i] = m_displacement[localNodeIndex][i]; + stack.uHatLocal[a][i] = m_displacementInc[localNodeIndex][i]; } } for( int icomp = 0; icomp < 6; ++icomp ) { m_avgStrain[k][icomp] = 0.0; + //m_avgPlasticStrain[k][icomp] = 0.0; } } @@ -124,11 +135,26 @@ class AverageStrainOverQuadraturePoints : real64 dNdX[ FE_TYPE::maxSupportPoints ][3]; real64 const detJxW = m_finiteElementSpace.template getGradN< FE_TYPE >( k, q, stack.xLocal, stack.feStack, dNdX ); real64 strain[6] = {0.0}; + real64 strainInc[6] = {0.0}; FE_TYPE::symmetricGradient( dNdX, stack.uLocal, strain ); + FE_TYPE::symmetricGradient( dNdX, stack.uHatLocal, strainInc ); + + real64 elasticStrainInc[6] = {0.0}; + m_solidUpdate.getElasticStrainInc( k, q, elasticStrainInc ); + + real64 conversionFactor[6] = {1.0, 1.0, 1.0, 0.5, 0.5, 0.5}; // used for converting from engineering shear to tensor shear for( int icomp = 0; icomp < 6; ++icomp ) { - m_avgStrain[k][icomp] += detJxW*strain[icomp]/m_elementVolume[k]; + m_avgStrain[k][icomp] += conversionFactor[icomp]*detJxW*strain[icomp]/m_elementVolume[k]; + + // This is a hack to handle boundary conditions such as those seen in plane-strain wellbore problems + // Essentially, if bcs are constraining the strain (and thus total displacement), we do not accumulate any plastic strain (regardless + // of stresses in material law) + if( std::abs( strainInc[icomp] ) > 1.0e-8 ) + { + m_avgPlasticStrain[k][icomp] += conversionFactor[icomp]*detJxW*(strainInc[icomp] - elasticStrainInc[icomp])/m_elementVolume[k]; + } } } @@ -160,12 +186,21 @@ class AverageStrainOverQuadraturePoints : protected: + /// The material + typename SOLID_TYPE::KernelWrapper const m_solidUpdate; + /// The displacement solution fields::solidMechanics::arrayViewConst2dLayoutTotalDisplacement const m_displacement; + /// The displacement increment + fields::solidMechanics::arrayViewConst2dLayoutIncrDisplacement const m_displacementInc; + /// The average strain fields::solidMechanics::arrayView2dLayoutStrain const m_avgStrain; + /// The average plastic strain + fields::solidMechanics::arrayView2dLayoutStrain const m_avgPlasticStrain; + }; @@ -182,6 +217,7 @@ class AverageStrainOverQuadraturePointsKernelFactory * @brief Create a new kernel and launch * @tparam SUBREGION_TYPE the subRegion type * @tparam FE_TYPE the finite element type + * @tparam SOLID_TYPE the constitutive type * @tparam POLICY the kernel policy * @param nodeManager the node manager * @param edgeManager the edge manager @@ -191,23 +227,26 @@ class AverageStrainOverQuadraturePointsKernelFactory * @param property the property at quadrature points * @param averageProperty the property averaged over quadrature points */ - template< typename SUBREGION_TYPE, - typename FE_TYPE, + template< typename FE_TYPE, + typename SOLID_TYPE, typename POLICY > static void createAndLaunch( NodeManager & nodeManager, EdgeManager const & edgeManager, FaceManager const & faceManager, - SUBREGION_TYPE const & elementSubRegion, + CellElementSubRegion const & elementSubRegion, FE_TYPE const & finiteElementSpace, + SOLID_TYPE const & solidModel, fields::solidMechanics::arrayViewConst2dLayoutTotalDisplacement const displacement, - fields::solidMechanics::arrayView2dLayoutStrain const avgStrain ) + fields::solidMechanics::arrayViewConst2dLayoutIncrDisplacement const displacementInc, + fields::solidMechanics::arrayView2dLayoutStrain const avgStrain, + fields::solidMechanics::arrayView2dLayoutStrain const avgPlasticStrain ) { - AverageStrainOverQuadraturePoints< SUBREGION_TYPE, FE_TYPE > + AverageStrainOverQuadraturePoints< FE_TYPE, SOLID_TYPE > kernel( nodeManager, edgeManager, faceManager, elementSubRegion, finiteElementSpace, - displacement, avgStrain ); + solidModel, displacement, displacementInc, avgStrain, avgPlasticStrain ); - AverageStrainOverQuadraturePoints< SUBREGION_TYPE, FE_TYPE >::template + AverageStrainOverQuadraturePoints< FE_TYPE, SOLID_TYPE >::template kernelLaunch< POLICY >( elementSubRegion.size(), kernel ); } }; From 907fb3f294fd89123da19ad9899530a8f62d91ea Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:32:44 -0800 Subject: [PATCH 3/3] fix: Feature/byer3/mass inj constraint fix (#3495) Co-authored-by: Pavel Tomin --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 + .../compositionalMultiphaseWell.ats | 16 ++ .../isothm_mass_inj_table.xml | 229 +++++++++++++++++ .../isothm_vol_inj_table.xml | 234 ++++++++++++++++++ .../wells/CompositionalMultiphaseWell.cpp | 29 ++- .../wells/CompositionalMultiphaseWell.hpp | 2 + .../fluidFlow/wells/WellControls.cpp | 5 + .../fluidFlow/wells/WellControls.hpp | 6 + .../CompositionalMultiphaseWellKernels.cpp | 26 +- .../CompositionalMultiphaseWellKernels.hpp | 2 + 11 files changed, 540 insertions(+), 15 deletions(-) create mode 100644 inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml create mode 100644 inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 6009de53427..746f223b649 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3384-9542-4e0f693 + baseline: integratedTests/baseline_integratedTests-pr3495-9552-257c87e allow_fail: all: '' streak: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index 26bf74a58a5..c5617ba8ed9 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 #3495 (2024-01-08) +===================== +Add missing logic to support switching from fixed mass rate injection rate constraint to max injection pressure. + PR #3384 (2024-01-07) ===================== Added plastic strain output. diff --git a/inputFiles/compositionalMultiphaseWell/compositionalMultiphaseWell.ats b/inputFiles/compositionalMultiphaseWell/compositionalMultiphaseWell.ats index ea1d810c064..16de5c4d90c 100644 --- a/inputFiles/compositionalMultiphaseWell/compositionalMultiphaseWell.ats +++ b/inputFiles/compositionalMultiphaseWell/compositionalMultiphaseWell.ats @@ -76,6 +76,22 @@ decks = [ partitions=[(1, 1, 1), (2, 2, 1)], restart_step=12, check_step=25, + restartcheck_params=RestartcheckParameters(**restartcheck_params)), + TestDeck( + name="isothm_mass_inj_table", + description= + "Isothermal mass injection constraint testing control switching", + partitions=[(1, 1, 1), (1, 2, 1)], + restart_step=24, + check_step=28, + restartcheck_params=RestartcheckParameters(**restartcheck_params)), + TestDeck( + name="isothm_vol_inj_table", + description= + "Isothermal vol injection constraint testing control switching, should have same results as isothm_mass_inj_table.xml", + partitions=[(1, 1, 1), (1, 2, 1)], + restart_step=24, + check_step=28, restartcheck_params=RestartcheckParameters(**restartcheck_params)) ] diff --git a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml new file mode 100644 index 00000000000..14076fab917 --- /dev/null +++ b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml new file mode 100644 index 00000000000..d39421e36fc --- /dev/null +++ b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 90f3a8677ec..b891467863d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -260,6 +260,8 @@ void CompositionalMultiphaseWell::registerDataOnMesh( Group & meshBodies ) wellControls.registerWrapper< real64 >( viewKeyStruct::massDensityString() ); + wellControls.registerWrapper< real64 >( viewKeyStruct::currentMassRateString() ); + // write rates output header // the rank that owns the reference well element is responsible if( m_writeCSV > 0 && subRegion.isLocallyOwned() ) @@ -452,6 +454,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n WellControls::Control const currentControl = wellControls.getControl(); real64 const & targetTotalRate = wellControls.getTargetTotalRate( time_n + dt ); real64 const & targetPhaseRate = wellControls.getTargetPhaseRate( time_n + dt ); + real64 const & targetMassRate = wellControls.getTargetMassRate( time_n + dt ); GEOS_THROW_IF( wellControls.isInjector() && currentControl == WellControls::Control::PHASEVOLRATE, "WellControls " << wellControls.getDataContext() << @@ -470,6 +473,18 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n "WellControls " << wellControls.getDataContext() << ": Target phase rate cannot be used for injectors", InputError ); + GEOS_THROW_IF( wellControls.isProducer() && !isZero( targetTotalRate ), + "WellControls " << wellControls.getDataContext() << + ": Target total rate cannot be used for producers", + InputError ); + GEOS_THROW_IF( wellControls.isProducer() && !isZero( targetMassRate ), + "WellControls " << wellControls.getDataContext() << + ": Target mass rate cannot be used for producers", + InputError ); + GEOS_THROW_IF( !m_useMass && !isZero( targetMassRate ), + "WellControls " << wellControls.getDataContext() << + ": Target mass rate cannot with useMass=0", + InputError ); // The user always provides positive rates, but these rates are later multiplied by -1 internally for producers GEOS_THROW_IF( wellControls.isProducer() && targetPhaseRate > 0.0, @@ -686,6 +701,10 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg real64 & currentTotalVolRate = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + + real64 & currentMassRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + arrayView1d< real64 > const & dCurrentTotalVolRate = wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentTotalVolRateString() ); @@ -721,6 +740,7 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg dCurrentTotalVolRate, currentPhaseVolRate, dCurrentPhaseVolRate, + ¤tMassRate, &iwelemRef, &logLevel, &wellControlsName, @@ -757,7 +777,8 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg // Step 2: update the total volume rate real64 const currentTotalRate = connRate[iwelemRef]; - + // Assumes useMass is true + currentMassRate = currentTotalRate; // Step 2.1: compute the inverse of the total density and derivatives massDensity = totalDens[iwelemRef][0]; real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; @@ -1959,6 +1980,12 @@ void CompositionalMultiphaseWell::assemblePressureRelations( real64 const & time GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::WellControl, GEOS_FMT( "Control switch for well {} from BHP constraint to phase volumetric rate constraint", subRegion.getName() ) ); } + else if( wellControls.getInputControl() == WellControls::Control::MASSRATE ) + { + wellControls.switchToMassRateControl( wellControls.getTargetMassRate( timeAtEndOfStep ) ); + GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::WellControl, + GEOS_FMT( "Control switch for well {} from BHP constraint to mass rate constraint", subRegion.getName()) ); + } else { wellControls.switchToTotalRateControl( wellControls.getTargetTotalRate( timeAtEndOfStep ) ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index aa70d4f4507..72614596376 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -296,6 +296,8 @@ class CompositionalMultiphaseWell : public WellSolverBase static constexpr char const * currentTotalVolRateString() { return "currentTotalVolumetricRate"; } static constexpr char const * dCurrentTotalVolRateString() { return "dCurrentTotalVolumetricRate"; } + static constexpr char const * currentMassRateString() { return "currentMassRate"; } + static constexpr char const * dCurrentTotalVolRate_dPresString() { return "dCurrentTotalVolumetricRate_dPres"; } static constexpr char const * dCurrentTotalVolRate_dCompDensString() { return "dCurrentTotalVolumetricRate_dCompDens"; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 7ce65b6cbec..47877476c2f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -71,27 +71,32 @@ WellControls::WellControls( string const & name, Group * const parent ) registerWrapper( viewKeyStruct::targetBHPString(), &m_targetBHP ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Target bottom-hole pressure [Pa]" ); registerWrapper( viewKeyStruct::targetTotalRateString(), &m_targetTotalRate ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Target total volumetric rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); registerWrapper( viewKeyStruct::targetPhaseRateString(), &m_targetPhaseRate ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Target phase volumetric rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); registerWrapper( viewKeyStruct::targetMassRateString(), &m_targetMassRate ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Target Mass Rate rate ( [kg^3/s])" ); registerWrapper( viewKeyStruct::targetPhaseNameString(), &m_targetPhaseName ). setRTTypeName( rtTypes::CustomTypes::groupNameRef ). setDefaultValue( "" ). setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Name of the target phase" ); registerWrapper( viewKeyStruct::refElevString(), &m_refElevation ). diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 3335b7d98dc..9e202096385 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -149,6 +149,12 @@ class WellControls : public dataRepository::Group */ Control getControl() const { return m_currentControl; } + /** + * @brief Get the input control type for the well. + * @return the Control enum enforced at the well + */ + Control getInputControl() const { return m_inputControl; } + /** * @brief Getter for the reference elevation where the BHP control is enforced * @return the reference elevation diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 42ec6911080..01fb94d2e72 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -37,6 +37,7 @@ inline void ControlEquationHelper:: switchControl( bool const isProducer, + WellControls::Control const & inputControl, WellControls::Control const & currentControl, integer const phasePhaseIndex, real64 const & targetBHP, @@ -46,6 +47,7 @@ ControlEquationHelper:: real64 const & currentBHP, arrayView1d< real64 const > const & currentPhaseVolRate, real64 const & currentTotalVolRate, + real64 const & currentMassRate, WellControls::Control & newControl ) { // if isViable is true at the end of the following checks, no need to switch @@ -58,7 +60,7 @@ ControlEquationHelper:: // Currently, the available constraints are: // - Producer: BHP, PHASEVOLRATE - // - Injector: BHP, TOTALVOLRATE + // - Injector: BHP, TOTALVOLRATE, MASSRATE // TODO: support GRAT, WRAT, LIQUID for producers and check if any of the active constraint is violated @@ -71,6 +73,10 @@ ControlEquationHelper:: controlIsViable = ( LvArray::math::abs( currentPhaseVolRate[phasePhaseIndex] ) <= LvArray::math::abs( targetPhaseRate ) ); } // the control is viable if the reference total rate is below the max rate for injectors + else if( inputControl == WellControls::Control::MASSRATE ) + { + controlIsViable = ( LvArray::math::abs( currentMassRate ) <= LvArray::math::abs( targetMassRate ) ); + } else { controlIsViable = ( LvArray::math::abs( currentTotalVolRate ) <= LvArray::math::abs( targetTotalRate ) ); @@ -219,17 +225,6 @@ ControlEquationHelper:: if constexpr ( IS_THERMAL ) dControlEqn[COFFSET_WJ::dT] = massDensity*dCurrentTotalVolRate[COFFSET_WJ::dT]; } - // Total mass rate control - else if( currentControl == WellControls::Control::MASSRATE ) - { - controlEqn = massDensity*currentTotalVolRate - targetMassRate; - dControlEqn[COFFSET_WJ::dP] = massDensity*dCurrentTotalVolRate[COFFSET_WJ::dP]; - dControlEqn[COFFSET_WJ::dQ] = massDensity*dCurrentTotalVolRate[COFFSET_WJ::dQ]; - for( integer ic = 0; ic < NC; ++ic ) - { - dControlEqn[COFFSET_WJ::dC+ic] = massDensity*dCurrentTotalVolRate[COFFSET_WJ::dC+ic]; - } - } else { GEOS_ERROR( "This constraint is not supported in CompositionalMultiphaseWell" ); @@ -323,6 +318,7 @@ PressureRelationKernel:: // static well control data bool const isProducer = wellControls.isProducer(); WellControls::Control const currentControl = wellControls.getControl(); + WellControls::Control const inputControl = wellControls.getInputControl(); real64 const targetBHP = wellControls.getTargetBHP( timeAtEndOfStep ); real64 const targetTotalRate = wellControls.getTargetTotalRate( timeAtEndOfStep ); real64 const targetPhaseRate = wellControls.getTargetPhaseRate( timeAtEndOfStep ); @@ -344,6 +340,9 @@ PressureRelationKernel:: arrayView1d< real64 const > const & dCurrentTotalVolRate = wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentTotalVolRateString() ); + real64 const & currentMassRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + real64 const & massDensity = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); @@ -358,6 +357,7 @@ PressureRelationKernel:: { WellControls::Control newControl = currentControl; ControlEquationHelper::switchControl( isProducer, + inputControl, currentControl, targetPhaseIndex, targetBHP, @@ -367,6 +367,7 @@ PressureRelationKernel:: currentBHP, currentPhaseVolRate, currentTotalVolRate, + currentMassRate, newControl ); if( currentControl != newControl ) { @@ -737,7 +738,6 @@ RateInitializationKernel:: else if( control == WellControls::Control::MASSRATE ) { connRate[iwelem] = targetMassRate; - connRate[iwelem] = targetMassRate* totalDens[iwelem][0]; } else { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index aae86fcf48c..c2e9078ba47 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -134,6 +134,7 @@ struct ControlEquationHelper static void switchControl( bool const isProducer, + WellControls::Control const & inputControl, WellControls::Control const & currentControl, integer const phasePhaseIndex, real64 const & targetBHP, @@ -143,6 +144,7 @@ struct ControlEquationHelper real64 const & currentBHP, arrayView1d< real64 const > const & currentPhaseVolRate, real64 const & currentTotalVolRate, + real64 const & currentMassRate, WellControls::Control & newControl ); template< integer NC, integer IS_THERMAL >